Can mutex implementations be interchanged (independently of the thread implementation) - c++

Do all mutex implementations ultimately call the same basic system/hardware calls - meaning that they can be interchanged?
Specifically, if I'm using __gnu_parallel algorithms (that uses openmp) and I want to make the classes they call threadsafe may I use boost::mutex for the locking? or must I write my own mutex such as the one described here
//An openmp mutex. Can this be replaced with boost::mutex?
class Mutex {
public:
Mutex() { omp_init_lock(&_mutex); }
~Mutex() { omp_destroy_lock(&_mutex); }
void lock() { omp_set_lock(&_mutex); }
void unlock() { omp_unset_lock(&_mutex); }
private:
omp_lock_t _mutex;
};
Edit, the link above to the openmp mutex seems to be broken, for anyone interested, the lock that goes with this mutex is along these lines
class Lock
{
public:
Lock(Mutex& mutex)
: m_mutex(mutex),
m_release(false)
{
m_mutex.lock();
}
~Lock()
{
if (!m_release)
m_mutex.unlock();
}
bool operator() const
{
return !m_release;
}
void release()
{
if (!m_release)
{
m_release = true;
m_mutex.unlock();
}
}
private:
Mutex& m_mutex;
bool m_release;
};

This link provides a useful discussion:
http://groups.google.com/group/comp.programming.threads/browse_thread/thread/67e7b9b9d6a4b7df?pli=1
Paraphrasing, (at least on Linux) Boost::Thread and OpenMP both an interface to pthread and so in principle should be able to be mixed (as Anders says +1), but mixing threading technologies in this way is generally a bad idea (as Andy says, +1).

You should not mix synchronization mechanisms. E.g. current pthreads mutex implementation is based on futex and it is different from previous pthreads implementations (see man 7 pthreads). If you create your own level of abstraction, you should use it. It should be considered what is your need - inter-thread or inter-process synchronization?
If you need cooperation with code that uses boost::mutex, you should use boost::mutex in place of open mp.
Additionally IMHO it is quite strange to use open mp library functions to realize mutex.

The part requiring compatibility is the thread suspension, rescheduling and context switching. As long as the threads are real threads, scheduled by the operating system, you should be able to use any mutex implementation that relies on some kind of kerner primitive for suspending and resuming a waiting thread.

Related

C++ Boost Mutex Lock

Recently I am playing around Boost mutex and I am not sure if I can do the following:
boost::recursive_mutex ListLock;
int main(){
ListLock.lock();
function1();
ListLock.unlock();
}
void function1(){
ListLock.lock();
//some operations
ListLock.unlock();
}
Is it okay to lock the ListLock twice?
It depends on the lock. Recursive locks allow ... recursive locks. So, no problem in your example.
Non-recursive locks (such as std::mutex or boost::mutex) would deadlock (technically, I think the behaviour is unspecified, but most POSIX thread implementations either deadlock or raise an exception based on EDEADLK).
See http://en.cppreference.com/w/cpp/thread/recursive_mutex for recursive_mutex

Upgrading read lock to write lock without releasing the first in C++11?

I know it's possible using boost::UpgradeLockable in C++14.
Is there anything similar for C++11?
An upgradeable lock can be written on top of simpler locking primitives.
struct upgradeable_timed_mutex {
void lock() {
upgradable_lock();
upgrade_lock();
}
void unlock() {
upgrade_unlock();
upgradable_unlock();
}
void shared_lock() { shared.shared_lock(); }
void shared_unlock() { shared.shared_unlock(); }
void upgradable_lock() { unshared.lock(); }
void ungradable_unlock() { unshared.unlock(); }
void upgrade_lock() { shared.lock(); }
void upgrade_unlock() { shared.unlock(); }
private:
friend struct upgradable_lock;
std::shared_timed_mutex shared;
std::timed_mutex unshared;
};
and similar for the timed and try variants. Note that timed variants which access two mutexes in a row have to do some extra work to avoid spending up to 2x the requested time, and try_lock has to be careful about the first lock's state in case the 2nd fails.
Then you have to write upgradable_lock, with the ability to spawn a std::unique_lock upon request.
Naturally this is hand-written thread safety code, so it is unlikely to be correct.
In C++1z you can write an untimed version as well (with std::shared_mutex and std::mutex).
Less concretely, there can be exactly one upgradeable or write lock at a time. This is what the unshared mutex represents.
So long as you hold unshared, nobody else is writing to the guarded data, so you can read from it without holding the shared mutex at all.
When you want to upgrade, you can grab a unique lock on the shared mutex. This cannot deadlock so long as no readers try to upgrade to upgradable. This excludes readers from reading, you can write, and then you release it and return back to a read only state (where you only hold the unshared mutex).

Another way to check std::queue event?

Well, I'm trying to work on some kind of queue. I have an IO thread that it's dedicated for popping data out of the std::queue but the problem is that I'm using a Sleep() in order to prevent 100% cpu constant checking. And of course other threads which will add items to the std::queue.
How could I make an event so that the thread is dormant and only initiates when the std::queue is NOT empty?
IO Thread
Sleep(100);
while (!myqueue.empty())
{
//process data FIFO
myqueue.pop(); //pop out and continue
}
Much appreciated, thank you! Oh and this is for c++11 or c++03 it doesn't matter - on Windows.
std::queue has absolutely nothing to do with threads. At all. Its .empty() member is not thread-safe (only reentrant)! The same applies to all it's other members. So multiple threads can use different queues whatever they like, but only one thread at a time can do anything at all with each instance.
C++11 or C++03 matters a lot. Because C++11 defines thread synchronization primitives, while C++03 does not and you have to use OS API.
In C++11 you would be interested in std::condition_variable.
In C++03 you would be interested in either Boost.Thread (mostly compatible with C++11) Events or Semaphores.
In either case the std::queue::push() and std::queue::pop() themselves must be protected by a mutual exclusion. The std::condition_variable even forces you to use one (std::mutex), in Windows API you'd use Critical Section.
On Windows, the C++11 classes are only available in Visual Studio 2012 and Windows 8. With older compiler use Boost (the advantage is that it will be portable) or native API.
You need a "condition variable". Whenever a thread puts something on the queue it "notifies" threads waiting on the condition variable. The thread that consumes events from the queue waits on the condition variable. It is asleep until someone notifies it via the condition variable.
Boost has a nice implementation: http://www.boost.org/doc/html/thread/synchronization.html#thread.synchronization.condvar_ref
You are using a lock to make sure access to the queue is thread-safe, aren't you?
my suggestion is to first look into how to use a thread safe queue, then perhaps think about using boost::condition signaling to provide more control.
here is an example of how you could build a thread safe queue:
#pragma once
#include <queue>
template<typename T>
class thread_safe_queue
{
queue<T> m_queue;
pthread_mutex_t m_mutex;
pthread_cond_t m_condv;
public:
thread_safe_queue() {
pthread_mutex_init(&m_mutex, NULL);
pthread_cond_init(&m_condv, NULL);
}
~thread_safe_queue() {
pthread_mutex_destroy(&m_mutex);
pthread_cond_destroy(&m_condv);
}
void push(T& item) {
pthread_mutex_lock(&m_mutex);
T itemcpy = std::move(item);
m_queue.push(std::move(itemcpy));
pthread_cond_signal(&m_condv);
pthread_mutex_unlock(&m_mutex);
}
T pop() {
pthread_mutex_lock(&m_mutex);
while (m_queue.size() == 0) {
pthread_cond_wait(&m_condv, &m_mutex);
}
T& _item = m_queue.front();
T itemcpy = std::move(_item);
m_queue.pop();
pthread_mutex_unlock(&m_mutex);
return itemcpy;
}
int size() {
pthread_mutex_lock(&m_mutex);
int size = m_queue.size();
pthread_mutex_unlock(&m_mutex);
return size;
}
};
this is how you instantiate it :
thread_safe_queue<myclass> myqueue;
if you want to use event signaling then look into using boost::condition - fx. like this:
#include <boost/thread/condition.hpp>
#include <boost/thread/mutex.hpp>
boost::mutex mtxWait;
boost::condition cndSignalQueueHasNewEntry;
bool WaitForQueueSignal(long milliseconds)
{
boost::mutex::scoped_lock mtxWaitLock(mtxWait);
boost::posix_time::time_duration wait_duration = boost::posix_time::milliseconds(milliseconds); // http://www.boost.org/doc/libs/1_34_0/doc/html/date_time/posix_time.html
boost::system_time const timeout=boost::get_system_time()+wait_duration; // http://www.justsoftwaresolutions.co.uk/threading/condition-variable-spurious-wakes.html
return cndSignalQueueHasNewEntry.timed_wait(mtxWait,timeout); // wait until signal notify_one or timeout
}
This is how you can signal
cndSignalQueueHasNewEntry.notify_one();
This is how you can wait for signal
bool bResult = WaitForQueueSignal(10000); // timeout after 10 seconds

How do I make a critical section with Boost?

For my cross-platform application I have started to use Boost, but I can't understand how I can implement code to reproduce behavior of Win32's critical section or .Net's lock.
I want to write a method Foo that can be called from different threads to control write operations to shared fields. Recursive calls within the same thread should be allowed (Foo() -> Foo()).
In C# this implementation is very simple:
object _synch = new object();
void Foo()
{
lock (_synch) // one thread can't be lock by him self, but another threads must wait untill
{
// do some works
if (...)
{
Foo();
}
}
}
With boost you can use boost::lock_guard<> class:
class test
{
public:
void testMethod()
{
// this section is not locked
{
boost::lock_guard<boost::recursive_mutex> lock(m_guard);
// this section is locked
}
// this section is not locked
}
private:
boost::recursive_mutex m_guard;
};
PS These classes located in Boost.Thread library.
Here's a rewrite of your example, using Boost.Thread: I removed the comments, but otherwise, it should be a 1-to-1 rewrite.
boost::recursive_mutex mtx;
void Foo()
{
boost::lock_guard<boost::recursive_mutex> lock(mtx);
if (...)
{
Foo();
}
}
The documentation can be found here.
Note that Boost defines a number of different mutex types. Because your example shows the lock being taken recursively, we need to use at least boost::recursive_mutex.
There are also different types of locks. In particular, if you want a reader-writer lock (so that multiple readers can hold the lock simultaneously, as long as no writer has the lock), you can use boost::shared_lock instead of lock_guard.

Upgradeable read/write lock Win32

I am in search of an upgradeable read write lock for win32 with the behaviour of pthreads rwlock, where a read lock can be up- and downgraded.
What I want:
pthread_rwlock_rdlock( &lock );
...read...
if( some condition ) {
pthread_rwlock_wrlock( &lock );
...write...
pthread_rwlock_unlock( &lock );
}
...read...
pthread_rwlock_unlock( &lock );
The upgrade behaviour is not required by posix, but it works on linux on mac.
Currently, I have a working implementation (based on an event, a semaphore and a critical section) that is upgradeable, but the upgrade may fail when readers are active. If it fails a read unlock + recheck + write lock is necessary.
What I have:
lock.rdlock();
...read...
if( some condition ) {
if( lock.tryupgrade() ) {
...write...
lock.unlock();
return;
} else {
lock.unlock();
// <- here, other threads may alter the condition ->
lock.wrlock();
if( some condition ) { // so, re-check required
...write...
}
lock.unlock();
return;
}
}
...read...
lock.unlock();
EDIT: The bounty:
I am still in search, but want to add some restrictions: it is used intra-process-only (so based on critical sections is ok, WIN32 mutexes are not ok), and it should be pure WIN32 API (no MFC, ATL etc.). Acquiring read locks should be fast (so, acquiring the read lock should not enter a critical section in its fast path). Maybe an InterlockedIncrement based solution is possible?
The boost shared_mutex class supports reader (shared) and writer (unique) locks and temporary upgrades from shared to unique locks.
Example for boost shared_mutex (multiple reads/one write)?
I don't recommend writing your own, it's a tricky thing to get right and difficult to test thoroughly.
pthread library is a 'Portable Threads' library. That means it's also supported on windows ;) Have a look: Pthreads-w32.
Additionally, consider using OpenMP instead of locks: the compiler extension provides portable critical sections, kernes threading model, tasks and much more! MS C++ supports this technology as well as g++ in Linux.
Cheers! :)
What is wrong with this approach?
// suppose:
struct RwLock
{
void AcquireExclusive();
void AcquireShared();
void Release();
bool TryAcquireExclusive();
};
// rwlock that has TryAcquireSharedToExclusive
struct ConvertableRwLock
{
void AcquireExclusive()
{
writeIntent.AcquireExclusive();
rwlock.AcquireExclusive();
writeIntent.Release();
}
void AcquireShared()
{
readIntent.AcquireShared();
rwlock.AcquireShared();
readIntent.Release();
}
void Release()
{
rwlock.Release();
}
bool TryConvertSharedToExclusive()
{
// Defer to other exclusive including convert.
// Avoids deadlock with other TryConvertSharedToExclusive.
if (!writeIntent.TryAcquireExclusive())
{
rwlock.Release();
return false;
}
// starve readers
readIntent.AcquireExclusive();
// release full lock, but no other can acquire since
// this thread has readIntent and writeIntent.
rwlock.Release();
// Wait for other shared to drain.
rwlock.AcquireExclusive();
readIntent.Release();
writeIntent.Release();
return true;
}
private:
RwLock rwlock;
RwLock readIntent;
RwLock writeIntent;
};