简短的问题
直到并包括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中?
Howard Hinnant的date library是C ++ 20即将推出的产品。它是通过p0355r4提出并于2017年11月批准用于C ++ 20.它是否是线程安全的?不幸的是,文件和提案似乎都不清楚。但是,像get_tzdb_list
这样的某些功能被明确地说具有“线程安全性”。你最好的选择是在gitter聊天中询问Hinnant自己。但是,在Why is there no C++11 threadsafe alternative to std::localtime and std::gmtime?中的讨论似乎暗示它是线程安全的(即使它从未明确说过)。作为Nicol Bolas points out,您可以将其包裹在互斥锁之后。
如果不是,您可以再次获得数据竞争,从而获得未定义的行为。如果您正在编写大型项目,其中编码工作被分成团队,您必须不断提醒每个人他们不应该(!)使用C ++标准提供的功能,而是使用您自己的包装器(或冒险未定义的行为) 。
在浅层,这是代码审查的目的。 Facebook对初级开发人员有这个问题,他们一遍又一遍地犯同样的错误。如果你的团队有“奇怪的反复出现的错误”,你需要以某种方式解决它(比如在linter中加入检查:Clang会浮现在脑海中)。
在更直接的层面上,Google就是其中的缩影。他们遇到的问题是使用旧的COW实现string
并切换到基于SSO的string
。但是,因为他们依赖于使用基于COW的string
的第三方库,他们需要在他们的代码库中支持这两者。告诉开发人员使用Google包装器是徒劳的。开发人员提出的解决方案是使用inline namespaces
的hack。有点极端,但如果你正在处理类似的大型代码库,它可以做到这一点。