在C++ 20中获取当前日期/时间是否是线程安全的?

Lom*_*mos 12 c++ time datetime date c++20

简短的问题

在C++ 17之前,C++没有提供线程安全的方式来获取当前时间或日期.这将在C++ 20中修复吗?

长问题

获取当前时间和日期的唯一可移植方法是使用std :: gmtime或std :: localtime函数.从C的早期开始的遗留物,这些函数将实施定义的时期以来的给定时间转换为日历时间(例如,1515153600到Fri,2018年1月5日,格林威治标准时间12:00:00).然而,唯一的缺点是这些函数返回一个指向内部静态变量的指针,而不是线程安全的.更糟糕的是,这个静态变量可能由所有相关函数共享,例如std :: gmtime,std :: localtime和std :: ctime,并且可能在每次调用任何这些函数时被覆盖.因此,如果您正在使用线程并希望定期检查数据争用和未定义行为的风险.

显然,目前的标准在这方面被打破.C++标准委员会是否有任何努力来解决这种情况以及这种情况在C++ 20中的可能性有多大?

use*_*101 11

Howard Hinnant的日期库 C++ 20即将推出的日期库.它是通过p0355r4提出的,并于2017年11月批准用于C++ 20.它是否是线程安全的?不幸的是,文件和提案似乎都不清楚.但是,某些功能get_tzdb_list明确表示具有"线程安全性".你最好的选择是在聊天中询问Hinnant自己.但是,讨论为什么没有C++ 11线程安全替代std :: localtime和std :: gmtime?似乎暗示它是线程安全的(即使它从未明确说过).正如Nicol Bolas 指出的那样,你可以将它包装在互斥锁之后.

如果不是,您可以再次获得数据竞争,从而获得未定义的行为.如果您正在编写大型项目,其中编码工作被分成团队,您必须不断提醒每个人他们不应该(!)使用C++标准提供的功能,而是使用您自己的包装器(或冒险未定义的行为) .

在浅层,这是代码审查的目的.Facebook为初级开发人员提出了这个问题,他们一遍又一遍地制造相同的错误.如果你的团队有"奇怪的反复出现的错误",你需要以某种方式解决它(比如在linter中加入检查:Clang会浮现在脑海中).

在更直接的层面上,谷歌就是其中的缩影.他们遇到的问题是使用旧的COW实现string并切换到基于SSO string.但是,因为它们依赖于使用基于COW的第三方库string,所以它们需要在其代码库中同时支持这两种库.告诉开发人员使用Google包装器是徒劳的.开发人员提出的解决方案是使用hack inline namespaces.有点极端,但如果你正在处理类似的大型代码库,它可以做到这一点.

  • 嗨!(波浪 :-) ) .Howard Hinnant的日期库和随后的C++标准化提议是线程安全的!100%,除了明确记录为非线程安全的小角落情况.这些极端情况涉及在应用程序仍处于运行时在运行时更新TZ数据库(如果您的应用程序需要一次保持多个月并且需要更新的时区数据库).在后一种情况下,程序员可以使用工具以线程安全的方式遍历此更新,但它并非开箱即用.RTFM. (8认同)
  • 一个nit - Howard的库已被提议用于C++ 20,但尚未被采用.如果它没有被采纳,我会感到惊讶,但不是. (3认同)
  • 我赞成这个答案,因为它说的几乎就是我所说的.我说的一切都不是官方的.是的我参加了委员会.但不,我没有委员会的官方声音.没有人这样做,除了Herb发布的官方公告(并不是他的所有通讯都是正式公告).但感谢信任投票.:-) (2认同)
  • 更新:上周,Howard 的提案(基于他的库)被 C++2a(可能是 c++20)接受。 (2认同)