JSONNode_Mutex.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. #include "JSONNode.h"
  2. #include "JSONGlobals.h"
  3. #ifdef JSON_MUTEX_CALLBACKS
  4. json_mutex_callback_t json_lock_callback = 0;
  5. json_mutex_callback_t json_unlock_callback = 0;
  6. void * global_mutex = 0;
  7. void * manager_mutex = 0;
  8. struct AutoLock {
  9. public:
  10. LIBJSON_OBJECT(AutoLock);
  11. AutoLock(void) json_nothrow {
  12. LIBJSON_CTOR;
  13. json_lock_callback(manager_mutex);
  14. }
  15. ~AutoLock(void) json_nothrow {
  16. LIBJSON_DTOR;
  17. json_unlock_callback(manager_mutex);
  18. }
  19. private:
  20. AutoLock(const AutoLock &);
  21. AutoLock & operator = (const AutoLock &);
  22. };
  23. #ifdef JSON_MUTEX_MANAGE
  24. json_mutex_callback_t json_destroy = 0;
  25. //make sure that the global mutex is taken care of too
  26. struct auto_global {
  27. public:
  28. LIBJSON_OBJECT(auto_global;)
  29. auto_global(void) json_nothrow { LIBJSON_CTOR; }
  30. ~auto_global(void) json_nothrow {
  31. LIBJSON_DTOR;
  32. if (global_mutex){
  33. JSON_ASSERT_SAFE(json_destroy != 0, JSON_TEXT("No json_destroy in mutex managed mode"), return;);
  34. json_destroy(global_mutex);
  35. }
  36. }
  37. private:
  38. auto_global(const auto_global &);
  39. auto_global & operator = (const auto_global &);
  40. };
  41. auto_global cleanupGlobal;
  42. #endif
  43. void JSONNode::register_mutex_callbacks(json_mutex_callback_t lock, json_mutex_callback_t unlock, void * manager_lock) json_nothrow {
  44. json_lock_callback = lock;
  45. json_unlock_callback = unlock;
  46. manager_mutex = manager_lock;
  47. }
  48. void JSONNode::set_global_mutex(void * mutex) json_nothrow {
  49. global_mutex = mutex;
  50. }
  51. void JSONNode::set_mutex(void * mutex) json_nothrow {
  52. makeUniqueInternal();
  53. internal -> _set_mutex(mutex);
  54. }
  55. void * JSONNode::getThisLock(JSONNode * pthis) json_nothrow {
  56. if (pthis -> internal -> mylock != 0){
  57. return pthis -> internal -> mylock;
  58. }
  59. JSON_ASSERT(global_mutex != 0, JSON_TEXT("No global_mutex")); //this is safe, because it's just goingi to return 0 anyway
  60. return global_mutex;
  61. }
  62. void JSONNode::lock(int thread) json_nothrow {
  63. JSON_ASSERT_SAFE(json_lock_callback != 0, JSON_TEXT("No locking callback"), return;);
  64. AutoLock lockControl;
  65. //first, figure out what needs to be locked
  66. void * thislock = getThisLock(this);
  67. #ifdef JSON_SAFE
  68. if (json_unlikely(thislock == 0)) return;
  69. #endif
  70. //make sure that the same thread isn't locking it more than once (possible due to complex ref counting)
  71. JSON_MAP(int, JSON_MAP(void *, unsigned int) )::iterator it = json_global(THREAD_LOCKS).find(thread);
  72. if (it == json_global(THREAD_LOCKS).end()){
  73. JSON_MAP(void *, unsigned int) newthread;
  74. newthread[thislock] = 1;
  75. json_global(THREAD_LOCKS).insert(std::pair<int, JSON_MAP(void *, unsigned int) >(thread, newthread));
  76. } else { //this thread already has some things locked, check if the current mutex is
  77. JSON_MAP(void *, unsigned int) & newthread = it -> second;
  78. JSON_MAP(void *, unsigned int)::iterator locker(newthread.find(thislock));
  79. if (locker == newthread.end()){ //current mutex is not locked, set it to locked
  80. newthread.insert(std::pair<void *, unsigned int>(thislock, 1));
  81. } else { //it's already locked, don't relock it
  82. ++(locker -> second);
  83. return; //don't try to relock, it will deadlock the program
  84. }
  85. }
  86. //if I need to, lock it
  87. json_lock_callback(thislock);
  88. }
  89. void JSONNode::unlock(int thread) json_nothrow{
  90. JSON_ASSERT_SAFE(json_unlock_callback != 0, JSON_TEXT("No unlocking callback"), return;);
  91. AutoLock lockControl;
  92. //first, figure out what needs to be locked
  93. void * thislock = getThisLock(this);
  94. #ifdef JSON_SAFE
  95. if (thislock == 0) return;
  96. #endif
  97. //get it out of the map
  98. JSON_MAP(int, JSON_MAP(void *, unsigned int) )::iterator it = json_global(THREAD_LOCKS).find(thread);
  99. JSON_ASSERT_SAFE(it != json_global(THREAD_LOCKS).end(), JSON_TEXT("thread unlocking something it didn't lock"), return;);
  100. //get the mutex out of the thread
  101. JSON_MAP(void *, unsigned int) & newthread = it -> second;
  102. JSON_MAP(void *, unsigned int)::iterator locker = newthread.find(thislock);
  103. JSON_ASSERT_SAFE(locker != newthread.end(), JSON_TEXT("thread unlocking mutex it didn't lock"), return;);
  104. //unlock it
  105. if (--(locker -> second)) return; //other nodes is this same thread still have a lock on it
  106. //if I need to, unlock it
  107. newthread.erase(locker);
  108. json_unlock_callback(thislock);
  109. }
  110. #ifdef JSON_MUTEX_MANAGE
  111. void JSONNode::register_mutex_destructor(json_mutex_callback_t destroy) json_nothrow {
  112. json_destroy = destroy;
  113. }
  114. #endif
  115. void internalJSONNode::_set_mutex(void * mutex, bool unset) json_nothrow {
  116. if (unset) _unset_mutex(); //for reference counting
  117. mylock = mutex;
  118. if (mutex != 0){
  119. #ifdef JSON_MUTEX_MANAGE
  120. JSON_MAP(void *, unsigned int)::iterator it = json_global(MUTEX_MANAGER).find(mutex);
  121. if (it == json_global(MUTEX_MANAGER).end()){
  122. json_global(MUTEX_MANAGER).insert(std::pair<void *, unsigned int>(mutex, 1));
  123. } else {
  124. ++it -> second;
  125. }
  126. #endif
  127. if (isContainer()){
  128. json_foreach(CHILDREN, myrunner){
  129. (*myrunner) -> set_mutex(mutex);
  130. }
  131. }
  132. }
  133. }
  134. void internalJSONNode::_unset_mutex(void) json_nothrow {
  135. #ifdef JSON_MUTEX_MANAGE
  136. if (mylock != 0){
  137. JSON_MAP(void *, unsigned int)::iterator it = json_global(MUTEX_MANAGER).find(mylock);
  138. JSON_ASSERT_SAFE(it != json_global(MUTEX_MANAGER).end(), JSON_TEXT("Mutex not managed"), return;);
  139. --it -> second;
  140. if (it -> second == 0){
  141. JSON_ASSERT_SAFE(json_destroy, JSON_TEXT("You didn't register a destructor for mutexes"), return;);
  142. json_global(MUTEX_MANAGER).erase(it);
  143. }
  144. }
  145. #endif
  146. }
  147. #ifdef JSON_DEBUG
  148. #ifndef JSON_LIBRARY
  149. JSONNode internalJSONNode::DumpMutex(void) const json_nothrow {
  150. JSONNode mut(JSON_NODE);
  151. mut.set_name(JSON_TEXT("mylock"));
  152. #ifdef JSON_MUTEX_MANAGE
  153. if (mylock != 0){
  154. mut.push_back(JSON_NEW(JSONNode(JSON_TEXT("this"), (long)mylock)));
  155. JSON_MAP(void *, unsigned int)::iterator it = json_global(MUTEX_MANAGER).find(mylock);
  156. if (it == json_global(MUTEX_MANAGER).end()){
  157. mut.push_back(JSON_NEW(JSONNode(JSON_TEXT("references"), JSON_TEXT("error"))));
  158. } else {
  159. mut.push_back(JSON_NEW(JSONNode(JSON_TEXT("references"), it -> second)));
  160. }
  161. } else {
  162. mut = (long)mylock;
  163. }
  164. #else
  165. mut = (long)mylock;
  166. #endif
  167. return mut;
  168. }
  169. #endif
  170. #endif
  171. #else
  172. #ifdef JSON_MUTEX_MANAGE
  173. #error You can not have JSON_MUTEX_MANAGE on without JSON_MUTEX_CALLBACKS
  174. #endif
  175. #endif