基於C++標準map的多線程安全容器mymap::map進化版

#pragma once

#include <map>

#if defined  _WIN32                                                         //Windows
#include <Windows.h>
#define MyMap_CLock_Mutex_t                 HANDLE
#define MyMap_CLock_Mutex_Init(_mutex)      (_mutex = CreateSemaphore(NULL,1,1,NULL))
#define MyMap_CLock_Mutex_Lock(_mutex)      (WaitForSingleObject(_mutex, INFINITE))
#define MyMap_CLock_Mutex_UnLock(_mutex)    (ReleaseSemaphore(_mutex,1,NULL))
#define MyMap_CLock_Mutex_Destroy(_mutex)   (CloseHandle(_mutex))
#define MyMap_Declar_Typename               typename
#define MyMap_Type_Typename

#elif defined __linux                                                       //Linux
#include <pthread.h>
#define MyMap_CLock_Mutex_t                 pthread_mutex_t
#define MyMap_CLock_Mutex_Init(_mutex)      (pthread_mutex_init(&_mutex, NULL))
#define MyMap_CLock_Mutex_Lock(_mutex)      (pthread_mutex_lock(&_mutex))
#define MyMap_CLock_Mutex_UnLock(_mutex)    (pthread_mutex_unlock(&_mutex))
#define MyMap_CLock_Mutex_Destroy(_mutex)   (pthread_mutex_destroy(&_mutex))
#define MyMap_Declar_Typename 
#define MyMap_Type_Typename                 typename
#endif

//************************************  
// 函數名稱: PthreadSelf
// 函數說明: 獲取線程ID內聯函數
// 做 成 者:smallErLang  
// 做成日期:2016/04/22
// 返 回 值: unsigned int :返回當前線程的ID
//************************************
inline unsigned int PthreadSelf()
{
#ifdef _WIN32
	return GetCurrentThreadId();
#else
	return thread_self();
#endif
}

namespace mymap
{
	template<class K, class V>
	class map;

	template<class K, class V>
	class myiterator;

	//lock
	class CLock  
	{  
	public: 
		CLock(){MyMap_CLock_Mutex_Init(_mutex);}
		~CLock(){MyMap_CLock_Mutex_Destroy(_mutex);}

		void Lock() {MyMap_CLock_Mutex_Lock(_mutex);}
		void UnLock() {MyMap_CLock_Mutex_UnLock(_mutex);}


	private:
		MyMap_CLock_Mutex_t _mutex;
	};

	//threadlockstats
	/************************************************************************/
	/* 
		1.CThreadLockStats是保存了當前全部線程調用_mutex_usr.Lock()和_mutex_usr.UnLock()
		的差值,記錄同一線程中_mutex_usr的使用狀況。
		2.類中可用函數爲TryLock(),TryUnLock(),若是同一線程中_mutex_usr已經Lock,則TryLock()
		再也不鎖,只是將標識自增;若是同一線程中_mutex_usr的Lock次數爲1同時須要釋放鎖的時候,
		調用TryUnLock會釋放,不爲1則將標識自減。
	*/
	/************************************************************************/
	template<class K, class V>
	class CThreadLockStats
	{
	private:
		CThreadLockStats();
		~CThreadLockStats();

		//************************************  
		// 函數名稱: TryLock
		// 函數說明: 防止重鎖
		// 做 成 者:smallErLang  
		// 做成日期:2016/04/22
		// 返 回 值: void  
		//************************************
		void TryLock();

		//************************************  
		// 函數名稱: TryUnLock
		// 函數說明: 與TryLock對應的釋放鎖
		// 做 成 者:smallErLang  
		// 做成日期:2016/04/22
		// 返 回 值: void  
		//************************************
		void TryUnLock();

	private:
		CLock _mutex_usr;

		CLock _mutex_stats;

		std::map<unsigned int, int>* _thread_lock_stats;

		friend mymap::map<K, V>;

		friend mymap::myiterator<K, V>;
	};

	template<class K, class V>
	void mymap::CThreadLockStats<K, V>::TryUnLock()
	{
		bool _isneedusrunlock = false;
		unsigned int _thread_id = PthreadSelf();

		_mutex_stats.Lock();

		if(_thread_lock_stats){
			MyMap_Type_Typename std::map<unsigned int, int>::iterator _finditr = _thread_lock_stats->find(_thread_id);

			if(_finditr != _thread_lock_stats->end()){

				if(_finditr->second == 1){

					_isneedusrunlock = true;
				}

				_finditr->second -= 1;

			}else{

				int _new_lock_counts = 0;

				_thread_lock_stats->insert(MyMap_Type_Typename std::map<unsigned int, int>::value_type(_thread_id, _new_lock_counts));
			}
		}

		_mutex_stats.UnLock();

		if(_isneedusrunlock){

			_mutex_usr.UnLock();
		}
	}

	template<class K, class V>
	void mymap::CThreadLockStats<K, V>::TryLock()
	{
		bool _isneedusrlock = false;
		unsigned int _thread_id = PthreadSelf();

		_mutex_stats.Lock();

		if(_thread_lock_stats){

			MyMap_Type_Typename std::map<unsigned int, int>::iterator _finditr = _thread_lock_stats->find(_thread_id);

			if(_finditr != _thread_lock_stats->end()){

				if(_finditr->second <= 0){

					_finditr->second = 0;

					_isneedusrlock = true;
				}

				_finditr->second += 1;
			}else{

				int _new_lock_counts = 1;

				_thread_lock_stats->insert(MyMap_Type_Typename std::map<unsigned int, int>::value_type(_thread_id, _new_lock_counts));

				_isneedusrlock = true;
			}
		}

		_mutex_stats.UnLock();

		//將_mutex_usr.Lock放置於_mutex_stats釋放後,防止死鎖
		//函數中非成對出現的鎖加上其餘鎖在多線程調用時必定會出現死鎖
		if(_isneedusrlock){

			_mutex_usr.Lock();
		}
	}

	template<class K, class V>
	mymap::CThreadLockStats<K, V>::~CThreadLockStats()
	{
		_mutex_stats.Lock();

		delete _thread_lock_stats;

		_thread_lock_stats = NULL;

		_mutex_stats.UnLock();
	}

	template<class K, class V>
	mymap::CThreadLockStats<K, V>::CThreadLockStats()
	{
		_thread_lock_stats = new std::map<unsigned int, int>;
	}

	//myiterator:迭代器繼承標準迭代器,減小運算符和一些函數的重載
	template<class K, class V>
	class myiterator: public MyMap_Type_Typename std::map<K, V>::iterator
	{
	public:
		myiterator();
		//************************************  
		// 函數名稱: myiterator
		// 函數說明: 重載拷貝構造,方便拷貝時就Lock,釋放時就UnLock;
		// 做 成 者:smallErLang  
		// 做成日期:2016/04/22
		// 返 回 值:   
		// 參    數: const myiterator & val_
		//************************************
		myiterator(const myiterator& val_);
		~myiterator();

		//************************************  
		// 函數名稱: operator=
		// 函數說明: 賦值運算會隱藏父類賦值函數,不會繼承,須要重載
		// 做 成 者:smallErLang  
		// 做成日期:2016/04/22
		// 返 回 值: myiterator&  
		// 參    數: const myiterator & val_
		//************************************
		myiterator& operator=(const myiterator& val_);

	private:
		myiterator& operator=(const MyMap_Declar_Typename std::map<K, V>::iterator& val_);

	private:
		CThreadLockStats<K, V>* _mutex_stats;

		friend mymap::map<K, V>;
	};

	template<class K, class V>
	mymap::myiterator<K, V>& mymap::myiterator<K, V>::operator=( const mymap::myiterator<K, V>& val_ )
	{
		_mutex_stats = val_._mutex_stats;

		if(_mutex_stats){

			_mutex_stats->TryLock();
		}

		this->std::map<K, V>::iterator::operator=(val_);

		return *this;
	}

	template<class K, class V>
	mymap::myiterator<K, V>::myiterator( const myiterator& val_ )
	{
		_mutex_stats = val_._mutex_stats;

		if(_mutex_stats){

			_mutex_stats->TryLock();
		}

		this->std::map<K, V>::iterator::operator=(val_);
	}

	template<class K, class V>
	mymap::myiterator<K, V>& mymap::myiterator<K, V>::operator=( const MyMap_Declar_Typename std::map<K, V>::iterator& val_ )
	{
		this->std::map<K, V>::iterator::operator=(val_);

		return *this;
	}

	//************************************  
	// 函數名稱: ~myiterator
	// 函數說明: 迭代器賦值和拷貝構造時Lock,析構時須要釋放鎖
	// 做 成 者:smallErLang  
	// 做成日期:2016/04/22
	// 返 回 值:   
	//************************************
	template<class K, class V>
	mymap::myiterator<K, V>::~myiterator()
	{
		if(_mutex_stats){

			_mutex_stats->TryUnLock();
		}

		_mutex_stats = NULL;
	}

	template<class K, class V>
	mymap::myiterator<K, V>::myiterator()
	{
		_mutex_stats = NULL;
	}

	//mymap
	/************************************************************************/
	/* 
		因爲iterator默認構造函數沒有TryLock,因此在返回該類型臨時變量時須要TryLock一次,
	臨時變量析構時TryUnLock一次;將返回的值進行拷貝構造或者拷貝賦值會TryLock一次,使用
	完後析構TryUnLock一次。達到成對鎖和釋放鎖的目的。
	*/
	/************************************************************************/
	template<class K, class V>
	class map: private std::map<K, V>
	{
	public:
		map();
		map(const map& val_);
		~map();

		map& operator=(const map& val_);

		typedef MyMap_Declar_Typename myiterator<K, V> iterator;

		void insert_s(const K& key_, const V& val_);
		void erase_s(const K& key_);
		void erase_s(iterator& itr_);
		iterator find_s(const K& key_);

		iterator begin_s();
		iterator end_s();

		unsigned int size_s();

	private:
		CThreadLockStats<K, V> _mutex_stats;
	};

	template<class K, class V>
	unsigned int mymap::map<K, V>::size_s()
	{
		unsigned int _size = 0;

		_mutex_stats.TryLock();

		_size = this->size();

		_mutex_stats.TryUnLock();

		return _size;
	}

	template<class K, class V>
	typename mymap::map<K, V>::iterator mymap::map<K, V>::end_s()
	{
		mymap::map<K, V>::iterator _ret;

		_ret._mutex_stats = &_mutex_stats;

		_mutex_stats.TryLock();

		_ret = this->end();

		return _ret;
	}

	template<class K, class V>
	typename mymap::map<K, V>::iterator mymap::map<K, V>::begin_s()
	{
		mymap::map<K, V>::iterator _ret;

		_ret._mutex_stats = &_mutex_stats;

		_mutex_stats.TryLock();

		_ret = this->begin();

		return _ret;
	}

	template<class K, class V>
	typename mymap::map<K, V>::iterator mymap::map<K, V>::find_s( const K& key_ )
	{
		mymap::map<K, V>::iterator _ret;

		_ret._mutex_stats = &_mutex_stats;

		_mutex_stats.TryLock();

		_ret = this->find(key_);

		return _ret;
	}

	template<class K, class V>
	void mymap::map<K, V>::erase_s( typename mymap::map<K, V>::iterator& itr_ )
	{
		_mutex_stats.TryLock();

		this->erase(itr_);

		_mutex_stats.TryUnLock();
	}

	template<class K, class V>
	void mymap::map<K, V>::erase_s( const K& key_ )
	{
		_mutex_stats.TryLock();

		this->erase(key_);

		_mutex_stats.TryUnLock();

		return ;
	}

	template<class K, class V>
	void mymap::map<K, V>::insert_s( const K& key_, const V& val_ )
	{
		_mutex_stats.TryLock();

		this->insert(std::map<K, V>::value_type(key_, val_));

		_mutex_stats.TryUnLock();

		return ;
	}

	template<class K, class V>
	mymap::map<K, V>& mymap::map<K, V>::operator=( const map& val_ )
	{
		val_._mutex_stats.TryLock();

		this->std::map<K, V>::operator =(val_);

		val_._mutex_stats.TryUnLock();

		return *this;
	}

	template<class K, class V>
	mymap::map<K, V>::~map()
	{

	}

	template<class K, class V>
	mymap::map<K, V>::map( const mymap::map<K, V>& val_ )
	{
		val_._mutex_stats.TryLock();

		this->std::map<K, V>::operator =(val_);

		val_._mutex_stats.TryUnLock();
	}

	template<class K, class V>
	mymap::map<K, V>::map()
	{

	}
}

    WIN下是測試OK的,因時間有限,Linux下編譯時須要本身調試下,可是編寫的函數都是支持WIN和Linux的。 linux

相關文章
相關標籤/搜索