libzmq/src/mutex.hpp
Luca Boccassi da31917f4f Relicense from LGPL3 + exceptions to Mozilla Public License version 2.0
Relicense permission collected from all relevant authors as tallied at:
https://github.com/rlenferink/libzmq-relicense/blob/master/checklist.md
The relicense grants are collected under RELICENSE/ and will be moved
to the above repository in a later commit.

Fixes https://github.com/zeromq/libzmq/issues/2376
2023-06-05 20:31:47 +01:00

178 lines
3.1 KiB
C++

/* SPDX-License-Identifier: MPL-2.0 */
#ifndef __ZMQ_MUTEX_HPP_INCLUDED__
#define __ZMQ_MUTEX_HPP_INCLUDED__
#include "err.hpp"
#include "macros.hpp"
// Mutex class encapsulates OS mutex in a platform-independent way.
#if defined(ZMQ_HAVE_WINDOWS) && !defined(ZMQ_USE_CV_IMPL_PTHREADS)
#include "windows.hpp"
namespace zmq
{
class mutex_t
{
public:
mutex_t () { InitializeCriticalSection (&_cs); }
~mutex_t () { DeleteCriticalSection (&_cs); }
void lock () { EnterCriticalSection (&_cs); }
bool try_lock () { return (TryEnterCriticalSection (&_cs)) ? true : false; }
void unlock () { LeaveCriticalSection (&_cs); }
CRITICAL_SECTION *get_cs () { return &_cs; }
private:
CRITICAL_SECTION _cs;
ZMQ_NON_COPYABLE_NOR_MOVABLE (mutex_t)
};
}
#elif defined ZMQ_HAVE_VXWORKS
#include <vxWorks.h>
#include <semLib.h>
namespace zmq
{
class mutex_t
{
public:
inline mutex_t ()
{
_semId =
semMCreate (SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE);
}
inline ~mutex_t () { semDelete (_semId); }
inline void lock () { semTake (_semId, WAIT_FOREVER); }
inline bool try_lock ()
{
if (semTake (_semId, NO_WAIT) == OK) {
return true;
}
return false;
}
inline void unlock () { semGive (_semId); }
private:
SEM_ID _semId;
ZMQ_NON_COPYABLE_NOR_MOVABLE (mutex_t)
};
}
#else
#include <pthread.h>
namespace zmq
{
class mutex_t
{
public:
inline mutex_t ()
{
int rc = pthread_mutexattr_init (&_attr);
posix_assert (rc);
rc = pthread_mutexattr_settype (&_attr, PTHREAD_MUTEX_RECURSIVE);
posix_assert (rc);
rc = pthread_mutex_init (&_mutex, &_attr);
posix_assert (rc);
}
inline ~mutex_t ()
{
int rc = pthread_mutex_destroy (&_mutex);
posix_assert (rc);
rc = pthread_mutexattr_destroy (&_attr);
posix_assert (rc);
}
inline void lock ()
{
int rc = pthread_mutex_lock (&_mutex);
posix_assert (rc);
}
inline bool try_lock ()
{
int rc = pthread_mutex_trylock (&_mutex);
if (rc == EBUSY)
return false;
posix_assert (rc);
return true;
}
inline void unlock ()
{
int rc = pthread_mutex_unlock (&_mutex);
posix_assert (rc);
}
inline pthread_mutex_t *get_mutex () { return &_mutex; }
private:
pthread_mutex_t _mutex;
pthread_mutexattr_t _attr;
ZMQ_NON_COPYABLE_NOR_MOVABLE (mutex_t)
};
}
#endif
namespace zmq
{
struct scoped_lock_t
{
scoped_lock_t (mutex_t &mutex_) : _mutex (mutex_) { _mutex.lock (); }
~scoped_lock_t () { _mutex.unlock (); }
private:
mutex_t &_mutex;
ZMQ_NON_COPYABLE_NOR_MOVABLE (scoped_lock_t)
};
struct scoped_optional_lock_t
{
scoped_optional_lock_t (mutex_t *mutex_) : _mutex (mutex_)
{
if (_mutex != NULL)
_mutex->lock ();
}
~scoped_optional_lock_t ()
{
if (_mutex != NULL)
_mutex->unlock ();
}
private:
mutex_t *_mutex;
ZMQ_NON_COPYABLE_NOR_MOVABLE (scoped_optional_lock_t)
};
}
#endif