PageRenderTime 64ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 0ms

/src/protobuf/src/google/protobuf/stubs/common.cc

http://decs.googlecode.com/
C++ | 342 lines | 229 code | 63 blank | 50 comment | 19 complexity | 3b75e79db6b989b82dc339edb7b80730 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-2.0
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // http://code.google.com/p/protobuf/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. // Author: kenton@google.com (Kenton Varda)
  31. #include <google/protobuf/stubs/common.h>
  32. #include <google/protobuf/stubs/once.h>
  33. #include <google/protobuf/stubs/strutil.h>
  34. #include <google/protobuf/stubs/substitute.h>
  35. #include <stdio.h>
  36. #include <errno.h>
  37. #include <vector>
  38. #include "config.h"
  39. #ifdef _WIN32
  40. #define WIN32_LEAN_AND_MEAN // We only need minimal includes
  41. #include <windows.h>
  42. #elif defined(HAVE_PTHREAD)
  43. #include <pthread.h>
  44. #else
  45. #error "No suitable threading library available."
  46. #endif
  47. namespace google {
  48. namespace protobuf {
  49. namespace internal {
  50. void VerifyVersion(int headerVersion,
  51. int minLibraryVersion,
  52. const char* filename) {
  53. if (GOOGLE_PROTOBUF_VERSION < minLibraryVersion) {
  54. // Library is too old for headers.
  55. GOOGLE_LOG(FATAL)
  56. << "This program requires version " << VersionString(minLibraryVersion)
  57. << " of the Protocol Buffer runtime library, but the installed version "
  58. "is " << VersionString(GOOGLE_PROTOBUF_VERSION) << ". Please update "
  59. "your library. If you compiled the program yourself, make sure that "
  60. "your headers are from the same version of Protocol Buffers as your "
  61. "link-time library. (Version verification failed in \""
  62. << filename << "\".)";
  63. }
  64. if (headerVersion < kMinHeaderVersionForLibrary) {
  65. // Headers are too old for library.
  66. GOOGLE_LOG(FATAL)
  67. << "This program was compiled against version "
  68. << VersionString(headerVersion) << " of the Protocol Buffer runtime "
  69. "library, which is not compatible with the installed version ("
  70. << VersionString(GOOGLE_PROTOBUF_VERSION) << "). Contact the program "
  71. "author for an update. If you compiled the program yourself, make "
  72. "sure that your headers are from the same version of Protocol Buffers "
  73. "as your link-time library. (Version verification failed in \""
  74. << filename << "\".)";
  75. }
  76. }
  77. string VersionString(int version) {
  78. int major = version / 1000000;
  79. int minor = (version / 1000) % 1000;
  80. int micro = version % 1000;
  81. return strings::Substitute("$0.$1.$2", major, minor, micro);
  82. }
  83. } // namespace internal
  84. // ===================================================================
  85. // emulates google3/base/logging.cc
  86. namespace internal {
  87. void DefaultLogHandler(LogLevel level, const char* filename, int line,
  88. const string& message) {
  89. static const char* level_names[] = { "INFO", "WARNING", "ERROR", "FATAL" };
  90. // We use fprintf() instead of cerr because we want this to work at static
  91. // initialization time.
  92. fprintf(stderr, "libprotobuf %s %s:%d] %s\n",
  93. level_names[level], filename, line, message.c_str());
  94. fflush(stderr); // Needed on MSVC.
  95. }
  96. void NullLogHandler(LogLevel level, const char* filename, int line,
  97. const string& message) {
  98. // Nothing.
  99. }
  100. static LogHandler* log_handler_ = &DefaultLogHandler;
  101. static int log_silencer_count_ = 0;
  102. static Mutex* log_silencer_count_mutex_ = NULL;
  103. GOOGLE_PROTOBUF_DECLARE_ONCE(log_silencer_count_init_);
  104. void DeleteLogSilencerCount() {
  105. delete log_silencer_count_mutex_;
  106. log_silencer_count_mutex_ = NULL;
  107. }
  108. void InitLogSilencerCount() {
  109. log_silencer_count_mutex_ = new Mutex;
  110. OnShutdown(&DeleteLogSilencerCount);
  111. }
  112. void InitLogSilencerCountOnce() {
  113. GoogleOnceInit(&log_silencer_count_init_, &InitLogSilencerCount);
  114. }
  115. static string SimpleCtoa(char c) { return string(1, c); }
  116. #undef DECLARE_STREAM_OPERATOR
  117. #define DECLARE_STREAM_OPERATOR(TYPE, TOSTRING) \
  118. LogMessage& LogMessage::operator<<(TYPE value) { \
  119. message_ += TOSTRING(value); \
  120. return *this; \
  121. }
  122. DECLARE_STREAM_OPERATOR(const string&, )
  123. DECLARE_STREAM_OPERATOR(const char* , )
  124. DECLARE_STREAM_OPERATOR(char , SimpleCtoa)
  125. DECLARE_STREAM_OPERATOR(int , SimpleItoa)
  126. DECLARE_STREAM_OPERATOR(uint , SimpleItoa)
  127. DECLARE_STREAM_OPERATOR(long , SimpleItoa)
  128. DECLARE_STREAM_OPERATOR(unsigned long, SimpleItoa)
  129. DECLARE_STREAM_OPERATOR(double , SimpleDtoa)
  130. #undef DECLARE_STREAM_OPERATOR
  131. LogMessage::LogMessage(LogLevel level, const char* filename, int line)
  132. : level_(level), filename_(filename), line_(line) {}
  133. LogMessage::~LogMessage() {}
  134. void LogMessage::Finish() {
  135. bool suppress = false;
  136. if (level_ != LOGLEVEL_FATAL) {
  137. InitLogSilencerCountOnce();
  138. MutexLock lock(log_silencer_count_mutex_);
  139. suppress = internal::log_silencer_count_ > 0;
  140. }
  141. if (!suppress) {
  142. internal::log_handler_(level_, filename_, line_, message_);
  143. }
  144. if (level_ == LOGLEVEL_FATAL) {
  145. abort();
  146. }
  147. }
  148. void LogFinisher::operator=(LogMessage& other) {
  149. other.Finish();
  150. }
  151. } // namespace internal
  152. LogHandler* SetLogHandler(LogHandler* new_func) {
  153. LogHandler* old = internal::log_handler_;
  154. if (old == &internal::NullLogHandler) {
  155. old = NULL;
  156. }
  157. if (new_func == NULL) {
  158. internal::log_handler_ = &internal::NullLogHandler;
  159. } else {
  160. internal::log_handler_ = new_func;
  161. }
  162. return old;
  163. }
  164. LogSilencer::LogSilencer() {
  165. internal::InitLogSilencerCountOnce();
  166. MutexLock lock(internal::log_silencer_count_mutex_);
  167. ++internal::log_silencer_count_;
  168. };
  169. LogSilencer::~LogSilencer() {
  170. internal::InitLogSilencerCountOnce();
  171. MutexLock lock(internal::log_silencer_count_mutex_);
  172. --internal::log_silencer_count_;
  173. };
  174. // ===================================================================
  175. // emulates google3/base/callback.cc
  176. Closure::~Closure() {}
  177. namespace internal { FunctionClosure0::~FunctionClosure0() {} }
  178. void DoNothing() {}
  179. // ===================================================================
  180. // emulates google3/base/mutex.cc
  181. #ifdef _WIN32
  182. struct Mutex::Internal {
  183. CRITICAL_SECTION mutex;
  184. #ifndef NDEBUG
  185. // Used only to implement AssertHeld().
  186. DWORD thread_id;
  187. #endif
  188. };
  189. Mutex::Mutex()
  190. : mInternal(new Internal) {
  191. InitializeCriticalSection(&mInternal->mutex);
  192. }
  193. Mutex::~Mutex() {
  194. DeleteCriticalSection(&mInternal->mutex);
  195. delete mInternal;
  196. }
  197. void Mutex::Lock() {
  198. EnterCriticalSection(&mInternal->mutex);
  199. #ifndef NDEBUG
  200. mInternal->thread_id = GetCurrentThreadId();
  201. #endif
  202. }
  203. void Mutex::Unlock() {
  204. #ifndef NDEBUG
  205. mInternal->thread_id = 0;
  206. #endif
  207. LeaveCriticalSection(&mInternal->mutex);
  208. }
  209. void Mutex::AssertHeld() {
  210. #ifndef NDEBUG
  211. GOOGLE_DCHECK_EQ(mInternal->thread_id, GetCurrentThreadId());
  212. #endif
  213. }
  214. #elif defined(HAVE_PTHREAD)
  215. struct Mutex::Internal {
  216. pthread_mutex_t mutex;
  217. };
  218. Mutex::Mutex()
  219. : mInternal(new Internal) {
  220. pthread_mutex_init(&mInternal->mutex, NULL);
  221. }
  222. Mutex::~Mutex() {
  223. pthread_mutex_destroy(&mInternal->mutex);
  224. delete mInternal;
  225. }
  226. void Mutex::Lock() {
  227. int result = pthread_mutex_lock(&mInternal->mutex);
  228. if (result != 0) {
  229. GOOGLE_LOG(FATAL) << "pthread_mutex_lock: " << strerror(result);
  230. }
  231. }
  232. void Mutex::Unlock() {
  233. int result = pthread_mutex_unlock(&mInternal->mutex);
  234. if (result != 0) {
  235. GOOGLE_LOG(FATAL) << "pthread_mutex_unlock: " << strerror(result);
  236. }
  237. }
  238. void Mutex::AssertHeld() {
  239. // pthreads dosn't provide a way to check which thread holds the mutex.
  240. // TODO(kenton): Maybe keep track of locking thread ID like with WIN32?
  241. }
  242. #endif
  243. // ===================================================================
  244. // Shutdown support.
  245. namespace internal {
  246. typedef void OnShutdownFunc();
  247. vector<void (*)()>* shutdown_functions = NULL;
  248. Mutex* shutdown_functions_mutex = NULL;
  249. GOOGLE_PROTOBUF_DECLARE_ONCE(shutdown_functions_init);
  250. void InitShutdownFunctions() {
  251. shutdown_functions = new vector<void (*)()>;
  252. shutdown_functions_mutex = new Mutex;
  253. }
  254. inline void InitShutdownFunctionsOnce() {
  255. GoogleOnceInit(&shutdown_functions_init, &InitShutdownFunctions);
  256. }
  257. void OnShutdown(void (*func)()) {
  258. InitShutdownFunctionsOnce();
  259. MutexLock lock(shutdown_functions_mutex);
  260. shutdown_functions->push_back(func);
  261. }
  262. } // namespace internal
  263. void ShutdownProtobufLibrary() {
  264. internal::InitShutdownFunctionsOnce();
  265. // We don't need to lock shutdown_functions_mutex because it's up to the
  266. // caller to make sure that no one is using the library before this is
  267. // called.
  268. // Make it safe to call this multiple times.
  269. if (internal::shutdown_functions == NULL) return;
  270. for (int i = 0; i < internal::shutdown_functions->size(); i++) {
  271. internal::shutdown_functions->at(i)();
  272. }
  273. delete internal::shutdown_functions;
  274. internal::shutdown_functions = NULL;
  275. delete internal::shutdown_functions_mutex;
  276. internal::shutdown_functions_mutex = NULL;
  277. }
  278. } // namespace protobuf
  279. } // namespace google