How to use pthread_mutex and it functions inside the class?

I searched many hours for a solution, but cannot find a simple answer. I have a class that uses pthreads. The actual function pointer is static in the class, and I need to lock the mutex, because so far I get "strange" results (parameters are not passed correctly).

However, pthread_mutex_lock and unlock will not work in the function specified for the thread, because it is in a static member function, but I cannot have a function that is not static, because it will not work inside the class, and I cannot move it outside the class because he will not be able to access the necessary information.

The following code should explain:

class Fight{ pthread_mutex_t thread_mutex; static void *thread_run_fighter(void *temp); public: Fight(); bool thread_round(Individual &a, int a_u, Individual &b, int b_u); std::vector<Individual> tournament(); }; 

And the cpp file:

  Fight::Fight(){ thread_mutex = PTHREAD_MUTEX_INITIALIZER; } bool Fight::thread_round(Individual &a, int a_u, Individual &b, int b_u){ if (a.saved and b.saved){ a.uniform = a_u; b.uniform = b_u; Individual *one = &a; Individual *two = &b; pthread_t a_thread, b_thread; int a_thread_id, b_thread_id; a_thread_id = pthread_create(&a_thread,NULL,Fight::thread_run_fighter,(void*) one); b_thread_id = pthread_create(&b_thread,NULL,Fight::thread_run_fighter,(void*) two); pthread_join( a_thread, NULL); pthread_join( b_thread, NULL); return true; } else{ return false; } } void *Fight::thread_run_fighter(void *temp){ Individual *indiv; indiv = (class Individual*)temp; pthread_mutex_lock( &thread_mutex ); indiv->execute(indiv->uniform); pthread_mutex_unlock( &thread_mutex ); } 

I would be very grateful if anyone could shed light on this. I was stuck for several hours and I could not find any information. Thanks!

+4
source share
4 answers

By 'does not work' I assume that you mean that it will not compile because you are trying to use an instance member in a member function of static .

But the bigger question is, why are you trying to use threads for this?

The stream function you have is fully protected by the mutex - you will get the same (or better) performance just by calling

 a.execute(a.uniform); b.execute(b.uniform); 

instead of unscrewing the threads and then waiting for them to complete.


But if you really want to use threads (maybe you will learn about them), and you want your static member function to be able to deal with instance members, here are a few pointers. To make this work, you need to somehow pass an instance of the Fight object to the static stream function:

 // somewhere in `class Fight` definition: // // a structure that will let you pass a Fight* instance pointer // along with an Individual* to work on in the the // thread function struct context { Fight* me; Individual* indiv; }; // ... // in Fight::thread_round(): // package up data to pass to the thread function context one = {this, &a }; // instead of Individual *one = &a; context two = {this, &b }; // instead of Individual *two = &b; 

Finally, Fight::thread_run_fighter() :

 void *Fight::thread_run_fighter(void *temp) { // pull out the Fight object instance and the Individual // object to work on context* ctx = (context*) temp; Individual *indiv = ctx->indiv; Fight* me = ctx->me; // do the work (in a pretty serialized fashion, unfortunately) pthread_mutex_lock( &me->thread_mutex ); indiv->execute(indiv->uniform); pthread_mutex_unlock( &me->thread_mutex ); return 0; } 
+4
source

The first question I would like to ask is: do you need portable code? If so, never pass the C ++ function to pthread_create. Reason: the interface for pthread_create requires a function declared as extern "C", and you are lucky (thanks x86 :)) that the static member method is suitable for this, but there is no guarantee that the same will happen on another platform or compilers.

Secondly, you called thread_mutex = PTHREAD_MUTEX_INITIALIZER; after creating the mutex, as far as I remember, the standard says that this is allowed only during initialization.

And finally, pthread_mutex_lock( &thread_mutex ) using the static method will not be allowed, because the static method does not have access to objects, not static members, so you need to pass a pointer to the object. You can declare pthread_mutex_t thread_mutex; and void *thread_run_fighter(void *temp); global as I see it will be the easiest way in this case.

And some notes: what about boost :: threads? I think it's better to use it instead of creating your own solution ...

+2
source

I think all you missed was to use &indiv->thread_mutex instead of indiv-> object.

EDIT: note that it is probably better to use a static movie rather than a C shotgun style: Individual *indiv = static_cast<Individual*>(temp);

+1
source

inside static thread_run_fighter you use non-static thread_mutex . thread_mutex must be created using pthread_mutex_init before using it.

0
source

All Articles