summaryrefslogtreecommitdiff
path: root/src/components/include/utils/lock.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/include/utils/lock.h')
-rw-r--r--src/components/include/utils/lock.h153
1 files changed, 94 insertions, 59 deletions
diff --git a/src/components/include/utils/lock.h b/src/components/include/utils/lock.h
index e615a58f9d..bfa1ef1770 100644
--- a/src/components/include/utils/lock.h
+++ b/src/components/include/utils/lock.h
@@ -32,24 +32,18 @@
#ifndef SRC_COMPONENTS_INCLUDE_UTILS_LOCK_H_
#define SRC_COMPONENTS_INCLUDE_UTILS_LOCK_H_
-#if defined(OS_POSIX)
-#include <pthread.h>
-#include <sched.h>
-#else
-#error Please implement lock for your OS
-#endif
#include <stdint.h>
-#include "utils/macro.h"
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/recursive_mutex.hpp>
+#include <iostream>
+#include <memory>
#include "utils/atomic.h"
+#include "utils/macro.h"
#include "utils/memory_barrier.h"
-namespace sync_primitives {
+using boost::system::error_code;
-namespace impl {
-#if defined(OS_POSIX)
-typedef pthread_mutex_t PlatformMutex;
-#endif
-} // namespace impl
+namespace sync_primitives {
class SpinMutex {
public:
@@ -78,71 +72,98 @@ class SpinMutex {
volatile unsigned int state_;
};
-/* Platform-indepenednt NON-RECURSIVE lock (mutex) wrapper
- Please use AutoLock to ackquire and (automatically) release it
- It eases balancing of multple lock taking/releasing and makes it
- Impossible to forget to release the lock:
- ...
- ConcurentlyAccessedData data_;
- sync_primitives::Lock data_lock_;
- ...
- {
- sync_primitives::AutoLock auto_lock(data_lock_);
- data_.ReadOrWriteData();
- } // lock is automatically released here
-*/
-class Lock {
+/* Abstract base class that allows AutoLock to handle both recursive and
+ * non-recursive locks
+ */
+class BaseLock {
public:
- Lock();
- Lock(bool is_recursive);
- ~Lock();
-
+ BaseLock() {}
+ virtual ~BaseLock() {}
// Ackquire the lock. Must be called only once on a thread.
// Please consider using AutoLock to capture it.
- void Acquire();
+ virtual void Acquire() = 0;
// Release the lock. Must be called only once on a thread after lock.
// was acquired. Please consider using AutoLock to automatically release
// the lock
- void Release();
+ virtual void Release() = 0;
// Try if lock can be captured and lock it if it was possible.
// If it captured, lock must be manually released calling to Release
// when protected resource access was finished.
// @returns wether lock was captured.
- bool Try();
+ virtual bool Try() = 0;
- private:
- impl::PlatformMutex mutex_;
+ protected:
+ // Ensures safety in locking
+ virtual void AssertTakenAndMarkFree() = 0;
+ virtual void AssertFreeAndMarkTaken() = 0;
+
+ friend class ConditionalVariable;
+};
+
+/*
+ * Platform-indepenednt NON-RECURSIVE lock (mutex) wrapper
+ */
+class Lock : public BaseLock {
+ public:
+ Lock();
+ ~Lock();
+
+ virtual void Acquire();
+
+ virtual void Release();
-#ifndef NDEBUG
+ virtual bool Try();
+
+ private:
/**
- * @brief Basic debugging aid, a flag that signals wether this lock is
- * currently taken
- * Allows detection of abandoned and recursively captured mutexes
- */
+ * @brief Basic debugging aid, a flag that signals wether this lock is
+ * currently taken
+ * Allows detection of abandoned and recursively captured mutexes
+ */
uint32_t lock_taken_;
+ virtual void AssertTakenAndMarkFree();
+ virtual void AssertFreeAndMarkTaken();
+ boost::mutex mutex_;
+ DISALLOW_COPY_AND_ASSIGN(Lock);
+ friend class ConditionalVariable;
+};
- /**
- * @brief Describe if mutex is recurcive or not
- */
- bool is_mutex_recursive_;
+/*
+ * Platform-indepenednt RECURSIVE lock (mutex) wrapper
+ */
+class RecursiveLock : public BaseLock {
+ public:
+ RecursiveLock();
+ ~RecursiveLock();
+
+ virtual void Acquire();
- void AssertFreeAndMarkTaken();
- void AssertTakenAndMarkFree();
-#else
- void AssertFreeAndMarkTaken() {}
- void AssertTakenAndMarkFree() {}
-#endif
+ virtual void Release();
- void Init(bool is_recursive);
+ virtual bool Try();
+ private:
+ /**
+ * @brief Basic debugging aid, a flag that signals wether this lock is
+ * currently taken
+ * Allows detection of abandoned and recursively captured mutexes
+ */
+ uint32_t lock_taken_;
+ virtual void AssertTakenAndMarkFree();
+ virtual void AssertFreeAndMarkTaken();
+ boost::recursive_mutex mutex_;
+ DISALLOW_COPY_AND_ASSIGN(RecursiveLock);
friend class ConditionalVariable;
- DISALLOW_COPY_AND_ASSIGN(Lock);
};
// This class is used to automatically acquire and release the a lock
class AutoLock {
public:
- explicit AutoLock(Lock& lock) : lock_(lock) {
+ explicit AutoLock(const std::shared_ptr<BaseLock>& lock) : lock_(*lock) {
+ lock_.Acquire();
+ }
+ explicit AutoLock(BaseLock& lock) : lock_(lock) {
+ // std::cerr << "lock is at " << &lock << std::endl;
lock_.Acquire();
}
~AutoLock() {
@@ -150,21 +171,35 @@ class AutoLock {
}
private:
- Lock& GetLock() {
+ BaseLock& GetLock() {
return lock_;
}
- Lock& lock_;
+ BaseLock& lock_;
private:
friend class AutoUnlock;
friend class ConditionalVariable;
DISALLOW_COPY_AND_ASSIGN(AutoLock);
};
-
+/* Please use AutoLock to acquire and (automatically) release it
+ * It eases balancing of multple lock taking/releasing and makes it
+ * Impossible to forget to release the lock:
+ * ...
+ * ConcurentlyAccessedData data_;
+ * sync_primitives::Lock data_lock_;
+ * ...
+ * {
+ * sync_primitives::AutoLock auto_lock(data_lock_);
+ * data_.ReadOrWriteData();
+ * } // lock is automatically released here
+ */
// This class is used to temporarly unlock autolocked lock
class AutoUnlock {
public:
- explicit AutoUnlock(Lock& lock) : lock_(lock) {
+ explicit AutoUnlock(const std::shared_ptr<BaseLock>& lock) : lock_(*lock) {
+ lock_.Release();
+ }
+ explicit AutoUnlock(BaseLock& lock) : lock_(lock) {
lock_.Release();
}
explicit AutoUnlock(AutoLock& lock) : lock_(lock.GetLock()) {
@@ -175,7 +210,7 @@ class AutoUnlock {
}
private:
- Lock& lock_;
+ BaseLock& lock_;
private:
DISALLOW_COPY_AND_ASSIGN(AutoUnlock);