【发布时间】:2011-11-10 22:49:55
【问题描述】:
C++ 以strftime 定义时间格式化函数,这需要struct tm“分解时间”记录。但是,C 和 C++03 语言没有提供线程安全的方式来获取这样的记录;整个程序只有一位大师struct tm。
在 C++03 中,这或多或少是可以的,因为该语言不支持多线程;它仅支持支持多线程的平台,然后提供诸如 POSIX localtime_r 之类的设施。
C++11 还定义了新的时间实用程序,它与非分解的time_t 类型接口,是用于重新初始化全局struct tm 的类型。但是获得time_t 不是问题。
我是否遗漏了什么或者这项任务仍然需要依赖 POSIX?
编辑:这是一些解决方法代码。它保持与提供::localtime_r 的多线程环境和仅提供std::localtime 的单线程环境的兼容性。它也可以很容易地适应检查其他功能,例如posix::localtime_r 或::localtime_s 或what-have-you。
namespace query {
char localtime_r( ... );
struct has_localtime_r
{ enum { value = sizeof localtime_r( std::declval< std::time_t * >(), std::declval< std::tm * >() )
== sizeof( std::tm * ) }; };
template< bool available > struct safest_localtime {
static std::tm *call( std::time_t const *t, std::tm *r )
{ return localtime_r( t, r ); }
};
template<> struct safest_localtime< false > {
static std::tm *call( std::time_t const *t, std::tm *r )
{ return std::localtime( t ); }
};
}
std::tm *localtime( std::time_t const *t, std::tm *r )
{ return query::safest_localtime< query::has_localtime_r::value >().call( t, r ); }
【问题讨论】:
-
你不能把
localtime包装在一个使用互斥锁的函数中吗?还是其他重量更轻的锁?我看不到这里需要 POSIX。 -
@Nicol:是的,但这只有在没有其他人尝试做同样的事情时才是安全的。换句话说,它在程序中工作,而不是在库中。
-
但是他们会从线程代码中调用一个非线程安全的函数,所以他们会得到他们应得的。您可以只公开一个函数供他们使用,如果他们使用标准 C 函数,那么他们会得到未定义的行为。
-
@Nicol:什么?我正在编写一个无法向其用户提供此类限制的库。
-
@Nicol:我的库不是多线程的,但我希望它与多线程代码兼容。您建议使用互斥锁并致电
localtime正是您建议我告诉用户不要这样做的建议。我不能坚持认为我的互斥锁是localtime的the 互斥锁——库的功能是不相关的。无论如何,与互斥锁有关的任何事情都是错误的解决方案,因为我的代码绝不是多线程的,它只是线程安全的。