I'm trying to understand std::mutex, std::lock_guard, std::unique_lock better when working with a class.
For starters I sort of know the difference between lock_guard and unique_lock: I know that lock_guard only locks the mutex on construction which is a preferred use when using it in a class member function as such:
class Foo {
std::mutex myMutex;
public:
void someFunc() {
std::lock_guard<std::mutex> guard( myMutex );
// code
}
};
As in the above the lock_guard with the class's member myMutex will be locked in the beginning of the scope of the function Foo::someFunc() then unlocked after the code leaves the scope due to the destructors of both lock_guard and mutex.
I also understand that unique_lock allows you to lock & unlock a mutex multiple times.
My question is about a design of a class to where; what If I want the mutex to be locked in the constructor of the class, then not to have it unlock when the constructor goes out of scope, but to unlock when the destructor of the class is called...
class Foo {
std::mutex myMutex;
public:
Foo() {
// lock mutex here;
}
~Foo() {
// unlock mutex here;
}
};
Can the above be achieved; and if so how?
In the last example above what I'm not sure about is: if a lock_guard is used in the constructor of the class; will it go out of scope after the constructor leaves scope, or when the class's destructor is invoked when the object of the class goes out of scope? I like to try to mimic the desired behavior of the 2nd example shown.
After I had posted this question: I did a little more research and some trial and errors. With that I have opted towards a different implementation and solution.
Instead of what I was originally proposing, I ended up using std::shared_mutex and std:shared_lock.
So in my class's header I'm not saving or storing any mutex. Now in my class's cpp file. I'm using a static global shared_mutex
So my class now looks like this:
Foo.cpp
#include "Foo.h"
#include <mutex>
std::mutex g_mutex;
Foo::Foo() {
// code not locked
{ // scope of guard
std::lock_guard<std::mutex> lock( g_mutex );
// code to lock
} // end scope destroy guard unlock mutex
// other class code
}
Foo::someFunc() {
// Code to lock
std::lock_guard<std::mutex> lock( g_mutex );
}
I had discovered why it wasn't working properly for me. In my class's constructor it was calling a function from its parent or base class. The parent or base class was then calling a static member of this class and the static member function of this class was also using lock_guard on the same mutex.
After I found the problem; I had two options. I could of used 2 independent mutexes, one for the constructor specifically and one for the static method specifically. After some thought I figured well if I use 2, and I'm blocking the full constructor the current lock and mutex won't go out of scope until the class instance is destroyed; however the life of the class will be nearly the full life of the application. Then if I used a second mutex and lock guard within the static method, it would be redundant to wrap another lock_guard around an existing one. So I came to the conclusion that I needed to create a scoped block { } for the code that needed to be blocked by the mutex so that it can be unlocked after this section goes out of scope, then the constructor is free to call the static method and it can reuse the same mutex as it is now free. The class is now working properly and it is not crashing nor throwing exceptions when it shouldn't be.
Related
I have singleton object shared between two units operating on seperate threads.
For example,
Thread A
Singleton.getInstace().incCounter();
Thread B
Singleton.getInstance().decCounter();
Is it possible to implement this atomics to be thread safe without bothering the consumers to do it in thread safe way.
Something like
static Singleton& GetInstance() {
std::scoped_lock lock(m_mtx);
static Singleton* singleton = new Singleton();
return *singleton;
}
I guess this will not work as the lock will be released after the return but incCounter and decCounter will be called without the lock.
Is it somehow possible to keep the lock active till atomic operation is completed.
Is doing a lock within the incCounter and decCounter the only solution here or in unit A and unit B only solution.
The current lock accomplishes nothing. A static function-local variable is required by the C++ standard to be initialized in exactly one thread. That is, the compiler will ensure that there can be no race conditions on its initialization. So the lock is protecting against something that can't happen.
You need to put a lock in the increment/decrement functions. And they need to lock the same mutex. Though perhaps they could increment/decrement an atomic variable, in which case you don't need a lock at all.
You could (but probably shouldn't) create a new type LockedSingleton which stores a reference to the singleton and a std::unique_lock. This would be what your GetInstance() returns. LockedSingleton would need to have its own increment/decrement functions which it forwards to its internal singleton reference, as well as any other interface functions.
class LockedSingleton
{
private:
std::unique_lock<std::mutex> lock_;
Singleton &obj_;
private: //Only friends can construct. Also, non-copyable.
LockedSingleton(std::mutex &mtx, Singleton &obj)
: lock_(mtx)
, obj_(obj)
{}
friend Singleton& GetInstance();
public:
void incCounter() {obj.incCounter();}
void decCounter() {obj.decCounter();}
};
static LockedSingleton GetInstance() {
static Singleton* singleton = new Singleton();
return LockedSingleton(m_mtx, *singleton);
}
Note that this only works in C++17 and above, due to guaranteed elision, since LockedSingleton is non-copyable.
I am reading Effective C++, in Rule 14: Think carefully about copying behavior in resource-managing classes, there is an example:
class Lock {
public:
explicit Lock(Mutex* pm) : mutexPtr(pm) {
lock(mutexPtr);
}
~Lock() {
unlock(mutexPtr);
}
private:
Mutex *mutexPtr;
};
It points out that if we construct the Lock as above, there will be a problem if we run the code below:
Mutex m;
Lock ml1(&m);
Lock ml2(ml1);
I think it may because the code may runs like below:
// ml1 constructes
lock(m)
// copy ml2, but ml1.mutexPtr and ml2.mutexPtr both point to m
ml2.mutexPtr = ml1.mutexPtr
// ml1 destructs
unlock(m)
// ml2 destructs
unlock(m)
So the m will be unlock for twice. So is it the real reason that cause the problem below? thx!
Yes, that is why the author is saying to be careful. If you use a recursive_mutex instead of plain mutex you can simply lock in the copy ctor and copy-assign operator, but if it's a non-recursive mutex it would likely be better to make the lock type non-copyable.
I need to lock object by private mutex in some external functions. What is the best way to do this?
I want something like this
#include <thread>
#include <mutex>
class Test
{
public:
std::lock_guard<std::mutex> lockGuard()
{
return std::lock_guard<std::mutex>(mutex);
}
private:
std::mutex mutex;
};
int main()
{
Test test;
std::lock_guard<std::mutex> lock = test.lockGuard();
//...
}
But lock_guard copy contructor is deleted. How can I do something like this?
Just use std::unique_lock<std::mutex> instead. It is not copyable, but it is movable, allowing the pattern you show.
#include <thread>
#include <mutex>
class Test
{
public:
std::unique_lock<std::mutex> lockGuard()
{
return std::unique_lock<std::mutex>(mutex);
}
private:
std::mutex mutex;
};
int main()
{
Test test;
std::unique_lock<std::mutex> lock = test.lockGuard();
//...
}
std::unique_lock<std::mutex> has a broadened API relative to std::lock_guard including:
Move constructible.
Move assignable.
Swappable.
lock()
unlock()
try_lock()
try_lock_for()
try_lock_until()
release()
owns_lock()
In other words, since you can unlock and move from a unique_lock, it is not guaranteed to hold the lock on the mutex (you can check that it does with owns_lock()). In contrast an invariant of lock_guard is that it always holds the lock on the mutex.
The std::unique_lock<T> has a move constructor defined and can be used as you like, but the approach is not very successful itself.
You should review your locking granularity, usually if you can't provide internal synchronization and ask user to maintain lock while performing operations (or when you need to perform multiple operations) on an object, there is no reason to store the mutex inside the object.
If I had to store the mutex inside object, I would use some wrapper which allows me to do the following:
locking_wrapper<Test> test;
test.do_locked([] (Test & instance) {
/* The following code is guaranteed not to interleave with
* any operations performed on instance from other threads. */
// your code using instance here
});
The locking_wrapper<T> would store store an instance of an object inside and provide a reference to it while maintaining a lock on internal mutex. Relying on the compiler's ability to inline code, such approach should give no overhead above what you're trying to do in your question.
The general idea on implementing the locking_wrapper is as follows:
template<typename T>
class locking_wrapper
{
mutable std::mutex mutex;
// the object which requires external synchronization on access
T instance;
public:
/* Here we define whatever constructors required to construct the
* locking_wrapper (e.g. value-initialize the instance, take an
* instance passed by user or something different) */
locking_wrapper() = default;
locking_wrapper(const T & instance) : instance{instance} {}
// Takes a functor to be performed on instance while maintaining lock
template<typename Functor>
void do_locked(Functor && f) const {
const std::lock_guard<std::mutex> lock{mutex};
f(instance);
}
};
You may pass whatever callable-entity to do_locked as you see fit, however calling it with a lambda-expression as I've suggested previously will give it the best chances to be inlined without any overhead.
Please note that using this approach with references, movable objects or some other kind I have not yet foreseen would require some modifications to the code.
If I have to write a singleton class in C++ I will be using a static variable, private constructor & a public static function that returns an object of class. However in Multithreaded environments the code will have problems. In order to avoid multiple threads access the same variable at the same time, is Boost threads best mechanism to use for synchronization? I mean for setting/unsetting a lock/mutex across the resource. Is there anything else inbuilt in C++ standard library where in I dont have to download boost, build stuff etc? I have heard of C++ Ox but dont know much.
C++98/03 have nothing to support threads at all. If you're using a C++98 or 03 compiler, you're pretty much stuck with using Boost, or something (more or less) OS-specific, such as pthreads or Win32's threading primitives.
C++11 has a reasonably complete thread support library, with mutexes, locks, thread-local storage, etc.
I feel obliged to point out, however, that it may be better to back up and do a bit more thinking about whether you need/want a Singleton at all. To put it nicely, the singleton pattern has fallen out of favor to a large degree.
Edit: Rereading this, I kind of skipped over one thing I'd intended to say: at least when I've used them, any/all singletons were fully initialized before any secondary thread was started. That renders concern over thread safety in their initialization completely moot. I suppose there could be a singleton that you can't initialize before you start up secondary threads so you'd need to deal with this, but at least right off it strikes me as a rather unusual exception that I'd deal with only when/if absolutely necessary.
For me the best way to implement a singleton using c++11 is:
class Singleton
{
public:
static Singleton & Instance()
{
// Since it's a static variable, if the class has already been created,
// It won't be created again.
// And it **is** thread-safe in C++11.
static Singleton myInstance;
// Return a reference to our instance.
return myInstance;
}
// delete copy and move constructors and assign operators
Singleton(Singleton const&) = delete; // Copy construct
Singleton(Singleton&&) = delete; // Move construct
Singleton& operator=(Singleton const&) = delete; // Copy assign
Singleton& operator=(Singleton &&) = delete; // Move assign
// Any other public methods
protected:
Singleton()
{
// Constructor code goes here.
}
~Singleton()
{
// Destructor code goes here.
}
// And any other protected methods.
}
This is a c++11 feature but with this way you can create a thread safe Singleton. According to new standard there is no need to care about this problem any more. Object initialization will be made only by one thread, other threads will wait till it complete. Or you can use std::call_once.
If you want to make a exclusive access to the singleton's resources you have to use a lock at these functions.
The different type of locks:
Using atomic_flg_lck:
class SLock
{
public:
void lock()
{
while (lck.test_and_set(std::memory_order_acquire));
}
void unlock()
{
lck.clear(std::memory_order_release);
}
SLock(){
//lck = ATOMIC_FLAG_INIT;
lck.clear();
}
private:
std::atomic_flag lck;// = ATOMIC_FLAG_INIT;
};
Using atomic:
class SLock
{
public:
void lock()
{
while (lck.exchange(true));
}
void unlock()
{
lck = true;
}
SLock(){
//lck = ATOMIC_FLAG_INIT;
lck = false;
}
private:
std::atomic<bool> lck;
};
Using mutex:
class SLock
{
public:
void lock()
{
lck.lock();
}
void unlock()
{
lck.unlock();
}
private:
std::mutex lck;
};
Just for Windows:
class SLock
{
public:
void lock()
{
EnterCriticalSection(&g_crit_sec);
}
void unlock()
{
LeaveCriticalSection(&g_crit_sec);
}
SLock(){
InitializeCriticalSectionAndSpinCount(&g_crit_sec, 0x80000400);
}
private:
CRITICAL_SECTION g_crit_sec;
};
The atomic and and atomic_flg_lck keep the thread in a spin count. Mutex just sleeps the thread. If the wait time is too long maybe is better sleep the thread. The last one "CRITICAL_SECTION" keeps the thread in a spin count until a time is consumed, then the thread goes to sleep.
How to use these critical sections?
unique_ptr<SLock> raiilock(new SLock());
class Smartlock{
public:
Smartlock(){ raiilock->lock(); }
~Smartlock(){ raiilock->unlock(); }
};
Using the raii idiom. The constructor to lock the critical section and the destructor to unlock it.
Example
class Singleton {
void syncronithedFunction(){
Smartlock lock;
//.....
}
}
This implementation is thread safe and exception safe because the variable lock is saved in the stack so when the function scope is ended (end of function or an exception) the destructor will be called.
I hope that you find this helpful.
Thanks!!
Currently I want to make wrapper accessor class in multithreaded environment. The purpose of the class is simple - Grab a lock on its construction and release a lock on its destruction. Other than that, it's identical to a normal pointer. Moreover, I want to prevent it from being created on heap area to ensure that the lock will be released eventually.
The inverse is fairly easy (private constructor with factory method), but I don't know that a stack-only variable is possible. Is there anyway?
Well, what about you overload operator new for your class and delcare it private?
I don't understand the problem? Any variable defined within the scope of a function is stack-only.
class Lock {
public:
Lock() {
performLock();
}
~Lock() {
performUnlock();
}
}
void foo() {
// ... Code
Lock onStackOnly;
// ... Code that is locked
}
void foo() {
// ... Code
{
Lock onStackOnly;
// ... Code that is locked
}
// This code is unlocked.
}