Reputation: 22936
A code which handles the exceptions well is called an exception safe code? Is this correct?
From here: https://codereview.stackexchange.com/a/9759/11619
You use lock/unlock pairs for the mutex. This is not exception safe. So I would create an object that will do the lock in the constructor and unlock in the destructor then use this to lock your mutexs. This will make your code more exception safe.
class MutexLocker
{
pthread_mutex_t& mutex;
MutextLocker(pthread_mutex_t& mutex)
: mutex(mutex)
{
pthread_mutex_lock(&mutex);
}
~MutexLocker()
{
pthread_mutex_unlock(&mutex);
}
};
In which way is the above shown code exception safe? I don't see any exception handling over there.
Or does exception safe code mean where we can "add" the exception handling? So, the above shown code can be made exception safe by adding exception handling, but it isn't now?
Upvotes: 5
Views: 2506
Reputation: 734
The code you provided serves the purpose well. Simply because when execution leaves the block in which the MutexLocker
object is defined, the object is destroyed and the mutex is released as per its destructor. This holds no matter the reason for the exit.
You don't have to code this class yourself though. The C++ standard specifies a class named lock_guard
that does exactly that.
http://en.cppreference.com/w/cpp/thread/lock_guard
Upvotes: 0
Reputation: 300029
Exception Safety is not about handling exceptions, it is about guaranteeing a number of properties about the program even in the presence of exceptions.
You can usually speak about the exception safety level of a given method:
In general, the NoThrow Guarantee only applies to the simplest methods (ie .size()
on a vector
for example) and the Strong Exception Guarantee may be costly to implement (being able to revert the effect or operating on a copy of the state may not be cheap).
On the other hand, the Basic Exception Guarantee is just that: Basic. Without it, safely operating a program is just impossible, so this is the least guarantee that is acceptable. If you leak resources or leave classes in an unusable state, the program may not be able to operate further.
This is why there is such an emphasis on RAII whenever exceptions are mentionned. Because RAII guarantees automatic cleanup of resources (memory, mutexes, files) whatever the path execution (regular return or exception) it is particularly desirable. However, RAII itself is not sufficient.
Related: Herb Sutter's GotW entry about Exception Safety and Exception Specifications.
Upvotes: 8
Reputation: 40633
"Exception safe" is a fairly overloaded term, but I would use it to describe sections of code which can have exceptions thrown through them and still maintain certain invariants (such as - nothing changes, no resources are leaked, all objects keep a valid state).
As an example, your void * printHello (void* threadId)
function is correct (in that it always matches pthread_mutex_lock (&demoMutex)
with pthread_mutex_unlock (&demoMutex)
), but if someone changed the section in the middle so that it could throw an exception (for example, by setting the throw flags on std::cout
), then your code would then permanently lock demoMutex
, with no hope for it ever being released. This would constitute a bug in your program. void * printHello (void* threadId)
is said to be "exception unsafe" because of this way in which bugs can easily be introduced into your program by adding exception handling to seemingly unrelated parts.
Using a RAII class to manage resources a good way to go about writing exception safe code (and is the resource management style to use in C++), because it avoids the need for duplicate manual cleanup in catch(...)
blocks, and it enforces the cleanup of resources by using the type system.
Upvotes: 2
Reputation: 64253
A code which handles the exceptions well is called an exception safe code?
Yes, but you do not say what well is. This is a good read on exception safety.
In which way is the above shown code exception safe?
That code is not exception safe in itself. That is meant to be used in a exception safe code. For example :
void bar()
{
throw std::runtime_error( "lala" );
}
void foo()
{
pthread_mutex_lock(&mutex);
bar();
// OPS! mutex not unlocked
pthread_mutex_unlock(&mutex);
}
This problem is solved by using the class that automatically unlock the exception. Next example has exception handling with strong guarantees :
void foo()
{
MutexLocker locker( mutex );
try {
bar();
} catch ( const std::runtime_error & )
{
// revert changes
}
}
Upvotes: 1
Reputation: 92321
You don't have to handle an exception to be exception safe. You just have to survive when an exception is thrown.
The MutexLocker helps you do this by unlocking the mutex when you leave the scope. It doesn't matter if you leave by a return statement or because an exception is thrown.
Upvotes: 3
Reputation: 2776
the MutexLocker destructor is always called, also when an exception was raised in the block where it was constructed.
that is what makes a construct using your MutexLocker exception safe.
Upvotes: 3