How can I achieve something like a semaphore using boost in C ++?

I noticed that the boost does not support semaphores. What is the easiest way to achieve this effect?

+7
c ++ multithreading boost boost-thread boost-interprocess
source share
3 answers

You either need Boost Interprocess semaphore or Boost Thread synchronization .

Mutex / Lock and condition are primitives that are commonly used to synchronize access to shared resources for multiple threads of a single process. Exclusive , reader-writer, and recursive / reentrant mutex types exist. In other words, Mutex is an exclusive castle. The condition is used to achieve atomicity when you need to unlock the mutex and wait for the object to change. When you start waiting on the condition, it unlocks the mutex and ensures that the unlock + call to wait is atomic and no other threads can change the resource between these two operations.

A semaphore, in another case, is a combination of a condition and a mutex and is used for exactly one purpose, but to synchronize access through processes.

See Mutex vs Semaphore .

There is also such a thing as non-blocking / blocking synchronization , which is becoming very popular these days. I personally use it in high-frequency trading applications when the amount of data is relatively large and low latency is of great importance.

In your case, I assume that 5 philosophers can dine in the same process with 5 threads. In this case, you need to use a mutex, not a semaphore. However, you may or may not use the condition. It depends on what exactly and how exactly you want to implement this dining procedure.

I'm not sure how to describe it better, as I will eventually write a book about it. Therefore, I would recommend that you find a book that is already written to understand the basic concepts. When you know the basics, you can use APIs / libraries / frameworks such as POSIX threads , Boost Interprocess or Thread , ACE or even non-blocking algorithms to achieve what you want.

Good luck

+6
source share

This is one way to implement a very simple semaphore using Boost.Thread. This is an inter-thread semaphore, not an inter-process one. No warranties are implied, etc. - I did not even compile the code. It illustrates the interaction of mutexes and variable conditions and suggests a reasonably recent version of Boost.

Note that the mutex variables and conditions are β€œpaired” - threads must have a mutex lock in order to wait for the condition variable, and re-get the lock when they are woken up. In addition, code that modifies data must explicitly spill other code that can wait. This means that the mutex, the condition variable, the data, and the condition (conditions) that cause awakening are all closely related. A tight connection also means that data, a mutex, and a condition variable should be encapsulated, if possible β€” any external modification may violate the code in strange ways, including deadlocks, missed wakes, and other strange errors.

All this actually means an addition to the words of Vlad Lazarenko - understanding the theory and principles is at least as important as having a β€œworking” code in multi-threaded programming.

#include <boost/thread/condition_variable.hpp> #include <boost/thread/mutex.hpp> #include <boost/thread/lock_types.hpp> class semaphore { //The current semaphore count. unsigned int count_; //mutex_ protects count_. //Any code that reads or writes the count_ data must hold a lock on //the mutex. boost::mutex mutex_; //Code that increments count_ must notify the condition variable. boost::condition_variable condition_; public: explicit semaphore(unsigned int initial_count) : count_(initial_count), mutex_(), condition_() { } unsigned int get_count() //for debugging/testing only { //The "lock" object locks the mutex when it constructed, //and unlocks it when it destroyed. boost::unique_lock<boost::mutex> lock(mutex_); return count_; } void signal() //called "release" in Java { boost::unique_lock<boost::mutex> lock(mutex_); ++count_; //Wake up any waiting threads. //Always do this, even if count_ wasn't 0 on entry. //Otherwise, we might not wake up enough waiting threads if we //get a number of signal() calls in a row. condition_.notify_one(); } void wait() //called "acquire" in Java { boost::unique_lock<boost::mutex> lock(mutex_); while (count_ == 0) { condition_.wait(lock); } --count_; } }; 
+21
source share

I made a semaphore class compatible with the concept of boosts TimedLockable , so it can be used with locks like boost::unique_lock<semaphore> . This is not a semaphore in the classical definition of one, but can be used as one. However, I hope this can be useful for someone.

He was somehow checked, but there is a high probability that I did something wrong. It would be great if someone could prove its correctness.

 class semaphore { private: semaphore(const semaphore & other); semaphore & operator = (const semaphore & other); boost::mutex _mutex; boost::condition_variable _condVar; size_t _count; class wait_predicate { private: const size_t & _countRef; public: wait_predicate(const size_t & countRef) : _countRef(countRef) {} bool operator()() { return _countRef > 0; } }; // must be used inside a locked scope! inline wait_predicate getWaitPredicate() const { return wait_predicate(_count); } public: semaphore(size_t size): _count(size) {} void lock() { boost::unique_lock<boost::mutex> local_lock(_mutex); _condVar.wait(local_lock, getWaitPredicate()); _count--; } void unlock() { boost::unique_lock<boost::mutex> local_lock(_mutex); _count++; _condVar.notify_one(); } bool try_lock() { boost::unique_lock<boost::mutex> local_lock(_mutex); if (0 == _count) return false; _count--; return true; } template <typename Duration> bool try_lock_for(const Duration & duration) { boost::unique_lock<boost::mutex> local_lock(_mutex); if (!_condVar.wait_for(local_lock, duration, getWaitPredicate())) return false; _count--; return true; } template <class TimePoint> bool try_lock_until(const TimePoint & timePoint) { boost::unique_lock<boost::mutex> local_lock(_mutex); if (!_condVar.wait_until(local_lock, timePoint, getWaitPredicate())) return false; _count--; return true; } template <class WaitCriteria> bool timed_lock(const WaitCriteria & criteria) { boost::unique_lock<boost::mutex> local_lock(_mutex); if (!_condVar.timed_wait(local_lock, criteria, getWaitPredicate())) return false; _count--; return true; } }; 
0
source share

All Articles