Boost :: scoped_lock not working with local static variable?

I made the following sample program for forced playback:

#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 stream 1 gets there first, and then stream 3. Isn't scoped_lock supposed to prevent other threads from entering this section of code? Should the first thread starting FirstCount () go to completion?

UPDATE

One thing that in my opinion is incorrect in my code is the line:

 boost::mutex::scoped_lock(mutex_); 

I think it should be like:

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

As soon as I do this, he makes a complaint that mutex_ is not static. Why it worked, I'm not sure. Changing mutex_ to static gives me a binding error:

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

Keep playing with him.

+4
source share
4 answers

You have two errors:

First of all, as already noted, mutex_ must also be static:

 private: static boost::mutex mutex_; 

and, of course, declare it somewhere (preferably in .cpp format!):

 boost::mutex ThreadWorker::mutex_{}; 

Now, why does the compiler not complain? Good, because you are not really creating a lock with the mutex_ argument here:

 boost::mutex::scoped_lock(mutex_); 

This will not actually call the constructor you want, but create a (local) mutex_ object that is of type scoped_lock and is constructed by the default constructor. Therefore, no compilers arise. You should change it to the following:

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

Now the compiler should start complaining about mutex_

+6
source

You have three separate objects, and none of them can see the other mutex_, because this element is created inside each object.

Perhaps you also wanted to make mutex_ static?

Edit: if I make the mutex statics and remove the statics from the i variable, then it works, as I assume you meant it. It seems that something like this is happening: each thread immediately enters the loop and is not blocked from each other due to the fact that the mutex is not static. By the time they are all output to the console (I don’t remember if there is a mutual exception when writing to cout), and I get incremented, they all see the static me as 30 and exit.

Edit 2: No, it’s still not correct, since some runs still have interspersed values.

Edit 3: the reason it compiles is because your scoped_lock is temporary, which seems to throw the compiler out of the fact that mutex_ should be static. Instead, try using the following code:

 #include <iostream> #include "boost\thread\mutex.hpp" #include "boost\thread\thread.hpp" class ThreadWorker { public: ThreadWorker() {} virtual ~ThreadWorker() {} static void FirstCount(int threadId) { // Created object f here rather than temprary boost::mutex::scoped_lock f(mutex_); int i = 0; // Not static for(i = 1; i <= 30; i++) { std::cout << i << ": Hi from thread: " << threadId << std::endl; } } private: static boost::mutex mutex_; // Static }; // Storage for static boost::mutex ThreadWorker::mutex_; int main(int argc, char* 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; } 
+3
source

Is this code compiled with the same compiler?

Do you see a problem with this code? Try to identify the problem without compiling it.

  class C {
 public:
     static int f () {
         return i;
     }

     int i;
 };

 int main () {
     return C :: f ();
 }

UPDATE: I just read your update.

  class C {
 public:
     static int f () {
         return i;
     }

     static int i;
 };

 int C :: i = whatever;

 int main () {
     return C :: f ();
 }
0
source

Changed my code:

ThreadWorker.h:

 #pragma once #include "boost\thread\mutex.hpp" #include <iostream> class ThreadWorker { public: ThreadWorker(); virtual ~ThreadWorker(); static void FirstCount(int threadId); private: static boost::mutex mutex_; }; 

ThreadWorker.cpp:

 #include "stdafx.h" #include "ThreadWorker.h" boost::mutex ThreadWorker::mutex_; ThreadWorker::ThreadWorker() { } ThreadWorker::~ThreadWorker() { } void ThreadWorker::FirstCount(int threadId) { boost::mutex::scoped_lock xyz(mutex_); static int i = 0; for(i = 1; i <= 30; i++) { std::cout << i << ": Hi from thread: " << threadId << std::endl; } } 

ThreadTest.cpp:

 // ThreadTest.cpp : Defines the entry point for the console application. // #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; } 

The change I made was 1. to separate the header file and cpp (I originally did this just to make my post more compact). 2. specifying the variable scoped_lock identifier and 3. making a static mutex.

Now it works as expected, sequentially prints 30 lines from each stream. What still bothers me is why the code was compiled earlier (since tinman was also able to compile my original code).

0
source

All Articles