I'm trying to replace the boost functionalities with STL functinoalities in C++11.
There is a write function in my multi-thread application.
First, the function verifies the data. Next, writes to it.
There are two locks mentioned as mentioned below:
class Data
{
mutable boost::mutex mut;
void Data::Write()
{
boost::upgrade_lock<boost::shared_mutex> ulock(mut);
// ... Verification statements
boost::upgrade_to_unique_lock<boost::shared_mutex> lock(ulock);
// ... Writing statements
}
};
I'm a novice of boost functionalities. Can you please explain what it does and how I can achieve the functionality with STL features?
C++11 doesn't provide shared locks at all. C++14 does, but doesn't allow them to be upgraded to exclusive locks; you'd need a second mutex for that, something like:
mutable std::shared_timed_mutex read_mutex;
std::mutex write_mutex;
void Write() {
std::shared_lock read_lock(read_mutex);
// ... Verification statements
std::lock_guard write_lock(write_mutex);
// ... Writing statements
}
You'll need to take some care only to acquire the write lock while already holding the read lock, to avoid deadlocks. If you have a working Boost solution, it might be better to stick to that until the standard library provides equivalent functionality.
In C++ threads you get:
#include <thread>
#include <mutex>
using namespace std;
mutex mu;
// lock_guard: acquire the mutex mu and lock it. when the lock_guard object goes out of scope, mutex is unlocked.
lock_guard<mutex> lock(mu);
// more flexible than the lock_guard
// http://en.cppreference.com/w/cpp/thread/unique_lock
unique_lock<mutex> ulock(mu);
ulock.unlock();
ulock.lock();
Related
I have multi-threaded program and it only has 1 mutex. I want to make the program terminate if it attempts to grab the lock if it already has it.
My actual program is pretty complicated. Of course we try to avoid deadlocks on a programming level. But just in case we miss a edge case, we prefer it to fail immediately rather than deadlock.
See a minimal example below.
std::mutex lock;
void f1() {
std::lock_guard<mutex> guard1(lock);
// some code ...
}
void f2() {
std::lock_guard<mutex> guard2(lock);
f1(); // Will deadlock here! How can I make it terminate instead of deadlock?
}
std::mutex provides no mechanism for accomplishing what you describe.
Instead of deadlock detection, you should be looking at deadlock avoidance. Careful programming, including appropriate choice of mutex role and scope, can help. Refactoring could help, too. For example, you could change your example code to
std::mutex lock;
static void f1_impl() {
// some code ...
}
void f1() {
std::lock_guard<mutex> guard1(lock);
f1_impl();
}
void f2() {
std::lock_guard<mutex> guard2(lock);
f1_impl();
}
But if that doesn't get you all the way to where you want to be, then you might want to consider using std::recursive_mutex instead of std::mutex. That addresses the problem by allowing a thread that already holds the mutex locked to lock it again.
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
I've reached a point in my project that requires communication between threads on resources that very well may be written to, so synchronization is a must. However I don't really understand synchronization at anything other than the basic level.
Consider the last example in this link: http://www.bogotobogo.com/cplusplus/C11/7_C11_Thread_Sharing_Memory.php
#include <iostream>
#include <thread>
#include <list>
#include <algorithm>
#include <mutex>
using namespace std;
// a global variable
std::list<int>myList;
// a global instance of std::mutex to protect global variable
std::mutex myMutex;
void addToList(int max, int interval)
{
// the access to this function is mutually exclusive
std::lock_guard<std::mutex> guard(myMutex);
for (int i = 0; i < max; i++) {
if( (i % interval) == 0) myList.push_back(i);
}
}
void printList()
{
// the access to this function is mutually exclusive
std::lock_guard<std::mutex> guard(myMutex);
for (auto itr = myList.begin(), end_itr = myList.end(); itr != end_itr; ++itr ) {
cout << *itr << ",";
}
}
int main()
{
int max = 100;
std::thread t1(addToList, max, 1);
std::thread t2(addToList, max, 10);
std::thread t3(printList);
t1.join();
t2.join();
t3.join();
return 0;
}
The example demonstrates how three threads, two writers and one reader, accesses a common resource(list).
Two global functions are used: one which is used by the two writer threads, and one being used by the reader thread. Both functions use a lock_guard to lock down the same resource, the list.
Now here is what I just can't wrap my head around: The reader uses a lock in a different scope than the two writer threads, yet still locks down the same resource. How can this work? My limited understanding of mutexes lends itself well to the writer function, there you got two threads using the exact same function. I can understand that, a check is made right as you are about to enter the protected area, and if someone else is already inside, you wait.
But when the scope is different? This would indicate that there is some sort of mechanism more powerful than the process itself, some sort of runtime environment blocking execution of the "late" thread. But I thought there were no such things in c++. So I am at a loss.
What exactly goes on under the hood here?
Let’s have a look at the relevant line:
std::lock_guard<std::mutex> guard(myMutex);
Notice that the lock_guard references the global mutex myMutex. That is, the same mutex for all three threads. What lock_guard does is essentially this:
Upon construction, it locks myMutex and keeps a reference to it.
Upon destruction (i.e. when the guard's scope is left), it unlocks myMutex.
The mutex is always the same one, it has nothing to do with the scope. The point of lock_guard is just to make locking and unlocking the mutex easier for you. For example, if you manually lock/unlock, but your function throws an exception somewhere in the middle, it will never reach the unlock statement. So, doing it the manual way you have to make sure that the mutex is always unlocked. On the other hand, the lock_guard object gets destroyed automatically whenever the function is exited – regardless how it is exited.
myMutex is global, which is what is used to protect myList. guard(myMutex) simply engages the lock and the exit from the block causes its destruction, dis-engaging the lock. guard is just a convenient way to engage and dis-engage the lock.
With that out of the way, mutex does not protect any data. It just provides a way to protect data. It is the design pattern that protects data. So if I write my own function to modify the list as below, the mutex cannot protect it.
void addToListUnsafe(int max, int interval)
{
for (int i = 0; i < max; i++) {
if( (i % interval) == 0) myList.push_back(i);
}
}
The lock only works if all pieces of code that need to access the data engage the lock before accessing and disengage after they are done. This design-pattern of engaging and dis-engaging the lock before and after every access is what protects the data (myList in your case)
Now you would wonder, why use mutex at all, and why not, say, a bool. And yes you can, but you will have to make sure that the bool variable will exhibit certain characteristics including but not limited to the below list.
Not be cached (volatile) across multiple threads.
Read and write will be atomic operation.
Your lock can handle situation where there are multiple execution pipelines (logical cores, etc).
There are different synchronization mechanisms that provide "better locking" (across processes versus across threads, multiple processor versus, single processor, etc) at a cost of "slower performance", so you should always choose a locking mechanism which is just about enough for your situation.
Just to add onto what others here have said...
There is an idea in C++ called Resource Acquisition Is Initialization (RAII) which is this idea of binding resources to the lifetime of objects:
Resource Acquisition Is Initialization or RAII, is a C++ programming technique which binds the life cycle of a resource that must be acquired before use (allocated heap memory, thread of execution, open socket, open file, locked mutex, disk space, database connection—anything that exists in limited supply) to the lifetime of an object.
C++ RAII Info
The use of a std::lock_guard<std::mutex> class follows the RAII idea.
Why is this useful?
Consider a case where you don't use a std::lock_guard:
std::mutex m; // global mutex
void oops() {
m.lock();
doSomething();
m.unlock();
}
in this case, a global mutex is used and is locked before the call to doSomething(). Then once doSomething() is complete the mutex is unlocked.
One problem here is what happens if there is an exception? Now you run the risk of never reaching the m.unlock() line which releases the mutex to other threads.
So you need to cover the case where you run into an exception:
std::mutex m; // global mutex
void oops() {
try {
m.lock();
doSomething();
m.unlock();
} catch(...) {
m.unlock(); // now exception path is covered
// throw ...
}
}
This works but is ugly, verbose, and inconvenient.
Now lets write our own simple lock guard.
class lock_guard {
private:
std::mutex& m;
public:
lock_guard(std::mutex& m_):(m(m_)){ m.lock(); } // lock on construction
~lock_guard() { t.unlock(); }} // unlock on deconstruction
}
When the lock_guard object is destroyed, it will ensure that the mutex is unlocked.
Now we can use this lock_guard to handle the case from before in a better/cleaner way:
std::mutex m; // global mutex
void ok() {
lock_guard lk(m); // our simple lock guard, protects against exception case
doSomething();
} // when scope is exited our lock guard object is destroyed and the mutex unlocked
This is the same idea behind std::lock_guard.
Again this approach is used with many different types of resources which you can read more about by following the link on RAII.
This is precisely what a lock does. When a thread takes the lock, regardless of where in the code it does so, it must wait its turn if another thread holds the lock. When a thread releases a lock, regardless of where in the code it does so, another thread may acquire that lock.
Locks protect data, not code. They do it by ensuring all code that accesses the protected data does so while it holds the lock, excluding other threads from any code that might access that same data.
Imagine you have a big function that locks/unlocks a mutex inside and you want to break the function into smaller functions:
#include <pthread.h>
class MyClass : public Uncopyable
{
public:
MyClass() : m_mutexBuffer(PTHREAD_MUTEX_INITIALIZER), m_vecBuffer() {}
~MyClass() {}
void MyBigFunction()
{
pthread_mutex_lock(&m_mutexBuffer);
if (m_vecBuffer.empty())
{
pthread_mutex_unlock(&m_mutexBuffer);
return;
}
// DoSomethingWithBuffer1();
unsigned char ucBcc = CalculateBcc(&m_vecBuffer[0], m_vecBuffer.size());
// DoSomethingWithBuffer2();
pthread_mutex_unlock(&m_mutexBuffer);
}
private:
void DoSomethingWithBuffer1()
{
// Use m_vecBuffer
}
void DoSomethingWithBuffer2()
{
// Use m_vecBuffer
}
private:
pthread_mutex_t m_mutexBuffer;
std::vector<unsigned char> m_vecBuffer;
};
How should I go about locking/unlocking the mutex inside the smaller functions?
Should I unlock the mutex first, then lock it straightaway and finally unlock it before returning?
void DoSomethingWithBuffer1()
{
pthread_mutex_unlock(&m_mutexBuffer);
pthread_mutex_lock(&m_mutexBuffer);
// Use m_vecBuffer
pthread_mutex_unlock(&m_mutexBuffer);
}
How should I go about locking/unlocking the mutex inside the smaller functions?
If your semantics require your mutex to be locked during the whole MyBigFunction() operation then you can't simply unlock it and relock it in the middle of the function.
My best bet would be to ignore the mutex in the smaller DoSomethingWithBuffer...() functions, and simply require that these functions are called with the mutex being already locked. This shouldn't be a problem since those functions are private.
On a side note, your mutex usage is incorrect: it is not exception safe, and you have code paths where you don't release the mutex. You should either use C++11's mutex and lock classes or boost's equivalents if you are using C++03. At worst if you can't use boost, write a small RAII wrapper to hold the lock.
In general, try to keep the regions of code within each lock to a minimum (to avoid contention), but avoid to unlock and immediatly re-lock the same mutex. Thus, if the smaller functions are not mutually exclusive, they should both use their own indepdenent mutices and only when they actually access the shared resource.
Another thing that should consider is to use RAII for locking and unlocking (as in C++11 with std::lock_guard<>), so that returning from a locked region (either directly or via an uncaught exception) does not leave you in a locked state.
Is there a way to ensure that blocked threads get woken up in the same order as they got blocked? I read somewhere that this would be called a "strong lock" but I found no resources on that.
On Mac OS X one can design a FIFO queue that stores all the thread ids of the blocked threads and then use the nifty function pthread_cond_signal_thread_np() to wake up one specific thread - which is obviously non-standard and non-portable.
One way I can think of is to use a similar queue and at the unlock() point send a broadcast() to all threads and have them check which one is the next in line.
But this would induce lots of overhead.
A way around the problem would be to issue packaged_task's to the queue and have it process them in order. But that seems more like a workaround to me than a solution.
Edit:
As pointed out by the comments, this question may sound irrelevant, since there is in principle no guaranteed ordering of locking attempts.
As a clarification:
I have something I call a ConditionLockQueue which is very similar to the NSConditionLock class in the Cocoa library, but it maintains a FIFO queue of blocked threads instead of a more-or-less random pool.
Essentially any thread can "line up" (with or without the requirement of a specific 'condition' - a simple integer value - to be met). The thread is then placed on the queue and blocks until it is the frontmost element in the queue whose condition is met.
This provides a very flexible way of synchronization and I have found it very helpful in my program.
Now what I really would need is a way to wake up a specific thread with a specific id.
But these problems are almost alike.
Its pretty easy to build a lock object that uses numbered tickets to insure that its completely fair (lock is granted in the order threads first tried to acquire it):
#include <mutex>
#include <condition_variable>
class ordered_lock {
std::condition_variable cvar;
std::mutex cvar_lock;
unsigned int next_ticket, counter;
public:
ordered_lock() : next_ticket(0), counter(0) {}
void lock() {
std::unique_lock<std::mutex> acquire(cvar_lock);
unsigned int ticket = next_ticket++;
while (ticket != counter)
cvar.wait(acquire);
}
void unlock() {
std::unique_lock<std::mutex> acquire(cvar_lock);
counter++;
cvar.notify_all();
}
};
edit
To fix Olaf's suggestion:
#include <mutex>
#include <condition_variable>
#include <queue>
class ordered_lock {
std::queue<std::condition_variable *> cvar;
std::mutex cvar_lock;
bool locked;
public:
ordered_lock() : locked(false) {};
void lock() {
std::unique_lock<std::mutex> acquire(cvar_lock);
if (locked) {
std::condition_variable signal;
cvar.emplace(&signal);
signal.wait(acquire);
} else {
locked = true;
}
}
void unlock() {
std::unique_lock<std::mutex> acquire(cvar_lock);
if (cvar.empty()) {
locked = false;
} else {
cvar.front()->notify_one();
cvar.pop();
}
}
};
I tried Chris Dodd solution
https://stackoverflow.com/a/14792685/4834897
but the compiler returned errors because queues allows only standard containers that are capable.
while references (&) are not copyable as you can see in the following answer by Akira Takahashi :
https://stackoverflow.com/a/10475855/4834897
so I corrected the solution using reference_wrapper which allows copyable references.
EDIT: #Parvez Shaikh suggested small alteration to make the code more readable by moving cvar.pop() after signal.wait() in lock() function
#include <mutex>
#include <condition_variable>
#include <queue>
#include <atomic>
#include <vector>
#include <functional> // std::reference_wrapper, std::ref
using namespace std;
class ordered_lock {
queue<reference_wrapper<condition_variable>> cvar;
mutex cvar_lock;
bool locked;
public:
ordered_lock() : locked(false) {}
void lock() {
unique_lock<mutex> acquire(cvar_lock);
if (locked) {
condition_variable signal;
cvar.emplace(std::ref(signal));
signal.wait(acquire);
cvar.pop();
} else {
locked = true;
}
}
void unlock() {
unique_lock<mutex> acquire(cvar_lock);
if (cvar.empty()) {
locked = false;
} else {
cvar.front().get().notify_one();
}
}
};
Another option is to use pointers instead of references, but it seems less safe.
Are we asking the right questions on this thread??? And if so: are they answered correctly???
Or put another way:
Have I completely misunderstood stuff here??
Edit Paragraph: It seems StatementOnOrder (see below) is false. See link1 (C++ threads etc. under Linux are ofen based on pthreads), and link2 (mentions current scheduling policy as the determining factor) -- Thanks to Cubbi from cppreference (ref). See also link, link, link, link. If the statement is false, then the method of pulling an atomic (!) ticket, as shown in the code below, is probably to be preferred!!
Here goes...
StatementOnOrder: "Multiple threads that run into a locked mutex and thus "go to sleep" in a particular order, will afterwards aquire ownership of the mutex and continue on in the same order."
Question: Is StatementOnOrder true or false ???
void myfunction() {
std::lock_guard<std::mutex> lock(mut);
// do something
// ...
// mutex automatically unlocked when leaving funtion.
}
I'm asking this because all code examples on this page to date, seem to be either:
a) a waste (if StatementOnOrder is true)
or
b) seriously wrong (if StatementOnOrder is false).
So why do a say that they might be "seriously wrong", if StatementOnOrder is false?
The reason is that all code examples think they're being super-smart by utilizing std::condition_variable, but are actually using locks before that, which will (if StatementOnOrder is false) mess up the order!!!
Just search this page for std::unique_lock<std::mutex>, to see the irony.
So if StatementOnOrder is really false, you cannot run into a lock, and then handle tickets and condition_variables stuff after that. Instead, you'll have to do something like this: pull an atomic ticket before running into any lock!!!
Why pull a ticket, before running into a lock? Because here we're assuming StatementOnOrder to be false, so any ordering has to be done before the "evil" lock.
#include <mutex>
#include <thread>
#include <limits>
#include <atomic>
#include <cassert>
#include <condition_variable>
#include <map>
std::mutex mut;
std::atomic<unsigned> num_atomic{std::numeric_limits<decltype(num_atomic.load())>::max()};
unsigned num_next{0};
std::map<unsigned, std::condition_variable> mapp;
void function() {
unsigned next = ++num_atomic; // pull an atomic ticket
decltype(mapp)::iterator it;
std::unique_lock<std::mutex> lock(mut);
if (next != num_next) {
auto it = mapp.emplace(std::piecewise_construct,
std::forward_as_tuple(next),
std::forward_as_tuple()).first;
it->second.wait(lock);
mapp.erase(it);
}
// THE FUNCTION'S INTENDED WORK IS NOW DONE
// ...
// ...
// THE FUNCTION'S INDENDED WORK IS NOW FINISHED
++num_next;
it = mapp.find(num_next); // this is not necessarily mapp.begin(), since wrap_around occurs on the unsigned
if (it != mapp.end()) {
lock.unlock();
it->second.notify_one();
}
}
The above function guarantees that the order is executed according to the atomic ticket that is pulled. (Edit: using boost's intrusive map, an keeping condition_variable on the stack (as a local variable), would be a nice optimization, which can be used here, to reduce free-store usage!)
But the main question is:
Is StatementOnOrder true or false???
(If it is true, then my code example above is a also waste, and we can just use a mutex and be done with it.)
I wish somebody like Anthony Williams would check out this page... ;)