2
* Copyright 2011 Google Inc.
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
17
// Author: morlovich@google.com (Maksim Orlovich)
19
// This contains classes that abstract away creation of threads and
20
// synchronization primitives.
21
// - ThreadSystem (base class): acts as a factory for mutexes compatible
22
// with some runtime environment and must be passed to Thread ctor to use its
23
// threading abilities.
24
// - ThreadImpl: abstract interface used to communicate with threading
25
// backends by Thread instances.
27
#ifndef PAGESPEED_KERNEL_BASE_THREAD_SYSTEM_H_
28
#define PAGESPEED_KERNEL_BASE_THREAD_SYSTEM_H_
30
#include "pagespeed/kernel/base/abstract_mutex.h"
31
#include "pagespeed/kernel/base/basictypes.h"
32
#include "pagespeed/kernel/base/thread_annotations.h"
34
namespace net_instaweb {
38
// Subclasses of this represent threading support under given environment,
39
// and help create various primitives for it.
46
class LOCKABLE CondvarCapableMutex : public AbstractMutex {
48
CondvarCapableMutex() { }
49
virtual ~CondvarCapableMutex();
51
// Creates a new condition variable associated with 'this' mutex.
52
virtual Condvar* NewCondvar() = 0;
55
DISALLOW_COPY_AND_ASSIGN(CondvarCapableMutex);
58
// Interface for a Mutex with ReaderLocks(). It is possible for multiple
59
// Readers to simultaneously hold an RWLock. A reader cannot hold the
60
// lock at the same time as a Writer, nor can two Writers hold the lock.
61
class LOCKABLE RWLock : public AbstractMutex {
66
// ReaderLock/Unlock are different from normal locks. Reader locks are
67
// shared while normal locks are exclusive. Normal lock cannot happen when
69
// Try to acquire a read share of this lock without blocking.
70
virtual bool ReaderTryLock() SHARED_TRYLOCK_FUNCTION(true) = 0;
71
// Block until this Mutex is free, or shared, then acquire a share of it.
72
virtual void ReaderLock() SHARED_LOCK_FUNCTION() = 0;
73
// Release a read share of this Mutex.
74
virtual void ReaderUnlock() UNLOCK_FUNCTION() = 0;
76
// Optionally checks that reader lock is held (for invariant checking
77
// purposes). Default implementation does no checking.
78
virtual void DCheckReaderLocked();
81
DISALLOW_COPY_AND_ASSIGN(RWLock);
84
// Scoped reader-lock for using RWLock*. Facilitates grabbing a
85
// reader-lock on entry to a scope, and releasing it on exit.
86
// Similar to ScopedMutex found in AbstractMutex, except that
87
// multiple ScopedReaders can be simultaneously instantiated on
89
class SCOPED_LOCKABLE ScopedReader {
91
explicit ScopedReader(RWLock* lock) SHARED_LOCK_FUNCTION(lock)
96
void Release() UNLOCK_FUNCTION() {
97
// We allow Release called explicitly, before the ScopedReader goes
98
// out of scope and is destructed, calling Release again.
100
lock_->ReaderUnlock();
105
~ScopedReader() UNLOCK_FUNCTION() { Release(); }
110
DISALLOW_COPY_AND_ASSIGN(ScopedReader);
113
// Encapsulates a thread ID, whose type is dependent on the thread system
114
// implementation, and may be non-integral. E.g, see
115
// http://linux.die.net/man/3/pthread_self.
120
virtual bool IsEqual(const ThreadId& that) const = 0;
121
virtual bool IsCurrentThread() const = 0;
124
DISALLOW_COPY_AND_ASSIGN(ThreadId);
132
virtual ~ThreadSystem();
135
// Makes a new mutex for this system.
137
// See also CondvarCapableMutex::NewCondvar.
138
virtual CondvarCapableMutex* NewMutex() = 0;
140
// This lock will provide following guarantee -
141
// - Reader reentrant safe.
142
// - Writer Priority, this ensures no writer starvation.
143
virtual RWLock* NewRWLock() = 0;
145
// Creates and returns a real-time timer. Caller is responsible for deleting.
147
// TODO(jmarantz): consider removing this and controlling timers separately.
148
virtual Timer* NewTimer() = 0;
150
// Returns an object holding the current thread ID. The resultant object must
151
// be freed by the caller.
152
virtual ThreadId* GetThreadId() const = 0;
156
friend class MockThreadSystem;
157
friend class CheckingThreadSystem;
158
virtual ThreadImpl* NewThreadImpl(Thread* wrapper, ThreadFlags flags) = 0;
160
DISALLOW_COPY_AND_ASSIGN(ThreadSystem);
163
// ThreadImpl is the class that's inherited off when implementing threading ---
164
// ThreadSystem::NewThreadImpl is responsible for creating an appropriate
165
// instance that's hooked up to a given user Thread object.
166
class ThreadSystem::ThreadImpl {
168
virtual bool StartImpl() = 0;
169
virtual void JoinImpl() = 0;
170
virtual ~ThreadImpl();
176
DISALLOW_COPY_AND_ASSIGN(ThreadImpl);
179
// Catch bug where variable name is omitted with ScopedReader, e.g.
180
// ThreadSystem::ScopedReader(&lock);
181
#define ScopedReader(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name)
183
} // namespace net_instaweb
185
#endif // PAGESPEED_KERNEL_BASE_THREAD_SYSTEM_H_