Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

boost::scoped_lock not working with local static variable?

I made the following sample program to play with boost threading:

#pragma once
#include "boost\thread\mutex.hpp"
#include <iostream>

class ThreadWorker
{
public:
    ThreadWorker() {}
    virtual ~ThreadWorker() {}

    static void FirstCount(int threadId)
    {
        boost::mutex::scoped_lock(mutex_);
        static int i = 0;

        for(i = 1; i <= 30; i++)
        {
            std::cout << i << ": Hi from thread:  " << threadId << std::endl;
        }

    }

private:
    boost::mutex mutex_;
};

main class:

// ThreadTest.cpp
#include "stdafx.h"
#include "boost\thread\thread.hpp"
#include "ThreadWorker.h"

int _tmain(int argc, _TCHAR* argv[])
{
    boost::thread thread1(&ThreadWorker::FirstCount, 1);
    boost::thread thread2(&ThreadWorker::FirstCount, 2);
    boost::thread thread3(&ThreadWorker::FirstCount, 3);

    thread1.join();
    thread2.join();
    thread3.join();

    std::string input;
    std::cout << "Press <enter> to finish...\n";
    std::getline( std::cin, input );
    return 0;
}

When I run this I get the following output:

1: Hi from thread:  1
1: Hi from thread:  3
2: Hi from thread:  3
...

It looks like thread 1 gets there first and then thread 3. Isn't the scoped_lock supposed to prevent other threads from entering that section of code? Shouldn't the first thread that runs FirstCount() go to completion?

UPDATE

One thing I think is wrong with my code is this line:

boost::mutex::scoped_lock(mutex_);

I think it should be like:

boost::mutex::scoped_lock xyz(mutex_);

Once I do that, it does make the complaint about mutex_ not being static. Why it worked in the first place I'm not sure. Changing mutex_ to static does gives me a linking error:

1>ThreadWorker.obj : error LNK2001: unresolved external symbol "private: static class boost::mutex ThreadWorker::mutex_" (?mutex_@ThreadWorker@@0Vmutex@boost@@A) 1>c:\something\ThreadTest\Debug\ThreadTest.exe : fatal error LNK1120: 1 unresolved externals

Still playing with it.

like image 973
User Avatar asked Jan 18 '23 12:01

User


1 Answers

You have two errors:

First of all, as already noticed, mutex_ should be static also:

private:
    static boost::mutex mutex_;

and of course declare it somewhere (in a .cpp file preferably!):

boost::mutex ThreadWorker::mutex_{};

Now, why does the compiler not complain? Well, because you actually do not construct a scoped lock with argument mutex_ here:

boost::mutex::scoped_lock(mutex_);

Actually this will not call the constructor that you want, but create a (local) object mutex_ that is of type scoped_lock and is constructed by the default constructor. Hence, no compiler issues. You should change it to something like the following:

boost::mutex::scoped_lock l{mutex_};

Now the compiler should start complaining about mutex_

like image 106
KillianDS Avatar answered Jan 22 '23 11:01

KillianDS