MutexList.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  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 MUTEXLIST_H
  17. #define MUTEXLIST_H
  18. #include <list>
  19. #include "MutexHelper.h"
  20. #define MUTEXLIST_PENDING_ADD 1
  21. #define MUTEXLIST_PENDING_REMOVE 2
  22. #define MUTEXLIST_PENDING_DELETE 3
  23. template <typename T>
  24. class MutexList{
  25. public:
  26. MutexList(){
  27. pending_changing = false;
  28. has_pending_data = false;
  29. pending_clear = false;
  30. changing = false;
  31. access_count = 0;
  32. access_pending = 0;
  33. }
  34. MutexList(const MutexList& list){
  35. pending_changing = false;
  36. has_pending_data = false;
  37. pending_clear = false;
  38. changing = false;
  39. access_count = 0;
  40. access_pending = 0;
  41. /*if(list.has_pending_data)
  42. pending_data = list.pending_data;
  43. current_data = list.current_data; */
  44. }
  45. ~MutexList(){
  46. while(!update(true)){
  47. Sleep(1);
  48. }
  49. }
  50. class iterator {
  51. private:
  52. typename std::list<T>::iterator itr; // Current element
  53. MutexList<T>* list;
  54. bool first_itr;
  55. public:
  56. iterator(){
  57. }
  58. iterator(MutexList<T>* list){
  59. if(list){
  60. this->list = list;
  61. list->update();
  62. this->list->AddAccess();
  63. first_itr = true;
  64. itr = list->current_data.begin();
  65. if(itr != list->current_data.end())
  66. value = *itr;
  67. }
  68. else
  69. this->list = 0;
  70. }
  71. ~iterator(){
  72. if(list)
  73. list->RemoveAccess();
  74. }
  75. bool HasNext(){
  76. return itr != list->current_data.end();
  77. }
  78. bool Next(){
  79. if(list->pending_clear)
  80. return false;
  81. if(first_itr)
  82. first_itr = false;
  83. else
  84. itr++;
  85. if(itr != list->current_data.end()){
  86. value = *itr;
  87. if(list->PendingContains(value)) //pending delete
  88. return Next();
  89. return true;
  90. }
  91. return false;
  92. }
  93. iterator* operator->() {
  94. return this;
  95. }
  96. T value;
  97. };
  98. void SetChanging(){
  99. ChangingLock.lock();
  100. changing = true;
  101. ChangingLock.unlock();
  102. }
  103. void SetNotChanging(){
  104. ChangingLock.lock();
  105. changing = false;
  106. ChangingLock.unlock();
  107. }
  108. void AddAccess(){
  109. AccessLock.lock();
  110. ++access_count;
  111. AccessLock.unlock();
  112. }
  113. void RemoveAccess(){
  114. AccessLock.lock();
  115. --access_count;
  116. AccessLock.unlock();
  117. }
  118. unsigned int size(bool include_pending = false){
  119. if(include_pending){
  120. update();
  121. return current_data.size() + pending_data.size();
  122. }
  123. return current_data.size();
  124. }
  125. iterator begin(){
  126. return iterator(this);
  127. }
  128. void clear(bool erase_all = false){
  129. pending_clear = true;
  130. if(erase_all){
  131. AddAccess();
  132. PendingLock.lock();
  133. typename std::list<T>::iterator itr;
  134. for(itr = current_data.begin(); itr != current_data.end(); itr++){
  135. RemoveData(*itr);
  136. }
  137. PendingLock.unlock();
  138. RemoveAccess();
  139. }
  140. update();
  141. }
  142. bool PendingContains(T key){
  143. if(!has_pending_data)
  144. return false;
  145. bool ret = false;
  146. PendingLock.lock();
  147. ret = (pending_data.count(key) > 0 && pending_data[key] == false);
  148. PendingLock.unlock();
  149. return ret;
  150. }
  151. unsigned int count(T key){
  152. unsigned int ret = 0;
  153. while(changing){
  154. Sleep(1);
  155. }
  156. AddAccess();
  157. bool retry = false;
  158. if(!changing){
  159. typename std::list<T>::iterator iter;
  160. for(iter = current_data.begin(); iter != current_data.end(); iter++){
  161. if(*iter == key)
  162. ret++;
  163. }
  164. }
  165. else
  166. retry = true;
  167. RemoveAccess();
  168. if(retry)
  169. return count(key); //only occurs whenever we change to changing state at the same time as a reading state
  170. return ret;
  171. }
  172. void RemoveData(T key, int32 erase_time = 0){
  173. handle_deletes.AddPendingDelete(key, Timer::GetCurrentTime2() + erase_time);
  174. }
  175. void Remove(T key, bool erase = false, int32 erase_time = 0){
  176. while(changing){
  177. Sleep(1);
  178. }
  179. AddAccess();
  180. PendingLock.lock();
  181. pending_data[key] = false;
  182. PendingLock.unlock();
  183. if(erase)
  184. RemoveData(key, erase_time);
  185. has_pending_data = true;
  186. RemoveAccess();
  187. update();
  188. }
  189. void Add(T key){
  190. if(count(key) > 0)
  191. return;
  192. while(changing){
  193. Sleep(1);
  194. }
  195. AddAccess();
  196. PendingLock.lock();
  197. pending_data[key] = true;
  198. PendingLock.unlock();
  199. has_pending_data = true;
  200. RemoveAccess();
  201. update();
  202. }
  203. private:
  204. bool update(bool force = false){
  205. //if(access_count > 5)
  206. // cout << "Possible error.\n";
  207. while(changing){
  208. Sleep(1);
  209. }
  210. if(pending_clear && access_count == 0){
  211. SetChanging();
  212. while(access_count > 0){
  213. Sleep(1);
  214. }
  215. AddAccess();
  216. PendingLock.lock();
  217. current_data.clear();
  218. has_pending_data = (pending_data.size() > 0);
  219. PendingLock.unlock();
  220. pending_clear = false;
  221. RemoveAccess();
  222. SetNotChanging();
  223. }
  224. if(!pending_clear && has_pending_data && access_count == 0){
  225. SetChanging();
  226. while(access_count > 0){
  227. Sleep(1);
  228. }
  229. AddAccess();
  230. PendingLock.lock();
  231. typename std::map<T, bool>::iterator pending_itr;
  232. for(pending_itr = pending_data.begin(); pending_itr != pending_data.end(); pending_itr++){
  233. if(pending_itr->second)
  234. current_data.push_back(pending_itr->first);
  235. else
  236. current_data.remove(pending_itr->first);
  237. }
  238. pending_data.clear();
  239. PendingLock.unlock();
  240. has_pending_data = false;
  241. RemoveAccess();
  242. SetNotChanging();
  243. }
  244. handle_deletes.CheckDeletes(force);
  245. return !pending_clear && !has_pending_data;
  246. }
  247. Locker PendingLock;
  248. Locker AccessLock;
  249. Locker ChangingLock;
  250. volatile int access_count;
  251. std::list<T> current_data;
  252. std::map<T, bool> pending_data;
  253. HandleDeletes<T> handle_deletes;
  254. volatile int access_pending;
  255. volatile bool pending_changing;
  256. volatile bool changing;
  257. volatile bool has_pending_data;
  258. volatile bool pending_clear;
  259. };
  260. #endif