Semaphore implementation

I was wondering if there is a way to implement the semaphore in C ++ (or C #), any libraries that will help. I tried using OpenMP, but I had no way to block threads, instead I had to tackle the animation, which led to deadlocks if / when I did not have enough threads. So, first I am looking for some kind of library that would allow me to block / spawn / kill my threads.
Secondly, are there libraries that already implement semaphores?
And finally, when I got acquainted with the context of semaphores, I found it very useful (maybe I'm wrong?), But I don’t see many libraries (if at all) implementing it. I am familiar with OpenMP, inspected Intel TBB streams, C #. But in none of them do I see semaphores explicitly. So semaphores are not as practical as I think? Or is it hard to implement? Or is it not known to me?
PS
Can semaphores be used cross-platform? Because they are probably OS related.

+2
source share
4 answers

Are there libraries that already implement this?
For C ++, there are several multithreading libraries that provide the implementation of Semaphore:

In addition, you can also use Semaphores using Boost. Check out this one .

+6
source

The first tip is using boost. All the hard work was done.

If you want to see how it is implemented, it should look like this (although this is an approximate sketch, I am sure that some studies can be optimized). Basically, a semaphore is built of three things:

  • Score
  • Condition variable (which provides suspension)
  • A mutex that provides exclusivity for bill changes and expectations provided.

Here is a simple version:

#include <pthread.h> // Need an exception safe locking class. struct MutexLocker { MutexLocker(pthread_mutex_t& m) :mutex(m) { if (pthread_mutex_lock(&mutex) != 0) {throw int(1); }} ~MutexLocker() { if (pthread_mutex_unlock(&mutex) != 0) {throw int(1); }} private: pthread_mutex_t& mutex; }; class Semaphore { public: Semaphore(int initCount = 0) : count(initCount) , waitCount(0) { if (pthread_mutex_init(&mutex, NULL) != 0) { throw int(1); } if (pthread_cond_init(&cond, NULL) != 0) { pthread_mutex_destroy(&mutex); throw int(2); } } void wait() { MutexLocker locker(mutex); while(count == 0) { ++waitCount; if (pthread_cond_wait(&cond, &mutex) != 0) { throw int(2); } // A call to pthread_cond_wait() unlocks the mutex and suspends the thread. // It does not busy wait the thread is suspended. // // When a condition variable receives apthread_cond_signal() a random thread // is un-suspended. But it is not released from the call to wait // until the mutex can be reacquired by the thread. // // Thus we get here only after the mutex has been locked. // // You need to use a while loop above because of this potential situation. // Thread A: Suspended waiting on condition variable. // Thread B: Working somewhere else. // Thread C: calls signal() below (incrementing count to 1) // This results in A being awakened but it can not exit pthread_cond_wait() // until it requires the mutex with a lock. While it tries to // do that thread B finishes what it was doing and calls wait() // Thread C has incremented the count to 1 so thread B does not // suspend but decrements the count to zero and exits. // Thread B now aquires the mutex but the count has been decremented to // zero so it must immediately re-suspend on the condition variable. // Note a thread will not be released from wait until // it receives a signal and the mustex lock can be re-established. --waitCount; } --count; } void signal() { // You could optimize this part with interlocked increment. MutexLocker locker(mutex); ++count; // This Comment based on using `interlocked increment` rather than mutex. // // As this part does not modify anything you don;t actually need the lock. // Potentially this will release more threads than you need (as you don't // have exclusivity on reading waitCount but that will not matter as the // wait() method does and any extra woken threads will be put back to sleep. // If there are any waiting threads let them out. if (waitCount > 0) { if (pthread_cond_signal(&cond) != 0) { throw int(2); } } } private: unsigned int count; unsigned int waitCount; pthread_mutex_t mutex; pthread_cond_t cond; }; 
+3
source

In .NET, there is an implementation in BCL: System.Threading.Semaphore .

For native code on Windows, check out the CreateSemaphore function . If you are targeting Linux, you can find the semaphore implementation of Vienna University of Technology here (which I have used before and works).

+2
source

In C ++, in order to block threads, I would recommend using state variables, not semaphores. In C #, monitors may be more appropriate.

Even for a fairly simple case, the manufacturer-consumer problem is more difficult to solve semaphores correctly: doing semaphore increments and losses in the wrong order can lead to problems. On the contrary, a solution based on variable variables will not have such problems: condition variables are used with a lock (mutex), and the correct order of operations is automatically applied; therefore, after waking up, the thread already has a detected lock.

See also my address. When should I use semaphores? , where I gave another example of a condition variable, in my opinion, more suitable for a problem often solved with semaphores.

And to solve another issue, I think that a higher responsibility for the erroneous use and more complex work of solutions (compared to alternatives) is the reason that some semaphores are not provided by some streaming packages. For TBB, I can say for sure. Thread support in C ++ 11 (developed after Boost.Thread) also does not; see Anthony Williams answer why.

0
source

Source: https://habr.com/ru/post/913356/


All Articles