Source code

Revision control

Other Tools

1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
* License, v. 2.0. If a copy of the MPL was not distributed with this
5
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
// An interface for read-write locks.
8
9
#ifndef mozilla_RWLock_h
10
#define mozilla_RWLock_h
11
12
#include "mozilla/Assertions.h"
13
#include "mozilla/BlockingResourceBase.h"
14
#include "mozilla/GuardObjects.h"
15
16
#ifndef XP_WIN
17
# include <pthread.h>
18
#endif
19
20
namespace mozilla {
21
22
// A RWLock is similar to a Mutex, but whereas a Mutex permits only a single
23
// reader thread or a single writer thread to access a piece of data, a
24
// RWLock distinguishes between readers and writers: you may have multiple
25
// reader threads concurrently accessing a piece of data or a single writer
26
// thread. This difference should guide your usage of RWLock: if you are not
27
// reading the data from multiple threads simultaneously or you are writing
28
// to the data roughly as often as read from it, then Mutex will suit your
29
// purposes just fine.
30
//
31
// You should be using the AutoReadLock and AutoWriteLock classes, below,
32
// for RAII read locking and write locking, respectively. If you really must
33
// take a read lock manually, call the ReadLock method; to relinquish that
34
// read lock, call the ReadUnlock method. Similarly, WriteLock and WriteUnlock
35
// perform the same operations, but for write locks.
36
//
37
// It is unspecified what happens when a given thread attempts to acquire the
38
// same lock in multiple ways; some underlying implementations of RWLock do
39
// support acquiring a read lock multiple times on a given thread, but you
40
// should not rely on this behavior.
41
//
42
// It is unspecified whether RWLock gives priority to waiting readers or
43
// a waiting writer when unlocking.
44
class RWLock : public BlockingResourceBase {
45
public:
46
explicit RWLock(const char* aName);
47
48
// Windows rwlocks don't need any special handling to be destroyed, but
49
// POSIX ones do.
50
#ifdef XP_WIN
51
~RWLock() = default;
52
#else
53
~RWLock();
54
#endif
55
56
#ifdef DEBUG
57
bool LockedForWritingByCurrentThread();
58
void ReadLock();
59
void ReadUnlock();
60
void WriteLock();
61
void WriteUnlock();
62
#else
63
void ReadLock() { ReadLockInternal(); }
64
void ReadUnlock() { ReadUnlockInternal(); }
65
void WriteLock() { WriteLockInternal(); }
66
void WriteUnlock() { WriteUnlockInternal(); }
67
#endif
68
69
private:
70
void ReadLockInternal();
71
void ReadUnlockInternal();
72
void WriteLockInternal();
73
void WriteUnlockInternal();
74
75
RWLock() = delete;
76
RWLock(const RWLock&) = delete;
77
RWLock& operator=(const RWLock&) = delete;
78
79
#ifndef XP_WIN
80
pthread_rwlock_t mRWLock;
81
#else
82
// SRWLock is pointer-sized. We declare it in such a fashion here to
83
// avoid pulling in windows.h wherever this header is used.
84
void* mRWLock;
85
#endif
86
87
#ifdef DEBUG
88
// We record the owning thread for write locks only.
89
PRThread* mOwningThread;
90
#endif
91
};
92
93
// Read lock and unlock a RWLock with RAII semantics. Much preferred to bare
94
// calls to ReadLock() and ReadUnlock().
95
class MOZ_RAII AutoReadLock final {
96
public:
97
explicit AutoReadLock(RWLock& aLock MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
98
: mLock(&aLock) {
99
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
100
MOZ_ASSERT(mLock, "null lock");
101
mLock->ReadLock();
102
}
103
104
~AutoReadLock() { mLock->ReadUnlock(); }
105
106
private:
107
AutoReadLock() = delete;
108
AutoReadLock(const AutoReadLock&) = delete;
109
AutoReadLock& operator=(const AutoReadLock&) = delete;
110
111
RWLock* mLock;
112
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
113
};
114
115
// Write lock and unlock a RWLock with RAII semantics. Much preferred to bare
116
// calls to WriteLock() and WriteUnlock().
117
class MOZ_RAII AutoWriteLock final {
118
public:
119
explicit AutoWriteLock(RWLock& aLock MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
120
: mLock(&aLock) {
121
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
122
MOZ_ASSERT(mLock, "null lock");
123
mLock->WriteLock();
124
}
125
126
~AutoWriteLock() { mLock->WriteUnlock(); }
127
128
private:
129
AutoWriteLock() = delete;
130
AutoWriteLock(const AutoWriteLock&) = delete;
131
AutoWriteLock& operator=(const AutoWriteLock&) = delete;
132
133
RWLock* mLock;
134
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
135
};
136
137
} // namespace mozilla
138
139
#endif // mozilla_RWLock_h