Blob Blame Raw
#ifndef COMMON_H
#define COMMON_H


#include <mutex>

#include "error.h"
#include "handle.h"



class RecursiveMutex {
public:
	class CondWrapper {
	private:
		int cnt;
		bool locked;
		inline void lockCnt(int cnt) { for(int i = 0; i < cnt; ++i) mutex.lock(); }
		inline void unlockCnt(int cnt) { for(int i = 0; i < cnt; ++i) mutex.unlock(); }
		
	public:
		RecursiveMutex &mutex;
		
		inline CondWrapper(RecursiveMutex &mutex):
			cnt(mutex.count()), locked(true), mutex(mutex) { }
		inline ~CondWrapper()
			{ if (!locked) lock(); }
		
		inline void lock() {
			if (!locked) lockCnt(cnt);
			locked = true;
		}
		
		inline void unlock() {
			if (locked) unlockCnt(cnt);
			locked = false;
		}
		
		inline bool try_lock() {
			if (locked || cnt <= 0) return true;
			if (!mutex.try_lock()) return false;
			lockCnt(cnt-1);
			locked = true;
			return true;
		}
	};

private:
	int cnt;
	
public:
	std::recursive_mutex mutex;
	
	inline RecursiveMutex(): cnt() { }
	inline ~RecursiveMutex() { assert(!cnt); }
	
	inline int count() const { return cnt; }
	inline void lock() { mutex.lock(); ++cnt; }
	inline bool try_lock() { if (mutex.try_lock()) { ++cnt; return true; } else return false; }
	inline void unlock() { mutex.unlock(); --cnt; }
};


#endif