Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a C++11 condition variable in VS2012

I can't get code working reliably in a simple VS2012 console application consisting of a producer and consumer that uses a C++11 condition variable. I am aiming at producing a small reliable program (to use as the basis for a more complex program) that uses the 3 argument wait_for method or perhaps the wait_until method from code I have gathered at these websites:

condition_variable: wait_for, wait_until

I'd like to use the 3 argument wait_for with a predicate like below except it will need to use a class member variable to be most useful to me later. I am receiving "Access violation writing location 0x__" or "An invalid parameter was passed to a service or function" as errors after only about a minute of running.

Would steady_clock and the 2 argument wait_until be sufficient to replace the 3 argument wait_for? I've also tried this without success.

Can someone show how to get the code below to run indefinitely with no bugs or weird behavior with either changes in wall-clock time from daylight savings time or Internet time synchronizations?

A link to reliable sample code could be just as helpful.

// ConditionVariable.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <condition_variable>
#include <mutex>
#include <thread>
#include <iostream>
#include <queue>
#include <chrono>
#include <atomic>

#define TEST1

std::atomic<int> 
//int 
    qcount = 0; //= ATOMIC_VAR_INIT(0);

int _tmain(int argc, _TCHAR* argv[])
{
    std::queue<int> produced_nums;
    std::mutex m;
    std::condition_variable cond_var;
    bool notified = false;
    unsigned int count = 0;

    std::thread producer([&]() {
        int i = 0;
        while (1) {
            std::this_thread::sleep_for(std::chrono::microseconds(1500));
            std::unique_lock<std::mutex> lock(m);
            produced_nums.push(i);
            notified = true;
            qcount = produced_nums.size();
            cond_var.notify_one();
            i++;
        }   
        cond_var.notify_one();
    }); 

    std::thread consumer([&]() {
        std::unique_lock<std::mutex> lock(m);
        while (1) {
#ifdef TEST1
            // Version 1
            if (cond_var.wait_for(
                lock,
                std::chrono::microseconds(1000),
                [&]()->bool { return qcount != 0; }))
            {
                if ((count++ % 1000) == 0)
                    std::cout << "consuming " << produced_nums.front    () << '\n';
                produced_nums.pop();
                qcount = produced_nums.size();
                notified = false;
            }
#else
            // Version 2
            std::chrono::steady_clock::time_point timeout1 =
                std::chrono::steady_clock::now() +
                //std::chrono::system_clock::now() +
                std::chrono::milliseconds(1);

            while (qcount == 0)//(!notified)
            {
                if (cond_var.wait_until(lock, timeout1) == std::cv_status::timeout)
                    break;
            }

            if (qcount > 0)
            {
                if ((count++ % 1000) == 0)
                std::cout << "consuming " << produced_nums.front() << '\n';
                produced_nums.pop();
                qcount = produced_nums.size();
                notified = false;
            }
#endif
        }
    });

    while (1);
    return 0;
}

Visual Studio Desktop Express had 1 important update which it installed and Windows Update has no other important updates. I'm using Windows 7 32-bit.

like image 421
Edward Avatar asked Dec 13 '12 18:12

Edward


1 Answers

Sadly, this is actually a bug in VS2012's implementation of condition_variable, and the fix will not be patched in. You'll have to upgrade to VS2013 when it's released.

See:

http://connect.microsoft.com/VisualStudio/feedback/details/762560

like image 198
brendanw Avatar answered Oct 13 '22 21:10

brendanw