MutexHelper.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. EQ2Emulator: Everquest II Server Emulator
  3. Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
  4. This file is part of EQ2Emulator.
  5. EQ2Emulator is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. EQ2Emulator is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #ifndef MUTEXHELPER_H
  17. #define MUTEXHELPER_H
  18. #include "../common/timer.h"
  19. #include "../common/Mutex.h"
  20. #include <list>
  21. #include <map>
  22. template<typename T>
  23. class IsPointer {
  24. public:
  25. static bool ValidPointer(T key){
  26. return false;
  27. }
  28. static void Delete(T key){
  29. }
  30. };
  31. class Locker{
  32. public:
  33. Locker(){
  34. #ifdef WIN32
  35. InitializeCriticalSection(&CSMutex);
  36. #else
  37. pthread_mutexattr_t attr;
  38. pthread_mutexattr_init(&attr);
  39. pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
  40. pthread_mutex_init(&CSMutex, &attr);
  41. pthread_mutexattr_destroy(&attr);
  42. #endif
  43. }
  44. Locker(const Locker& locker){
  45. #ifdef WIN32
  46. InitializeCriticalSection(&CSMutex);
  47. #else
  48. pthread_mutexattr_t attr;
  49. pthread_mutexattr_init(&attr);
  50. pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
  51. pthread_mutex_init(&CSMutex, &attr);
  52. pthread_mutexattr_destroy(&attr);
  53. #endif
  54. }
  55. ~Locker(){
  56. #ifdef WIN32
  57. DeleteCriticalSection(&CSMutex);
  58. #else
  59. // pthread_mutex_destroy(&CSMutex);
  60. #endif
  61. }
  62. void lock(){
  63. #ifdef WIN32
  64. EnterCriticalSection(&CSMutex);
  65. #else
  66. pthread_mutex_lock(&CSMutex);
  67. #endif
  68. }
  69. void unlock(){
  70. #ifdef WIN32
  71. LeaveCriticalSection(&CSMutex);
  72. #else
  73. pthread_mutex_unlock(&CSMutex);
  74. #endif
  75. }
  76. private:
  77. #ifdef WIN32
  78. CRITICAL_SECTION CSMutex;
  79. #else
  80. pthread_mutex_t CSMutex;
  81. #endif
  82. };
  83. template<typename T>
  84. class IsPointer<T*> {
  85. public:
  86. static bool ValidPointer(T* key){
  87. return true;
  88. }
  89. static void Delete(T* key){
  90. if(key){
  91. delete key;
  92. key = 0;
  93. }
  94. }
  95. };
  96. template <typename KeyT, typename ValueT>
  97. class DeleteData{
  98. public:
  99. void SetData(int type, KeyT key, ValueT value, unsigned int time){
  100. this->type = type;
  101. this->key = key;
  102. this->value = value;
  103. this->time = time;
  104. }
  105. void DeleteKey(){
  106. IsPointer<KeyT>::Delete(key);
  107. }
  108. void DeleteValue(){
  109. IsPointer<ValueT>::Delete(value);
  110. }
  111. unsigned int GetTime(){
  112. return time;
  113. }
  114. int GetType(){
  115. return type;
  116. }
  117. private:
  118. int type;
  119. KeyT key;
  120. ValueT value;
  121. unsigned int time;
  122. };
  123. template<typename T>
  124. class HandleDeletes {
  125. public:
  126. HandleDeletes(){
  127. access_count = 0;
  128. next_delete_attempt = 0;
  129. changing = false;
  130. has_pending_deletes = false;
  131. }
  132. ~HandleDeletes(){
  133. CheckDeletes(true);
  134. }
  135. void AddPendingDelete(T value, unsigned int time){
  136. if(IsPointer<T>::ValidPointer(value)){
  137. while(changing){
  138. Sleep(1);
  139. }
  140. ++access_count;
  141. pending_deletes[value] = time;
  142. has_pending_deletes = true;
  143. --access_count;
  144. }
  145. }
  146. void CheckDeletes(bool force = false){
  147. while(changing){
  148. Sleep(1);
  149. }
  150. if(has_pending_deletes && (force || (Timer::GetCurrentTime2() > next_delete_attempt && access_count == 0))){
  151. changing = true;
  152. while(access_count > 0){
  153. Sleep(1);
  154. }
  155. ++access_count;
  156. next_delete_attempt = Timer::GetCurrentTime2();
  157. std::list<T> deletes;
  158. typename std::map<T, unsigned int>::iterator pending_delete_itr;
  159. for(pending_delete_itr = pending_deletes.begin(); pending_delete_itr != pending_deletes.end(); pending_delete_itr++){
  160. if(force || next_delete_attempt >= pending_delete_itr->second)
  161. deletes.push_back(pending_delete_itr->first);
  162. }
  163. if(deletes.size() > 0){
  164. typename std::list<T>::iterator delete_itr;
  165. for(delete_itr = deletes.begin(); delete_itr != deletes.end(); delete_itr++){
  166. IsPointer<T>::Delete(*delete_itr);
  167. pending_deletes.erase(*delete_itr);
  168. }
  169. has_pending_deletes = (pending_deletes.size() > 0);
  170. }
  171. next_delete_attempt += 1000;
  172. --access_count;
  173. changing = false;
  174. }
  175. }
  176. private:
  177. volatile bool changing;
  178. volatile int access_count;
  179. volatile unsigned int next_delete_attempt;
  180. volatile bool has_pending_deletes;
  181. std::map<T, unsigned int> pending_deletes;
  182. };
  183. #endif