Have an object on stack not for the entire lifetime of the function - c++

I have a function foo() that acquires a critical section does some processing and releases the critical section.Now there are multiple control flows so in order to avoid remembering to release the lock i thought of wrapping it up in a class, so that the destructor would automatically free the lock.
class Lock
{
public:
LPCRITICAL_SECTION m_a;
Lock(CRITICAL_SECTION *a):m_a(a){EnterCriticalSection(a);}
~Lock(){LeaveCriticalSection(m_a);}
};
Now the problem is that i have control flows where i want to acquire the lock, do something and then free it, and then continue other processing.So i don't want to wait to free the lock till function ends when the destruction would kick in.Is there a way to achieve this.

Use a local block:
void myFunction() {
// do stuff
{
Lock l(&critsec);
// do stuff needing lock
}
// do more stuff
}

Related

make function exception-safe

In my multithreaded server I have somefunction(), which needs to protect two independent of each other global data using EnterCriticalSection.
somefunction()
{
EnterCriticalSection(&g_List);
...
EnterCriticalSection(&g_Variable);
...
LeaveCriticalSection(&g_Variable);
...
LeaveCriticalSection(&g_List);
}
Following the advice of better programmers i'm going to use a RAII wrapper. For example:
class Locker
{
public:
Locker(CSType& cs): m_cs(cs)
{
EnterCriticalSection(&m_cs);
}
~Locker()
{
LeaveCriticalSection(&m_cs);
}
private:
CSType& m_cs;
}
My question: Is it ok to transform somefunction() to this?
(putting 2 Locker in one function):
somefunction()
{
// g_List,g_Variable previously initialized via InitializeCriticalSection
Locker lock(g_List);
Locker lock(g_Variable);
...
...
}
?
Your current solution has potential dead lock case. If you have two (or more) CSTypes which will be locked in different order this way, you will end up in dead lock. Best way would be to lock them both atomically. You can see an example of this in boost thread library. shared_lock and unique_lock can be used in deferred mode so that first you prepare all raii objects for all mutex objects, and then lock them all atomically in one call to lock function.
As long as you keep lock order the same in your threads its OK. Do you really need to lock them both at the same time? Also with scoped lock you can add scopes to control when to unlock, something like this:
{
// use inner scopes to control lock duration
{
Locker lockList (g_list);
// do something
} // unlocked at the end
Locker lockVariable (g_variable);
// do something
}

Locking/unlocking mutex inside private functions

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.

What could cause a deadlock of a single write/multiple read lock?

I have a class instance that is used by several other classes in other threads to communicate.
This class uses a slim reader/writer lock (WinAPI's SRWLOCK) as a synchronization object and a couple of RAII helper classes to actually lock/unlock the thing:
static unsigned int readCounter = 0;
class CReadLock
{
public:
CReadLock(SRWLOCK& Lock) : m_Lock(Lock) { InterlockedIncrement(&readCounter); AcquireSRWLockShared(&m_Lock); }
~CReadLock() {ReleaseSRWLockShared(m_Lock); InterlockedDecrement(&readCounter);}
private:
SRWLOCK& m_Lock;
};
class CWriteLock
{
public:
CWriteLock(SRWLOCK& Lock) : m_Lock(Lock) { AcquireSRWLockExclusive(&m_Lock); }
~CWriteLock() { ReleaseSRWLockExclusive(&m_Lock); }
private:
SRWLOCK& m_Lock;
};
The problem is the whole thing deadlocks all the time. When I pause the deadlocked program, I see:
one thread stuck in AcquireSRWLockExclusive();
two threads stuck in AcquireSRWLockShared();
readCounter global is set to 3.
The way I see it, the only way for this to happen is CReadLock instance's destructor hasn't been called somehow somewhere so the lock is perpetually stuck. However, the only way for this to happen (as far as I know) is because an exception has been thrown. It wasn't. I checked.
What might be the problem? How should I go about fixing (or at least locating the reason of) this thing?
Are you using Read lock in recursive manner?
void foo()
{
CReadLock rl(m_lock);
...
bar();
}
void bar()
{
CReadLock rl(m_lock);
...
}
void baz()
{
CWritedLock rl(m_lock);
...
}
if foo() and baz() are called simultaneously you may get deadlock:
1. (Thread A) foo locks
2. (Thread B) baz asks to create write lock now all read locks would block until all are released - waits.
3. (Thread A) bar tries to lock and waits because there is pending write lock
The fact that you have 2 threads stuck on Read lock and Read Lock counter is 3 that most likely shows that you have a recursion in one of the locks - i.e. one thread had tried to acquired read lock twice.
one thread stuck in AcquireSRWLockExclusive();
two threads stuck in AcquireSRWLockShared();
readCounter global is set to 3.
Well, as far as I can read from it, you have one thread holding the read lock currently, one write thread waiting for that read lock to be released, and two read threads waiting for that write thread to get and release the lock.
In other words, you have one dangling read thread, which has not bee destructed, like you say yourself. Add debug print to destructor and constructor.

Threading C++ lock

I need some synchronous mechanism for thread. I am wondering the implementation below which one is a better way?
classA{
public:
int sharedResourceA;
pthread_mutex_t mutex1;
functionA();
int nonSharedResources;
}
classA::functionA(){
pthread_mutex_lock( &mutex1 );
use sharedResourceA;
pthread_mutex_unlock( &mutex1 );
}
classA objA;
pthread_mutex_lock(&objA.mutex1) //use lock because another thread can call obj.functionA
use objA.sharedResources;
pthread_mutex_unlock(&objA.mutex1)
use objA.nonSharedResources = blah //without lock because is non shared
OR I shouldn't create a lock at classA, instead I create a lock at the application. Eg:
classA objA;
pthread_mutex_t mutex2;
pthread_mutex_lock(mutex2) //use lock because another thread can call obj.functionA
use objA.sharedResources;
pthread_mutex_unlock(mutex2)
pthread_mutex_lock(mutex2) //use lock because another thread can call obj.functionA
functionA();
pthread_mutex_unlock(mutex2)
use objA.nonSharedResources = blah //without lock because is non shared
First - the idiomatic way for doing locks in c++ is to create a lock class that uses RAII.
Then you can go
Lock l(mutex1);
// do stuff under mutex1 lock;
// Lock is freed at end of scope
(I bet boost has a lock, we made our own)
Second. (the scope question). If class A uses shared resources internally then it should lock them internally. Otherwise
how does a caller know to do it
how can you be sure they did it
what if you change the implementation
The application level lock should be used when the caller is the one using the shared resources and is composing something larger that uses classA, funcX and file W. Note that classA may still have its own internal lock in this case
If functionA uses some shared resources, it should ensure that it's accessing them in correct way - i.e. ensure thread safety. That is a vote for the first option you presented.
There are more efficient ways to use mutexes: see boost::recursive_mutex and boost::recursive_mutex::scoped_lock. Using this you can ensure that even if something in critical section throws, your mutex will be unlocked. For example:
using namespace boost;
struct C
{
function f ()
{
//non critical section
//...
//critical section
{
//acquire the mutex
recursive_mutex::scoped_lock lock(mutex);
//do whatever you want. Can throw if it needs to:)
}//exiting the scope causes the mutex to be released
//non critical section again
}
private:
recursive_mutex mutex;
}
I would say the first one is better because if you need to instantiate ClassA more than once, you'll need do create as many global locks for the second solution.
It also respect object encapsulation if you do it inside the class and hides usage of the protected resource behind method. Also, if the shared resource ever becomes not shared, you have the class methods to change in the code instead of refactoring each and every usage of the resource if you use global locks.

Simple Thread Synchronization

I need a simple "one at a time" lock on a section of code. Consider the function func which can be run from multiple threads:
void func()
{
// locking/mutex statement goes here
operation1();
operation2();
// corresponding unlock goes here
operation3();
}
I need to make sure that operation1 and operation2 always run "together". With C# I would use a simple lock block around these two calls. What is the C++/Win32/MFC equivalent?
Presumably some sort of Mutex?
Improving Michael solution above for C++.
Michael solution is perfect for C applications. But when used in C++ this style is discouraged because of the possibility of exceptions. If an exception happens in operation1 or operation2 then the critical section will not be correctly left and all other threads will block waiting.
// Perfect solution for C applications
void func()
{
// cs previously initialized via InitializeCriticalSection
EnterCriticalSection(&cs);
operation1();
operation2();
LeaveCriticalSection(&cs);
operation3();}
}
// A better solution for C++
class Locker
{
public:
Locker(CSType& cs): m_cs(cs)
{
EnterCriticalSection(&m_cs);
}
~Locker()
{
LeaveCriticalSection(&m_cs);
}
private:
CSType& m_cs;
}
void func()
{
// cs previously initialized via InitializeCriticalSection
{
Locker lock(cs);
operation1();
operation2();
}
operation3();
}
Critical sections will work (they're lighter-weight that mutexes.) InitializeCriticalSection, EnterCriticalSection, LeaveCriticalSection, and DeleteCriticalSection are the functions to look for on MSDN.
void func()
{
// cs previously initialized via InitializeCriticalSection
EnterCriticalSection(&cs);
operation1();
operation2();
LeaveCriticalSection(&cs);
operation3();}
}
EDIT:
Critical sections are faster than mutexes since critical sections are primarily user mode primitives - in the case of an uncontended acquire (usually the common case) there is no system call into the kernel, and acquiring takes on the order of dozens of cycles. A kernel switch is more more expensive (on the order of hundreds of cycles). The only time critical sections call into the kernel is in order to block, which involves waiting on a kernel primitive, (either mutex or event). Acquiring a mutex always involves a call into the kernel, and is thus orders of magnitude slower.
However, critical sections can only be used to synchronize resources in one process. In order to synchronize across multiple processes, a mutex is needed.
The best method would be to use a critical section, use EnterCriticalSection and LeaveCriticalSection. The only ticky part is that you need to initialize a critical section first with InitializeCriticalSection. If this code is within a class, put the initialization in the constructor and the CRITICAL_SECTION data structure as a member of the class. If the code is not part of a class, you need to likely use a global or something similiar to ensure it is initialized once.
using MFC:
Define a synchronization object. ( Mutext or Critical section)
1.1 If multiple threads belonging to different process enters the
func() then use CMutex.
1.2. If multiple threads of same process enters the func() then use
CCriticalSection.
CSingleLock can be used to ease the usage of synchronization objects.
Lets say we have defined critical section
CCriticalSection m_CriticalSection;
void func()
{
// locking/mutex statement goes here
CSingleLock aLock(&m_CriticalSection, **TRUE**);
// TRUE indicates that Lock aquired during aLock creation.
// if FALSE used then use aLock.Lock() for locking.
operation1();
operation2();
// corresponding unlock goes here
aLock.Unlock();
operation3();
}
EDIT: Refer VC++ article from MSDN: Multithreading with C++ and MFC Classes and
Multithreading: How to Use the Synchronization Classes
You can try this:
void func()
{
// See answer by Sasha on how to create the mutex
WaitForSingleObject (mutex, INFINITE);
operation1();
operation2();
ReleaseMutex(mutex);
operation3();
}