mns_utils.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. // Copyright (C) 2015, Alibaba Cloud Computing
  2. #ifndef MNS_SDK_UTILS_H
  3. #define MNS_SDK_UTILS_H
  4. #include <string>
  5. #ifdef _WIN32
  6. #include <memory>
  7. #include <windows.h>
  8. #else
  9. #include <tr1/memory>
  10. #include <sys/time.h>
  11. #include <string.h>
  12. #endif
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <errno.h>
  16. #include <iostream>
  17. #include "mns_exception.h"
  18. #include "mns_common_tool.h"
  19. namespace mns
  20. {
  21. namespace sdk
  22. {
  23. #define MNS_LOCK_SAFE(x) \
  24. do \
  25. { \
  26. int r = (x); \
  27. if (r != 0) \
  28. { \
  29. int e = errno; \
  30. std::cerr << "MNS_LOCK_SAFE to abort() @ " << __FILE__ << ":" <<__LINE__ << " in " << __FUNCTION__ << std::endl \
  31. << "Ret:" << r << " errno:" << e << "(" << strerror(e) << ')' << std::endl; \
  32. abort(); \
  33. } \
  34. } while(false)
  35. class PTMutex
  36. {
  37. public:
  38. PTMutex()
  39. {
  40. #ifdef _WIN32
  41. InitializeCriticalSection(&cs);
  42. #else
  43. MNS_LOCK_SAFE(pthread_mutex_init(&mutex, NULL));
  44. #endif
  45. }
  46. ~PTMutex()
  47. {
  48. #ifdef _WIN32
  49. DeleteCriticalSection(&cs);
  50. #else
  51. MNS_LOCK_SAFE(pthread_mutex_destroy(&mutex));
  52. #endif
  53. }
  54. void lock()
  55. {
  56. #ifdef _WIN32
  57. EnterCriticalSection(&cs);
  58. #else
  59. MNS_LOCK_SAFE(pthread_mutex_lock(&mutex));
  60. #endif
  61. }
  62. void unlock()
  63. {
  64. #ifdef _WIN32
  65. LeaveCriticalSection(&cs);
  66. #else
  67. MNS_LOCK_SAFE(pthread_mutex_unlock(&mutex));
  68. #endif
  69. }
  70. #ifdef _WIN32
  71. CRITICAL_SECTION& get_pthread_mutex()
  72. {
  73. return cs;
  74. }
  75. #else
  76. pthread_mutex_t& get_pthread_mutex()
  77. {
  78. return mutex;
  79. }
  80. #endif
  81. protected:
  82. #ifdef _WIN32
  83. CRITICAL_SECTION cs;
  84. #else
  85. mutable pthread_mutex_t mutex;
  86. #endif
  87. };
  88. class PTCond
  89. {
  90. public:
  91. PTCond()
  92. {
  93. #ifdef _WIN32
  94. InitializeConditionVariable(&cond);
  95. #else
  96. MNS_LOCK_SAFE(pthread_cond_init(&cond, NULL));
  97. #endif
  98. }
  99. ~PTCond()
  100. {
  101. #ifndef _WIN32
  102. MNS_LOCK_SAFE(pthread_cond_destroy(&cond));
  103. #endif
  104. }
  105. int wait(PTMutex& mutex, int64_t usec)
  106. {
  107. #ifdef _WIN32
  108. if (usec < 0)
  109. {
  110. if (SleepConditionVariableCS(&cond, &(mutex.get_pthread_mutex()), INFINITE))
  111. {
  112. return 0;
  113. }
  114. else
  115. {
  116. return GetLastError();
  117. }
  118. }
  119. else
  120. {
  121. #define MICROSECONDS_PER_MILLISECOND 1000
  122. if (SleepConditionVariableCS(&cond, &(mutex.get_pthread_mutex()), (DWORD)usec / MICROSECONDS_PER_MILLISECOND))
  123. {
  124. return 0;
  125. }
  126. else
  127. {
  128. return GetLastError();
  129. }
  130. #undef MICROSECONDS_PER_MILLISECOND
  131. }
  132. #else
  133. int ret;
  134. if (usec == -1)
  135. {
  136. // never fail
  137. ret = pthread_cond_wait(&cond, &mutex.get_pthread_mutex());
  138. }
  139. else
  140. {
  141. if (usec < 0)
  142. {
  143. MNS_THROW(MNSExceptionBase, "PTCond::wait only accepts positve usec (expect usec = -1 for infinity wait)");
  144. }
  145. timespec ts;
  146. timeval tp;
  147. gettimeofday(&tp, 0);
  148. #define MICROSECONDS_PER_SECOND 1000000
  149. #define NANOSECONDS_PER_MICROSECONDS 1000
  150. /// Calculate "second" part. Caution, usec may exceeds MICROSECONDS_PER_SECOND.
  151. ts.tv_sec = tp.tv_sec + (usec / MICROSECONDS_PER_SECOND);
  152. /// Calcuate "microsecond" part.
  153. int usec_sum = tp.tv_usec + usec % MICROSECONDS_PER_SECOND;
  154. /// Adjust "second" part if usec_sum exceeds MICROSECONDS_PER_SECOND
  155. ts.tv_sec += usec_sum / MICROSECONDS_PER_SECOND;
  156. usec_sum %= MICROSECONDS_PER_SECOND;
  157. /// Calcuate nanosecond
  158. ts.tv_nsec = usec_sum * NANOSECONDS_PER_MICROSECONDS;
  159. #undef MICROSECONDS_PER_SECOND
  160. #undef NANOSECONDS_PER_MICROSECONDS
  161. // fail if timed-out or interupted by a signal
  162. ret = pthread_cond_timedwait(&cond, &mutex.get_pthread_mutex(), &ts);
  163. }
  164. return ret;
  165. #endif
  166. }
  167. void signal()
  168. {
  169. #ifdef _WIN32
  170. WakeConditionVariable(&cond);
  171. #else
  172. MNS_LOCK_SAFE(pthread_cond_signal(&cond));
  173. #endif
  174. }
  175. protected:
  176. #ifdef _WIN32
  177. CONDITION_VARIABLE cond;
  178. #else
  179. pthread_cond_t cond;
  180. #endif
  181. };
  182. class WaitObject
  183. {
  184. friend class PTScopedLock;
  185. PTMutex mutex;
  186. PTCond cond;
  187. public:
  188. WaitObject() {}
  189. int wait(int64_t timeout = -1)
  190. {
  191. return cond.wait(mutex, timeout);
  192. }
  193. void signal()
  194. {
  195. cond.signal();
  196. }
  197. };
  198. typedef std::shared_ptr<WaitObject> WaitObjectPtr;
  199. class PTScopedLock
  200. {
  201. private:
  202. PTMutex& mDevice;
  203. PTScopedLock(const PTScopedLock&);
  204. PTScopedLock& operator=(const PTScopedLock&);
  205. public:
  206. // lock when construct
  207. explicit PTScopedLock(PTMutex& m) : mDevice(m)
  208. {
  209. mDevice.lock();
  210. }
  211. explicit PTScopedLock(WaitObject& wo) : mDevice(wo.mutex)
  212. {
  213. mDevice.lock();
  214. }
  215. // unlock when destruct
  216. ~PTScopedLock()
  217. {
  218. mDevice.unlock();
  219. }
  220. };
  221. class MNSUtils
  222. {
  223. public:
  224. static std::string getLastNodeFromURL(const std::string& inputURL);
  225. static std::string escapeJson(const std::string &s);
  226. static std::string toJsonStr(const std::map<std::string, std::string>& param);
  227. };
  228. }
  229. }
  230. #endif