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 31// Author: kenton@google.com (Kenton Varda) 32 33#include <google/protobuf/stubs/common.h> 34#include <google/protobuf/stubs/once.h> 35#include <stdio.h> 36#include <errno.h> 37#include <vector> 38 39#include "config.h" 40 41#ifdef _WIN32 42#define WIN32_LEAN_AND_MEAN // We only need minimal includes 43#include <windows.h> 44#define snprintf _snprintf // see comment in strutil.cc 45#elif defined(HAVE_PTHREAD) 46#include <pthread.h> 47#else 48#error "No suitable threading library available." 49#endif 50 51namespace google { 52namespace protobuf { 53 54namespace internal { 55 56void VerifyVersion(int headerVersion, 57 int minLibraryVersion, 58 const char* filename) { 59 if (GOOGLE_PROTOBUF_VERSION < minLibraryVersion) { 60 // Library is too old for headers. 61 GOOGLE_LOG(FATAL) 62 << "This program requires version " << VersionString(minLibraryVersion) 63 << " of the Protocol Buffer runtime library, but the installed version " 64 "is " << VersionString(GOOGLE_PROTOBUF_VERSION) << ". Please update " 65 "your library. If you compiled the program yourself, make sure that " 66 "your headers are from the same version of Protocol Buffers as your " 67 "link-time library. (Version verification failed in \"" 68 << filename << "\".)"; 69 } 70 if (headerVersion < kMinHeaderVersionForLibrary) { 71 // Headers are too old for library. 72 GOOGLE_LOG(FATAL) 73 << "This program was compiled against version " 74 << VersionString(headerVersion) << " of the Protocol Buffer runtime " 75 "library, which is not compatible with the installed version (" 76 << VersionString(GOOGLE_PROTOBUF_VERSION) << "). Contact the program " 77 "author for an update. If you compiled the program yourself, make " 78 "sure that your headers are from the same version of Protocol Buffers " 79 "as your link-time library. (Version verification failed in \"" 80 << filename << "\".)"; 81 } 82} 83 84string VersionString(int version) { 85 int major = version / 1000000; 86 int minor = (version / 1000) % 1000; 87 int micro = version % 1000; 88 89 // 128 bytes should always be enough, but we use snprintf() anyway to be 90 // safe. 91 char buffer[128]; 92 snprintf(buffer, sizeof(buffer), "%d.%d.%d", major, minor, micro); 93 94 // Guard against broken MSVC snprintf(). 95 buffer[sizeof(buffer)-1] = '\0'; 96 97 return buffer; 98} 99 100} // namespace internal 101 102// =================================================================== 103// emulates google3/base/logging.cc 104 105namespace internal { 106 107void DefaultLogHandler(LogLevel level, const char* filename, int line, 108 const string& message) { 109 static const char* level_names[] = { "INFO", "WARNING", "ERROR", "FATAL" }; 110 111 // We use fprintf() instead of cerr because we want this to work at static 112 // initialization time. 113 fprintf(stderr, "libprotobuf %s %s:%d] %s\n", 114 level_names[level], filename, line, message.c_str()); 115 fflush(stderr); // Needed on MSVC. 116} 117 118void NullLogHandler(LogLevel level, const char* filename, int line, 119 const string& message) { 120 // Nothing. 121} 122 123static LogHandler* log_handler_ = &DefaultLogHandler; 124static int log_silencer_count_ = 0; 125 126static Mutex* log_silencer_count_mutex_ = NULL; 127GOOGLE_PROTOBUF_DECLARE_ONCE(log_silencer_count_init_); 128 129void DeleteLogSilencerCount() { 130 delete log_silencer_count_mutex_; 131 log_silencer_count_mutex_ = NULL; 132} 133void InitLogSilencerCount() { 134 log_silencer_count_mutex_ = new Mutex; 135 OnShutdown(&DeleteLogSilencerCount); 136} 137void InitLogSilencerCountOnce() { 138 GoogleOnceInit(&log_silencer_count_init_, &InitLogSilencerCount); 139} 140 141LogMessage& LogMessage::operator<<(const string& value) { 142 message_ += value; 143 return *this; 144} 145 146LogMessage& LogMessage::operator<<(const char* value) { 147 message_ += value; 148 return *this; 149} 150 151// Since this is just for logging, we don't care if the current locale changes 152// the results -- in fact, we probably prefer that. So we use snprintf() 153// instead of Simple*toa(). 154#undef DECLARE_STREAM_OPERATOR 155#define DECLARE_STREAM_OPERATOR(TYPE, FORMAT) \ 156 LogMessage& LogMessage::operator<<(TYPE value) { \ 157 /* 128 bytes should be big enough for any of the primitive */ \ 158 /* values which we print with this, but well use snprintf() */ \ 159 /* anyway to be extra safe. */ \ 160 char buffer[128]; \ 161 snprintf(buffer, sizeof(buffer), FORMAT, value); \ 162 /* Guard against broken MSVC snprintf(). */ \ 163 buffer[sizeof(buffer)-1] = '\0'; \ 164 message_ += buffer; \ 165 return *this; \ 166 } 167 168DECLARE_STREAM_OPERATOR(char , "%c" ) 169DECLARE_STREAM_OPERATOR(int , "%d" ) 170DECLARE_STREAM_OPERATOR(uint , "%u" ) 171DECLARE_STREAM_OPERATOR(long , "%ld") 172DECLARE_STREAM_OPERATOR(unsigned long, "%lu") 173DECLARE_STREAM_OPERATOR(double , "%g" ) 174#undef DECLARE_STREAM_OPERATOR 175 176LogMessage::LogMessage(LogLevel level, const char* filename, int line) 177 : level_(level), filename_(filename), line_(line) {} 178LogMessage::~LogMessage() {} 179 180void LogMessage::Finish() { 181 bool suppress = false; 182 183 if (level_ != LOGLEVEL_FATAL) { 184 InitLogSilencerCountOnce(); 185 MutexLock lock(log_silencer_count_mutex_); 186 suppress = internal::log_silencer_count_ > 0; 187 } 188 189 if (!suppress) { 190 internal::log_handler_(level_, filename_, line_, message_); 191 } 192 193 if (level_ == LOGLEVEL_FATAL) { 194 abort(); 195 } 196} 197 198void LogFinisher::operator=(LogMessage& other) { 199 other.Finish(); 200} 201 202} // namespace internal 203 204LogHandler* SetLogHandler(LogHandler* new_func) { 205 LogHandler* old = internal::log_handler_; 206 if (old == &internal::NullLogHandler) { 207 old = NULL; 208 } 209 if (new_func == NULL) { 210 internal::log_handler_ = &internal::NullLogHandler; 211 } else { 212 internal::log_handler_ = new_func; 213 } 214 return old; 215} 216 217LogSilencer::LogSilencer() { 218 internal::InitLogSilencerCountOnce(); 219 MutexLock lock(internal::log_silencer_count_mutex_); 220 ++internal::log_silencer_count_; 221}; 222 223LogSilencer::~LogSilencer() { 224 internal::InitLogSilencerCountOnce(); 225 MutexLock lock(internal::log_silencer_count_mutex_); 226 --internal::log_silencer_count_; 227}; 228 229// =================================================================== 230// emulates google3/base/callback.cc 231 232Closure::~Closure() {} 233 234namespace internal { FunctionClosure0::~FunctionClosure0() {} } 235 236void DoNothing() {} 237 238// =================================================================== 239// emulates google3/base/mutex.cc 240 241#ifdef _WIN32 242 243struct Mutex::Internal { 244 CRITICAL_SECTION mutex; 245#ifndef NDEBUG 246 // Used only to implement AssertHeld(). 247 DWORD thread_id; 248#endif 249}; 250 251Mutex::Mutex() 252 : mInternal(new Internal) { 253 InitializeCriticalSection(&mInternal->mutex); 254} 255 256Mutex::~Mutex() { 257 DeleteCriticalSection(&mInternal->mutex); 258 delete mInternal; 259} 260 261void Mutex::Lock() { 262 EnterCriticalSection(&mInternal->mutex); 263#ifndef NDEBUG 264 mInternal->thread_id = GetCurrentThreadId(); 265#endif 266} 267 268void Mutex::Unlock() { 269#ifndef NDEBUG 270 mInternal->thread_id = 0; 271#endif 272 LeaveCriticalSection(&mInternal->mutex); 273} 274 275void Mutex::AssertHeld() { 276#ifndef NDEBUG 277 GOOGLE_DCHECK_EQ(mInternal->thread_id, GetCurrentThreadId()); 278#endif 279} 280 281#elif defined(HAVE_PTHREAD) 282 283struct Mutex::Internal { 284 pthread_mutex_t mutex; 285}; 286 287Mutex::Mutex() 288 : mInternal(new Internal) { 289 pthread_mutex_init(&mInternal->mutex, NULL); 290} 291 292Mutex::~Mutex() { 293 pthread_mutex_destroy(&mInternal->mutex); 294 delete mInternal; 295} 296 297void Mutex::Lock() { 298 int result = pthread_mutex_lock(&mInternal->mutex); 299 if (result != 0) { 300 GOOGLE_LOG(FATAL) << "pthread_mutex_lock: " << strerror(result); 301 } 302} 303 304void Mutex::Unlock() { 305 int result = pthread_mutex_unlock(&mInternal->mutex); 306 if (result != 0) { 307 GOOGLE_LOG(FATAL) << "pthread_mutex_unlock: " << strerror(result); 308 } 309} 310 311void Mutex::AssertHeld() { 312 // pthreads dosn't provide a way to check which thread holds the mutex. 313 // TODO(kenton): Maybe keep track of locking thread ID like with WIN32? 314} 315 316#endif 317 318// =================================================================== 319// Shutdown support. 320 321namespace internal { 322 323typedef void OnShutdownFunc(); 324vector<void (*)()>* shutdown_functions = NULL; 325Mutex* shutdown_functions_mutex = NULL; 326GOOGLE_PROTOBUF_DECLARE_ONCE(shutdown_functions_init); 327 328void InitShutdownFunctions() { 329 shutdown_functions = new vector<void (*)()>; 330 shutdown_functions_mutex = new Mutex; 331} 332 333inline void InitShutdownFunctionsOnce() { 334 GoogleOnceInit(&shutdown_functions_init, &InitShutdownFunctions); 335} 336 337void OnShutdown(void (*func)()) { 338 InitShutdownFunctionsOnce(); 339 MutexLock lock(shutdown_functions_mutex); 340 shutdown_functions->push_back(func); 341} 342 343} // namespace internal 344 345void ShutdownProtobufLibrary() { 346 internal::InitShutdownFunctionsOnce(); 347 348 // We don't need to lock shutdown_functions_mutex because it's up to the 349 // caller to make sure that no one is using the library before this is 350 // called. 351 352 // Make it safe to call this multiple times. 353 if (internal::shutdown_functions == NULL) return; 354 355 for (int i = 0; i < internal::shutdown_functions->size(); i++) { 356 internal::shutdown_functions->at(i)(); 357 } 358 delete internal::shutdown_functions; 359 internal::shutdown_functions = NULL; 360 delete internal::shutdown_functions_mutex; 361 internal::shutdown_functions_mutex = NULL; 362} 363 364} // namespace protobuf 365} // namespace google 366