0

I've currently been playing around with concurrent objects, based on Herb Sutter's presentation. I'm currently using Visual Studio 2012 with November CTP (could not check the stuff below in another way, Clang doesn't like class members in decltypes, g++ did not like anything on Windows).

Doing so, I've faced a curious bug with a thread-id being -1. Consider the following code:

__workerThread([=]() -> void {    
    std::cerr << std::endl; 
    while (!__done) 
    { 
        this->__innerqueue.pop()(); 
    }    
})

It's just the initialization of a std::thread with a lambda function - nothing spectacular, I thought. But without the first line that forces a call to std::cerr (no optimization), this thread's id appears to be -1 (due to the debugger), while otherwise, it's like it should be.

The problem with this thread ID occurs when executing

std::unique_lock<std::mutex> lock(this->__accessMutex);

inside the message-queue, since it crashes somewhere in the lower APIs (mutex.c).

Has anyone got an idea what may cause this curious behavior ? Adding the call to std::cerr is just a nasty workaround for the moment, and I'd like to get rid of it ...

You can find the full source at Github if you want to play around with it.

Praetorian
  • 106,671
  • 19
  • 240
  • 328
DorianGrey
  • 45
  • 5
  • 5
    FYI, identifiers containing adjacent underscores are reserved by the implementation. – Praetorian Feb 19 '13 at 18:58
  • Have you tried to call `get_id()`? The `id` of an `std::thread` may even be generated on-demand AFAIK. – Andy Prowl Feb 19 '13 at 19:08
  • I don't think many people will want to go to Github to look at code. Can you minimize the code and post it here? – GManNickG Feb 19 '13 at 19:51
  • The fact that `__done` is not atomic nor protected by a memory barrier is definitely a problem, but I don't know that it's the particular problem that you see manifesting... – ildjarn Feb 19 '13 at 23:28
  • @Praetorian I know that, but at the moment, there is no relevant conflict. Suppose I've been working with python too much... @AndyProwl I did that before, yes. Only calling it does not prevent the error, but using it with `std::cout` or `std::cerr` does. Optimization stuff, I suppose. – DorianGrey Feb 20 '13 at 11:25
  • @GManNickG The code snippets I've mentioned are as small as possible. I cannot cut down the full source to post something compilable without changing the intentions, which may cause misleading distractions during runtime. – DorianGrey Feb 20 '13 at 11:32

1 Answers1

3

It looks like an initializer problem. The thread runs before the concurrent queue is fully created (a race). The std::cerr probably delays the thread just long enough to make it work.

try swapping the two lines:

std::thread __workerThread;
mutable concurrent::queue<std::function<void()>, std::queue> __innerqueue;

Swapping should create the __innerqueue before the thread and it should work as advertised.

Tyler Jandreau
  • 4,245
  • 1
  • 22
  • 47
Robostyle
  • 46
  • 1