Home | History | Annotate | Download | only in stubs
      1 // Copyright (c) 2006, Google Inc.
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are
      6 // met:
      7 //
      8 //     * Redistributions of source code must retain the above copyright
      9 // notice, this list of conditions and the following disclaimer.
     10 //     * Redistributions in binary form must reproduce the above
     11 // copyright notice, this list of conditions and the following disclaimer
     12 // in the documentation and/or other materials provided with the
     13 // distribution.
     14 //     * Neither the name of Google Inc. nor the names of its
     15 // contributors may be used to endorse or promote products derived from
     16 // this software without specific prior written permission.
     17 //
     18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 
     30 #ifndef GOOGLE_PROTOBUF_STUBS_MUTEX_H_
     31 #define GOOGLE_PROTOBUF_STUBS_MUTEX_H_
     32 
     33 #ifdef GOOGLE_PROTOBUF_NO_THREADLOCAL
     34 #include <pthread.h>
     35 #endif
     36 
     37 #include <google/protobuf/stubs/macros.h>
     38 
     39 // ===================================================================
     40 // emulates google3/base/mutex.h
     41 namespace google {
     42 namespace protobuf {
     43 namespace internal {
     44 
     45 // A Mutex is a non-reentrant (aka non-recursive) mutex.  At most one thread T
     46 // may hold a mutex at a given time.  If T attempts to Lock() the same Mutex
     47 // while holding it, T will deadlock.
     48 class LIBPROTOBUF_EXPORT Mutex {
     49  public:
     50   // Create a Mutex that is not held by anybody.
     51   Mutex();
     52 
     53   // Destructor
     54   ~Mutex();
     55 
     56   // Block if necessary until this Mutex is free, then acquire it exclusively.
     57   void Lock();
     58 
     59   // Release this Mutex.  Caller must hold it exclusively.
     60   void Unlock();
     61 
     62   // Crash if this Mutex is not held exclusively by this thread.
     63   // May fail to crash when it should; will never crash when it should not.
     64   void AssertHeld();
     65 
     66  private:
     67   struct Internal;
     68   Internal* mInternal;
     69 
     70   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Mutex);
     71 };
     72 
     73 // Undefine the macros  to workaround the conflicts with Google internal
     74 // MutexLock implementation.
     75 // TODO(liujisi): Remove the undef once internal macros are removed.
     76 #undef MutexLock
     77 #undef ReaderMutexLock
     78 #undef WriterMutexLock
     79 #undef MutexLockMaybe
     80 
     81 // MutexLock(mu) acquires mu when constructed and releases it when destroyed.
     82 class LIBPROTOBUF_EXPORT MutexLock {
     83  public:
     84   explicit MutexLock(Mutex *mu) : mu_(mu) { this->mu_->Lock(); }
     85   ~MutexLock() { this->mu_->Unlock(); }
     86  private:
     87   Mutex *const mu_;
     88   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLock);
     89 };
     90 
     91 // TODO(kenton):  Implement these?  Hard to implement portably.
     92 typedef MutexLock ReaderMutexLock;
     93 typedef MutexLock WriterMutexLock;
     94 
     95 // MutexLockMaybe is like MutexLock, but is a no-op when mu is NULL.
     96 class LIBPROTOBUF_EXPORT MutexLockMaybe {
     97  public:
     98   explicit MutexLockMaybe(Mutex *mu) :
     99     mu_(mu) { if (this->mu_ != NULL) { this->mu_->Lock(); } }
    100   ~MutexLockMaybe() { if (this->mu_ != NULL) { this->mu_->Unlock(); } }
    101  private:
    102   Mutex *const mu_;
    103   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLockMaybe);
    104 };
    105 
    106 #if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
    107 template<typename T>
    108 class ThreadLocalStorage {
    109  public:
    110   ThreadLocalStorage() {
    111     pthread_key_create(&key_, &ThreadLocalStorage::Delete);
    112   }
    113   ~ThreadLocalStorage() {
    114     pthread_key_delete(key_);
    115   }
    116   T* Get() {
    117     T* result = static_cast<T*>(pthread_getspecific(key_));
    118     if (result == NULL) {
    119       result = new T();
    120       pthread_setspecific(key_, result);
    121     }
    122     return result;
    123   }
    124  private:
    125   static void Delete(void* value) {
    126     delete static_cast<T*>(value);
    127   }
    128   pthread_key_t key_;
    129 
    130   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadLocalStorage);
    131 };
    132 #endif
    133 
    134 }  // namespace internal
    135 
    136 // We made these internal so that they would show up as such in the docs,
    137 // but we don't want to stick "internal::" in front of them everywhere.
    138 using internal::Mutex;
    139 using internal::MutexLock;
    140 using internal::ReaderMutexLock;
    141 using internal::WriterMutexLock;
    142 using internal::MutexLockMaybe;
    143 
    144 
    145 }  // namespace protobuf
    146 }  // namespace google
    147 
    148 #endif  // GOOGLE_PROTOBUF_STUBS_MUTEX_H_
    149