I am using pthread_mutex_t in a C++ program, as follows:
class Mutex : public noncopyable
{
public:
Mutex()
{
pthread_mutex_init(&m_mutex, NULL);
}
void acquire()
{
pthread_mutex_lock(&m_mutex);
}
void release()
{
pthread_mutex_unlock(&m_mutex);
}
private:
pthread_mutex_t m_mutex;
};
(The class is not copyable - http://www.boost.org/doc/libs/1_53_0/boost/noncopyable.hpp)
The thing that I don't understand - is it considered an error to not call pthread_mutex_destroy
in the destructor? The documentation I have read does not state that destroy must be called.
Does anyone know, what does pthread_mutex_destroy
actually do and under what conditions is it required?
EDIT
Does the answer for pthread_mutex_destroy
also apply to pthread_cond_destroy
, etc? They seem almost like useless functions to me, unless pthread_mutex_init
et. al. are allocating memory? (the docs, to me, aren't entirely clear on this.)
It doesn't hurt me to call destroy anyway, so the question is largely academic.
On linux anyway, it seems destroy only sets the mutex to an invalid state:
int
__pthread_mutex_destroy (mutex)
pthread_mutex_t *mutex;
{
if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0
&& mutex->__data.__nusers != 0)
return EBUSY;
/* Set to an invalid value. */
mutex->__data.__kind = -1;
return 0;
}
(From glibc-2.14/nptl/pthread_mutex_destroy.c).
If someone provides you with a destroy function, then you are required to call it as the final action on that object before it goes out of scope.
On architectures and implementations where the API has no effect, this will be optimised away, however if the API changes in future to require cleaning up of internal state and your code does not call it, your code will now have a memory and/or resource leak.
So the simple answer is yes; you must call this API - and here's the thing - even if the API does nothing at the moment, because although the API itself is fixed forever into the future, the implementation behind the API is not.
From IEEE documentation which is the standard governing POSIX:
The pthread_mutex_destroy() function shall destroy the mutex object referenced by mutex; the mutex object becomes, in effect, uninitialized. An implementation may cause pthread_mutex_destroy() to set the object referenced by mutex to an invalid value. A destroyed mutex object can be reinitialized using pthread_mutex_init(); the results of otherwise referencing the object after it has been destroyed are undefined.
The documentation does not say you must call it. But it is a good practice to do so.
Calling this api will signal the POSIX library to release all the resources which were reserved for use of this particular mutex object during its initialization.
It is logical to assume mutex initialization does allocate/reserve some resources.
A few years have gone by and @SecurityMatt was right. To settle the debate, you must call pthread_mutex_destroy to satisfy API requirements and to potentially free memory.
Here is an excerpt of the latest pthread_mutex_destroy:
int _pthread_mutex_destroy (pthread_mutex_t *mutex)
{
if (mutex->__attr == __PTHREAD_ERRORCHECK_MUTEXATTR
|| mutex->__attr == __PTHREAD_RECURSIVE_MUTEXATTR)
/* Static attributes. */
;
else
free (mutex->__attr);
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With