Line data Source code
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 620 : explicit MutexLock(Mutex *mu) : mu_(mu) { this->mu_->Lock(); }
85 619 : ~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 3305 : mu_(mu) { if (this->mu_ != NULL) { this->mu_->Lock(); } }
100 3305 : ~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_
|