TNA*_*TNA 44 c++ thread-safety c++11 c++-chrono
在C++ 11中,你仍然需要使用std::localtime和std::gmtime作为间接来打印std::chrono::time_point.这些函数在C++ 11引入的多线程环境中使用是不安全的,因为它们返回一个指向内部静态结构的指针.这尤其令人讨厌,因为C++ 11引入了方便的功能std::put_time,由于同样的原因几乎无法使用.
为什么这么根本被打破或者我忽略了什么?
T.C*_*.C. 17
根据N2661,补充说<chrono>:
本文不提供日历服务,除了与C的最小映射
time_t.由于本文没有提出日期/时间库,也没有指定时期,因此它也没有解决闰秒问题.但是,日期/时间库会发现这是构建的良好基础.
本文未提出通用物理量库.
本文提出了一个坚实的基础,在未来,可以为一般的物理单元库提供兼容的起点.虽然这样一个未来的图书馆可能采取多种形式中的任何一种,但目前的提案远远没有实际成为一个物理单位图书馆.该提案是针对特定时间的,并且继续受到线程库的时间相关需求的推动.
该提议的主要目标是以易于使用,安全使用,高效且足够灵活的方式满足标准库线程API的需求,从而在10年甚至100年后不会过时.本提案中包含的每个功能都是出于特定原因而以实际用例为动机.那些属于"酷"类别的东西,或"听起来可能有用",或"非常有用但不需要此接口"的内容尚未包括在内.这些项目可能出现在其他提案中,并可能针对TR.
请注意,主要目标<chrono>是"满足标准库线程API的需求",这不需要日历服务.
Mat*_*son 11
localtime并且gmtime具有静态的内部存储,这意味着它们不是线程安全的(我们必须返回指向数据结构的指针,因此它必须动态分配,静态值或全局值 - 因为动态分配会泄漏内存,这不是一个合理的解决方案,这意味着它必须是一个全局变量或静态变量[理论上,可以在TLS中分配和存储,并使其成为线程安全的方式]).
大多数系统都有线程安全的替代品,但它们不是标准库的一部分.例如,Linux/Posix有localtime_r和gmtime_r,它为结果提供了额外的参数.例如,参见
http://pubs.opengroup.org/onlinepubs/7908799/xsh/gmtime.html
类似地,Microsoft库也具有gmtime_s重入性,并以类似的方式工作(将输出参数作为输入传递).请参阅http://msdn.microsoft.com/en-us/library/3stkd9be.aspx
至于为什么标准C++ 11库不使用这些功能?你必须问那些编写该规范的人 - 我希望它具有可移植性和便利性,但我并不完全确定.
没有线程安全替代方案std::localtime,std::gmtime因为您没有提出并在整个标准化过程中编组它.其他人也没有.
chrono唯一的日历代码是包装现有time_t功能的代码.标准化或编写新标准不属于chrono项目范围.执行此类标准化需要更多时间,更多工作,并添加更多依赖项.简单地包装每个time_t函数很简单,依赖性很少,而且很快.
他们狭隘地集中精力.他们成功地关注了他们所关注的事情.
我鼓励您开始工作<calendar>或加入此类工作,以便为其创建强大的日历API std.祝你好运!
如果您愿意使用免费的、开源的 3rd 方库,这里有一种以std::chrono::system_clock::time_pointUTC打印的方法:
#include "date.h"
#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono;
std::cout << system_clock::now() << " UTC\n";
}
Run Code Online (Sandbox Code Playgroud)
这是std::gmtime使用现代 C++ 语法的线程安全替代方案。
对于现代的、线程安全的std::localtime替换,您需要这个密切相关的更高级别的时区库,其语法如下所示:
#include "tz.h"
#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono;
std::cout << make_zoned(current_zone(), system_clock::now()) << "\n";
}
Run Code Online (Sandbox Code Playgroud)
这两者都将以您system_clock支持的任何精度输出,例如:
2016-07-05 10:03:01.608080 EDT
Run Code Online (Sandbox Code Playgroud)
(macOS 上的微秒)
这些库远远超出了一个gmtime和localtime替代。例如,您想查看儒略历中的当前日期吗?
#include "julian.h"
#include <iostream>
int
main()
{
using namespace std::chrono;
std::cout << julian::year_month_day(date::floor<date::days>(system_clock::now())) << "\n";
}
2016-06-22
Run Code Online (Sandbox Code Playgroud)
现在的 GPS 时间怎么样?
#include "tz.h"
#include <iostream>
int
main()
{
using namespace date;
std::cout << std::chrono::system_clock::now() << " UTC\n";
std::cout << gps_clock::now() << " GPS\n";
}
2016-07-05 14:13:02.138091 UTC
2016-07-05 14:13:19.138524 GPS
Run Code Online (Sandbox Code Playgroud)
https://github.com/HowardHinnant/date
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0355r0.html
更新
“date.h”和“tz.h”库现在在 C++2a 规范草案中,有非常小的变化,我们希望 'a' 是 '0'。它们将位于标题<chrono>和下方namespace std::chrono(并且不会有date namespace)。