| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377 | #ifndef AUTOLOCKH#define AUTOLOCKH#ifdef _WIN32#pragma warning (disable:4786)#include <windows.h>#elif defined(__linux__) || defined(__APPLE__)#include <pthread.h>#else#error port me!!#endif/*NULLSOFT_LOCK_OUTPUT_STATUS turns on/off debugging outputthis can be VERY useful if you are trying to find a deadlockeach time the guard is locked or unlocked, it outputs a list ofany threads using the mutex, and their function stack*/ //#define NULLSOFT_LOCK_OUTPUT_STATS#ifdef NULLSOFT_LOCK_OUTPUT_STATS#include <string> // we save each function name as a string#include <deque> // we make a list of the recursive function stack for each thread#include <map> // and map#include <iostream> // we output to std::cerr#include <windows.h>/*****Description:	This class uses scoping to wrap a critical section (lightweight in-process mutex)	The constructor enters the mutex and the destructor leaves it.  This allows it to	take advantage of automatic scoping in C++, because C++ automatically calls the destructor	when an object leaves scope.  	This is _especially_ useful when you have multiple return paths, since you don't have to	repeat mutex-leaving code. To use:	Make a LockGuard for a resource you want to protect.  The guard is shared, so make it part 	of your class, or a global, or whatever.  The LockGuard is essentially a "token", equivalent	to your mutex handle or critical section handle.		Make an AutoLock object on the stack to lock.  It will unlock automatically when the object	leaves scope.  			Note: You'll want to make an object on the stack - don't use a heap object (new/delete)		unless you have weird requirements and know what you are doing. 	Example: 	class MyClass	{		LockGuard fileGuard;		fstream file;		void DumpSomeData() // 		{			AutoLock lock(fileGuard);			file << GetData();		} 		void CALLBACK NewData() // potentially called by another thread		{			AutoLock lock(fileGuard)			file << newData;		}	};  	Tip: You can use "false scoping" to tweak the mutex lifetime, for example: 	void DoStuff()	{		a = GetData();		{ // false scope			AutoLock lock(dataGuard);			DoCalculationsWith(a);		} // mutex will release here		SetData(a);	}		Tip: A common mistake is making a temporary object.	i.e.	CORRECT:  AutoLock lock(fileGuard); // an AutoLock object called "lock" is put on the stack	INCORRECT: AutoLock(fileGuard); // An unnamed temporary is created which will be destroyed IMMEDIATELY *******/#define MANUALLOCKNAME(x) x#define LOCKNAME(x) ,x#define GUARDNAME(x) (x)namespace Nullsoft{	namespace Utility	{		/* the token which represents a resource to be locked */		class LockGuard		{		public:			inline LockGuard(const char *name = "Unnamed Guard")			{				lockName = name;				InitializeCriticalSection(&cerr_cs);				InitializeCriticalSection(&map_cs);				InitializeCriticalSection(&m_cs);			}			inline ~LockGuard()			{				DeleteCriticalSection(&cerr_cs);				DeleteCriticalSection(&map_cs);				DeleteCriticalSection(&m_cs);			}			inline void Lock()			{				EnterCriticalSection(&m_cs);			}			inline void Unlock()			{				LeaveCriticalSection(&m_cs);			}			int ThreadCount()			{				EnterCriticalSection(&map_cs);				int count = 0;				for (ThreadMap::iterator itr = threads.begin(); itr != threads.end(); itr++)				{					if (!itr->second.empty())						count++;				}				LeaveCriticalSection(&map_cs);				return count;			}			void Display()			{				EnterCriticalSection(&map_cs);				EnterCriticalSection(&cerr_cs);				if (ThreadCount() > 1 && owner)				{					std::cerr << "Guard: " << lockName << std::endl;					for (ThreadMap::iterator itr = threads.begin(); itr != threads.end(); itr++)					{						if (itr->second.empty())							continue;						std::cerr << "  Thread ID: " << std::hex << itr->first << std::dec;						if (owner == itr->first)							std::cerr << " [holding the mutex] *****";						else							std::cerr << " [blocked]";						std::cerr << std::endl;						for (FunctionStack::iterator fitr = itr->second.begin(); fitr != itr->second.end(); fitr++)						{							std::cerr << "    " << *fitr << "();" << std::endl;						}					}				}				LeaveCriticalSection(&cerr_cs);				LeaveCriticalSection(&map_cs);			}			void In(DWORD thread, const char *functionName)			{				EnterCriticalSection(&map_cs);				threads[thread].push_back(functionName);				LeaveCriticalSection(&map_cs);			}			void Out(DWORD thread)			{				EnterCriticalSection(&map_cs);				threads[thread].pop_back();				LeaveCriticalSection(&map_cs);			}			std::string lockName;			CRITICAL_SECTION cerr_cs, map_cs;			typedef std::deque<std::string> FunctionStack; // this typedef reduce ugly c++ <>::<>::<> overkill			typedef std::map<DWORD, FunctionStack> ThreadMap;			ThreadMap threads;			DWORD owner;		private:			CRITICAL_SECTION m_cs;		};		/* an AutoLock locks a resource (represented by a LockGuard) for the duration of its lifetime */		class AutoLock		{		public:			/*			@param functionName The function name which wants the mutex				we pass it in as a char * even though it'll be converted to a std::string				to reduce overhead when OUTPUT_STATS is off			 */			inline AutoLock(LockGuard &_guard, const char *functionName = "function name not passed") : guard(&_guard)			{				ManualLock(functionName);			}			inline void ManualLock(char *functionName = "manual lock")			{				thisThread = GetCurrentThreadId();				guard->In(thisThread, functionName);				guard->Display();				guard->Lock();				guard->owner = thisThread;				guard->Display();			}			inline void ManualUnlock()			{				guard->Display();				guard->Unlock();				InterlockedCompareExchange((LONG volatile *)&guard->owner, 0, (LONG)thisThread);				/* above line is functionally equivalent to:				if (guard->owner == thisThread) 					guard->owner=0;				*/				guard->Out(thisThread);				guard->Display();			}			inline ~AutoLock()			{				ManualUnlock();			}			LockGuard *guard;			DWORD thisThread;		};	}}#else#define MANUALLOCKNAME(x)#define LOCKNAME(x)#define GUARDNAME(x)namespace nu{		/* the token which represents a resource to be locked */		class LockGuard		{		public:			inline LockGuard(const char *guardName = "")			{      #ifdef _WIN32					InitializeCriticalSection(&m_cs);#elif defined(__linux__)           pthread_mutexattr_t mtxattr;           pthread_mutexattr_init(&mtxattr);           pthread_mutexattr_settype(&mtxattr,  PTHREAD_MUTEX_RECURSIVE_NP );                      pthread_mutex_init(&mtx, &mtxattr);           pthread_mutexattr_destroy(&mtxattr);#elif defined(__APPLE__)                pthread_mutexattr_t mtxattr;                pthread_mutexattr_init(&mtxattr);                pthread_mutexattr_settype(&mtxattr,  PTHREAD_MUTEX_RECURSIVE);                           pthread_mutex_init(&mtx, &mtxattr);                pthread_mutexattr_destroy(&mtxattr);           #else           #error port me          #endif			}			inline ~LockGuard()			{      #ifdef _WIN32				DeleteCriticalSection(&m_cs);      #elif defined(__linux__) || defined(__APPLE__)      pthread_mutex_destroy(&mtx);      #else      #error port me!      #endif      }			inline void Lock()			{      #ifdef _WIN32				EnterCriticalSection(&m_cs);      #elif defined(__linux__) || defined(__APPLE__)        pthread_mutex_lock(&mtx);        #else        #error por tme!      #endif      }			inline void Unlock()			{      #ifdef _WIN32				LeaveCriticalSection(&m_cs);      #elif defined(__linux__) || defined(__APPLE__)        pthread_mutex_unlock(&mtx);        #else        #error port me!      #endif      }		private:    #ifdef _WIN32			CRITICAL_SECTION m_cs;      #elif defined(__linux__) || defined(__APPLE__)			pthread_mutex_t mtx;			        #else        #error port me!    #endif    };		/* an AutoLock locks a resource (represented by a LockGuard) for the duration of its lifetime */		class AutoLock		{		public:			inline AutoLock(LockGuard &_guard) : guard(&_guard)			{				guard->Lock();			}						inline AutoLock(LockGuard *_guard) : guard(_guard)			{				guard->Lock();			}			inline void ManualLock()			{				guard->Lock();			}			inline void ManualUnlock()			{				guard->Unlock();			}			inline ~AutoLock()			{				guard->Unlock();			}			LockGuard *guard;		};		// will lock anything that implements Lock() and Unlock()		template <class LockGuard_t>		class AutoLockT		{		public:			inline AutoLockT(LockGuard_t &_guard) : guard(&_guard)			{				guard->Lock();			}						inline AutoLockT(LockGuard_t *_guard) : guard(_guard)			{				guard->Lock();			}			inline void ManualLock()			{				guard->Lock();			}			inline void ManualUnlock()			{				guard->Unlock();			}			inline ~AutoLockT()			{				guard->Unlock();			}			LockGuard_t *guard;		};}#endif#endif
 |