Difference between boost::unique_lock and boost::upgrade_lock? - c++

I am new to threading concept in C++ . I Just wanted to know few things: How is a boost::unique_lock different from boost::upgrade_lock?
How actually an exclusive ownership differ from upgrade ownership.
Maybe one can say exclusive ownership is thread safe but not upgrade ownership,
in that case i would like to know how can an upgrade ownership can be harmful if
it can be? I want to know what is that upgrade_lock allows or not allows that
unique_lock does except exclusive lock thing. Not providing exclusive lock by
upgrade_lock makes it similar to shared_lock or what and if so then how is it
different from shared_lock?

The difference between upgrade_lock and unique_lock is simple. An instance of unique_lock is acquiring a full exclusive ownership of a shared_mutex. This means that no one else can get any type of ownership while the unique_lock is alive.
Unlike the unique_lock an instance of upgrade_lock is acquiring an upgrade ownership that exclusive only amongst threads trying to get the same upgrade ownership. All other threads that try to get a shared ownership could acquire it with no conflict until the upgrade_lock is upgraded to unique (with an instance of upgrade_to_unique_lock).
The upgrade_lock is useful when some of threads can be readers only and will not try to promote itself to writers. Otherwise (all readers may try to become writers at some point) upgrade_lock will operate as unique_lock.

#Xeo yes upgrade_lock can be upgraded to uniue_lock by
upgrade_yo_unique_lock . so why do we need shared_lock is that because
shared_lock cant be upgrade to unique_lock ? Is that the only thing ?
Yes.
shared_mutex exists only to supply the functionality of traditional read/write mutexes. Some clients will be understandably leery of a mutex changing lock-modes from one to another, and yet still need the traditional functionality of a rw/mutex. This is the role of shared_mutex.
Other clients will look at shared_mutex and say: I want more. I want to sometimes atomically upgrade my ownership from shared to exclusive. And this is the role of upgrade_mutex. upgrade_mutex is not better than shared_mutex, nor vice-versa. It is simply another tool in the toolbox.

Related

When to use C++11 mutex, lock, unique_lock, shared_lock, etc

What is the difference between shared_lock and shared_mutex.lock_shared() other than that the destructor of shared_lock unlocks the associated mutex?
Is a shared_mutex the only mutex class I can use with shared_lock?
Why would someone want to use lock_guard instead of unique_lock?
If I have many threads constantly locking for reading (shared_lock) a variable and I have a variable that tries to lock it for writing (unique_lock), will this writing thread have a priority over the other ones?
For #4, is there a possibility for a deadlock?
shared_mutex.lock_shared() is a function call that locks shared_mutex in a shared mode, while shared_lock is a "lock-class" that is used to lock and automatically unlock mutex at the end of the scope.
No, you can use shared_lock with any type that meets the SharedMutex requirements.
Always use lock_guard unless you need additional functionality of unique_lock. This way your intent is more clear.
This does not depend on shared_lock or unique_lock, but on what SharedMutex you are using. Exact beheavior is not specified by the standard. But here are some clues:
On Windows shared_lock will usually be implemented using SRWLOCK and tries to be fair e.g. will try to balance readers and writers. No one will have higher priority here.
On POSIX systems shared_mutex will most likely be implemented on top of pthread_rwlock_t and implementations usually give preference to readers because of its requirement to support recursive read locks.
Boost shared_mutex tries to be fair and gives no preference to either side.
With reader-preferring shared_mutex it is possible for your writer thread to never acquire the lock if there is always at least one reader holding it.

Is using unique_lock for a task that can be acomplished by lock_guard slower?

I am confused regarding the reason why lock_guard exists. Is it:
A simpler interface than unique_lock?
Better performance than unique_lock?
Something else?
lock_guard can be implemented with one unit of state: a pointer or reference to the Mutex type it has locked.
unique_lock has to both hold that state, and knowing if it is currently locked, as a unique_lock can have a Mutex that is not locked. This means it must have at least a bool of extra state.
lock_guard provides a zero overhead RAII lock/unlock wrapper around acquiring and releasing a Mutex. Basically the lock_guard means that there is zero reason to avoid using RAII to handle locks on a Mutex.
unique_lock can only reach zero overhead if the compiler can be convinced to notice you only use it in ways that lock_guard could be used (ie, construct it, then destroy it, without fiddling with it).
Beyond those efficiency arguments, a programmer who sees a lock_guard knows that it is going to last until end of scope without having to examine the code in the scope. A programmer who sees a unique_lock must examine all use of the variable to know if this is the case.
But the above is only half the reason.
The other half of the reason is because much of the threading library for C++11 was based off of boost libraries, which had already implemented a mostly platform independent threading library. Boost has both lock_guard and unique_lock, with nearly identical semantics to the C++11 versions.
So when the boost threading library was standardized, both where carried in, and nobody eliminated them.
You almost answer your own question here - 1) and 2) are both good reasons. std::lock_guard is a simple scoped locking object. Features like a timeout on mutex acquisition add to the complexity of the mutex primitive, increasing both the time it takes to perform the operation and the probability of contention for the mutex. So why pay for what you don't need?
Whether 'try_locking' with or without timeouts is good design is another question; like thread cancellation, a broken design which C++11 does not implement.

How does the upgradable ownership of a mutex affect other threads?

the situation is:
a thread acquires an upgradable ownership of a boost::shared_mutex and is calling unlock_upgrade_and_lock(), which blocks because the other threads are possessing shared ownership of the same shared_mutex at the moment.
Will upgradable ownership of the first thread prevent(block) other threads when they are trying to "lock_shared" the shared_mutex so that all those already sharing ownership will finally unlock_shared and exclusive ownership for the first thread be guaranteed?
Or there is a possibility for the first thread to stay blocked for as long as there is another thread sharing the mutex?
(Assuming the Boost implementation vaguely models the WG21 proposal from Howard Hinnant ...)
Converting from shared ownership to upgrade ownership prevents any new threads acquiring the lock, so eventually all the shared owners will release it and the thread with upgrade ownership can convert it to exclusive ownership. This is the point of the "upgrade lock" as opposed to just shared and exclusive locks, see the explanation in N3427:
Note that an alternative design of try-converting from shared to exclusive, instead of from shared to upgrade as shown, would be susceptible to update (writer) starvation. This is because as long as there are multiple searchers (shared locks), none of the searchers can ever successfully try-convert to updaters. It is only by successfully registering yourself as the single thread having upgrade ownership and then blocking on a conversion from upgrade to exclusive, do you enable the implementation to start blocking new searchers from obtaining a shared lock so that you can eventually obtain the exclusive lock as existing searchers are cleared out.

Why should call lock_upgrade() of a boost::thread::shared_mutex block?

I'm studying manual on boost::thread and they say that effect of calling lock_upgrade() of shared_mutex is
"The current thread blocks until upgrade ownership can be obtained for the current thread.".
But why should it block, as upgrade ownership it's not yet an exclusive ownership?
Thank you.
But why should it block, as upgrade ownership it's not yet an exclusive ownership?
If someone already has exclusive ownership, then no-one can obtain shared or upgradable ownership; so lock_shared and lock_upgrade will both block in that situation.
And, as noted in the comments, only one thread can have upgradable ownership; so lock_upgrade will also block if someone already has that.

Differences between Conditional variables, Mutexes and Locks

For example the c++0x interfaces
I am having a hard time figuring out when to use which of these things (cv, mutex and lock).
Can anyone please explain or point to a resource?
Thanks in advance.
On the page you refer to, "mutex" is the actual low-level synchronizing primitive. You can take a mutex and then release it, and only one thread can take it at any single time (hence it is a synchronizing primitive). A recursive mutex is one which can be taken by the same thread multiple times, and then it needs to be released as many times by the same thread before others can take it.
A "lock" here is just a C++ wrapper class that takes a mutex in its constructor and releases it at the destructor. It is useful for establishing synchronizing for C++ scopes.
A condition variable is a more advanced / high-level form of synchronizing primitive which combines a lock with a "signaling" mechanism. It is used when threads need to wait for a resource to become available. A thread can "wait" on a CV and then the resource producer can "signal" the variable, in which case the threads who wait for the CV get notified and can continue execution. A mutex is combined with CV to avoid the race condition where a thread starts to wait on a CV at the same time another thread wants to signal it; then it is not controllable whether the signal is delivered or gets lost.
I'm not too familiar w/ C++0x so take this answer w/ a grain of salt.
re: Mutex vs. locks: From the documentation you posted, it looks like a mutex is an object representing an OS mutex, whereas a lock is an object that holds a mutex to facilitate the RAII pattern.
Condition variables are a handy mechanism to associate a blocking/signaling mechanism (signal+wait) with a mutual exclusion mechanism, yet keep them decoupled in the OS so that you as system programmer can choose the association between condvar and mutex. (useful for dealing with multiple sets of concurrently-accessed objects) Rob Krten has some good explanations on condvars in one of the online chapters of his book on QNX.
As far as general references: This book (not out yet) looks interesting.
This question has been answered. I just add this that may help to decide WHEN to use these synchronization primitives.
Simply, the mutex is used to guarantee mutual access to a shared resource in the critical section of multiple threads. The luck is a general term but a binary mutex can be used as a lock. In modern C++ we use lock_guard and similar objects to utilize RAII to simplify and make safe the mutex usage. The conditional variable is another primitive that often combined with a mutex to make something know as a monitor.
I am having a hard time figuring out when to use which of these things
(cv, mutex and lock). Can anyone please explain or point to a
resource?
Use a mutex to guarantee mutual exclusive access to something. It's the default solution for a broad range of concurrency problems. Use lock_guard if you have a scope in C++ that you want to guard it with a mutex. The mutex is handled by the lock_guard. You just create a lock_guard in the scope and initialize it with a mutex and then C++ does the rest for you. The mutex is released when the scope is removed from the stack, for any reason including throwing an exception or returning from a function. It's the idea behind RAII and the lock_guard is another resource handler.
There are some concurrency issues that are not easily solvable by only using a mutex or a simple solution can lead to complexity or inefficiency. For example, the produced-consumer problem is one of them. If we want to implement a consumer thread reading items from a buffer shared with a producer, we should protect the buffer with a mutex but, without using a conditional variable we should lock the mutex, check the buffer and read an item if it's not empty, unlock it and wait for some time period, lock it again and go on. It's a waste of time if the buffer is often empty (busy waiting) and also there will be lots of locking and unlocking and sleeps.
The solution we need for the producer-consumer problem must be simpler and more efficient. A monitor (a mutex + a conditional variable) helps us here. We still need a mutex to guarantee mutual exclusive access but a conditional variable lets us sleep and wait for a certain condition. The condition here is the producer adding an item to the buffer. The producer thread notifies the consumer thread that there is and item in the buffer and the consumer wakes up and gets the item. Simply, the producer locks the mutex, puts something in the buffer, notifies the consumer. The consumer locks the mutex, sleeps while waiting for a condition, wake s up when there is something in the buffer and gets the item from the buffer. It's a simpler and more efficient solution.
The next time you face a concurrency problem think this way: If you need mutual exclusive access to something, use a mutex. Use lock_guard if you want to be safer and simpler. If the problem has a clue of waiting for a condition that must happen in another thread, you MIGHT need a conditional variable.
As a general rule of thumb, first, analyze your problem and try to find a famous concurrency problem similar to yours (for example, see classic problems of synchronization section in this page). Read about the solutions proposed for the well-known solution to peak the best one. You may need some customization.