13

简短的问题

直到并包括 C++17,C++ 都没有提供线程安全的方法来获取当前时间或日期。这会在 C++20 中修复吗?

长问题

获取当前时间和日期的唯一可移植方法是使用 std::gmtime 或 std::localtime 函数。C 早期的残余,这些函数将自实现定义的纪元以来的给定时间转换为日历时间(例如,1515153600 转换为 2018 年 1 月 5 日星期五 12:00:00 GMT)。然而,唯一的缺点是这些函数返回一个指向内部静态变量的指针并且不是线程安全的。更糟糕的是,这个静态变量可能被所有相关函数共享,例如 std::gmtime、std::localtime 和 std::ctime,并且可能在每次调用这些函数时被覆盖。因此,如果您正在使用线程并希望定期检查您冒着数据竞争和未定义行为的风险的时间。

显然,当前的标准在这方面被打破了。C++ 标准委员会是否有任何努力来解决这种情况,这有多大可能包含在 C++20 中?

4

1 回答 1

12

Howard Hinnant 的日期库 C++20 的未来。它是通过p0355r4提出的,并于 2017 年 11 月批准用于 C++20。它是线程安全的吗?不幸的是,文档和提案似乎都不清楚这一点。但是,某些功能,如get_tzdb_list明确表示具有“线程安全”。您最好的选择是在gitter聊天中询问 Hinnant 本人。但是,为什么没有 C++11 线程安全替代 std::localtime 和 std::gmtime 中的讨论?似乎表明它是线程安全的(即使它从未明确说过)。正如 Nicol Bolas指出的那样,您可以将其包装在互斥体后面。

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

在浅层次上,这就是代码审查的目的。Facebook对初级开发人员有这个问题,他们不断地重复同样的错误。如果您的团队有“奇怪地反复出现的错误”,您需要以某种方式解决它(例如向 linter 添加检查:想到 Clang)。

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

于 2018-01-05T02:31:35.883 回答