简体   繁体   中英

Concurrent std::call_once calls

Could please someone explain me why both of the threads in this program (when compiled using the compilers shipped with Visual Studio 2012/2013) are blocked until both std::call_once calls are executed? Another Visual Studio bug (given that it behaves as expected when compiled with GCC)? Can someone please come up with a workaround? Imagine all the pain I've been through to narrow the problem down and please, be merciful.

#include <chrono>
#include <iostream>
#include <mutex>
#include <thread>

namespace
{
    std::once_flag did_nothing;

    void do_nothing()
    { }

    void sleep_shorter_and_do_nothing_once()
    {
        std::this_thread::sleep_for(std::chrono::seconds(3));
        std::cout << "1\n";
        std::call_once(did_nothing, do_nothing);
        std::cout << "2\n";
    }

    std::once_flag sleeped_longer;

    void sleep_longer()
    {
        std::this_thread::sleep_for(std::chrono::seconds(10));
    }

    void sleep_longer_once()
    {
        std::cout << "3\n";
        std::call_once(sleeped_longer, sleep_longer);
        std::cout << "4\n";
    }
}

int main()
{
    std::thread t1(sleep_shorter_and_do_nothing_once);
    std::thread t2(sleep_longer_once);
    t1.join();
    t2.join();
    return 0;
}

To elaborate, it behaves as expected when compiled using GCC:

  • prints "3",
  • waits 3 seconds,
  • prints "1",
  • immediately prints "2",
  • waits another 6-7 seconds,
  • and prints "4".

When compiled using the compilers shipped with Visual Studio 2012/2013, it behaves like this:

  • prints "3",
  • waits 3 seconds,
  • prints "1",
  • waits another 6-7 seconds ,
  • and only then immediately prints "2" and "4" .

Clearly, it's a misbehavior. Or isn't it?

UPDATE: I cannot submit this as a Visual Studio bug, because my work account is for some reason "not authorized to submit feedback for this connection", whatever this means. I've got a reply from the Microsoft STL maintainer saying he'll hopefully investigate the issue at some time in the future.

我收到了Microsoft STL维护人员的回复,说该错误已在Visual Studio 2015中修复。

It prefers to be a misbehavior.
"The completion of an effective call to call_once on a once_flag object synchronizes with all subsequent calls to call_once on the same once_flag object." (N3242, 30.4.4.2-clause-3).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM