Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/ReentrantMonitor.h
Line
Count
Source (jump to first uncovered line)
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
#ifndef mozilla_ReentrantMonitor_h
8
#define mozilla_ReentrantMonitor_h
9
10
#include "prmon.h"
11
12
#ifdef MOZILLA_INTERNAL_API
13
#include "GeckoProfiler.h"
14
#endif //MOZILLA_INTERNAL_API
15
16
#include "mozilla/BlockingResourceBase.h"
17
18
//
19
// Provides:
20
//
21
//  - ReentrantMonitor, a Java-like monitor
22
//  - ReentrantMonitorAutoEnter, an RAII class for ensuring that
23
//    ReentrantMonitors are properly entered and exited
24
//
25
// Using ReentrantMonitorAutoEnter is MUCH preferred to making bare calls to
26
// ReentrantMonitor.Enter and Exit.
27
//
28
namespace mozilla {
29
30
31
/**
32
 * ReentrantMonitor
33
 * Java-like monitor.
34
 * When possible, use ReentrantMonitorAutoEnter to hold this monitor within a
35
 * scope, instead of calling Enter/Exit directly.
36
 **/
37
class ReentrantMonitor : BlockingResourceBase
38
{
39
public:
40
  /**
41
   * ReentrantMonitor
42
   * @param aName A name which can reference this monitor
43
   */
44
  explicit ReentrantMonitor(const char* aName,
45
                            recordreplay::Behavior aRecorded = recordreplay::Behavior::Preserve)
46
    : BlockingResourceBase(aName, eReentrantMonitor)
47
#ifdef DEBUG
48
    , mEntryCount(0)
49
#endif
50
17
  {
51
17
    MOZ_COUNT_CTOR(ReentrantMonitor);
52
17
    if (aRecorded == recordreplay::Behavior::Preserve) {
53
17
      mReentrantMonitor = PR_NewMonitor();
54
17
    } else {
55
0
      recordreplay::AutoPassThroughThreadEvents pt;
56
0
      mReentrantMonitor = PR_NewMonitor();
57
0
    }
58
17
    if (!mReentrantMonitor) {
59
0
      MOZ_CRASH("Can't allocate mozilla::ReentrantMonitor");
60
0
    }
61
17
  }
62
63
  /**
64
   * ~ReentrantMonitor
65
   **/
66
  ~ReentrantMonitor()
67
13
  {
68
13
    NS_ASSERTION(mReentrantMonitor,
69
13
                 "improperly constructed ReentrantMonitor or double free");
70
13
    PR_DestroyMonitor(mReentrantMonitor);
71
13
    mReentrantMonitor = 0;
72
13
    MOZ_COUNT_DTOR(ReentrantMonitor);
73
13
  }
74
75
#ifndef DEBUG
76
  /**
77
   * Enter
78
   * @see prmon.h
79
   **/
80
30
  void Enter() { PR_EnterMonitor(mReentrantMonitor); }
81
82
  /**
83
   * Exit
84
   * @see prmon.h
85
   **/
86
30
  void Exit() { PR_ExitMonitor(mReentrantMonitor); }
87
88
  /**
89
   * Wait
90
   * @see prmon.h
91
   **/
92
  nsresult Wait(PRIntervalTime aInterval = PR_INTERVAL_NO_TIMEOUT)
93
13
  {
94
13
#ifdef MOZILLA_INTERNAL_API
95
13
    AUTO_PROFILER_THREAD_SLEEP;
96
13
#endif //MOZILLA_INTERNAL_API
97
13
    return PR_Wait(mReentrantMonitor, aInterval) == PR_SUCCESS ?
98
13
      NS_OK : NS_ERROR_FAILURE;
99
13
  }
100
101
#else // ifndef DEBUG
102
  void Enter();
103
  void Exit();
104
  nsresult Wait(PRIntervalTime aInterval = PR_INTERVAL_NO_TIMEOUT);
105
106
#endif  // ifndef DEBUG
107
108
  /**
109
   * Notify
110
   * @see prmon.h
111
   **/
112
  nsresult Notify()
113
13
  {
114
13
    return PR_Notify(mReentrantMonitor) == PR_SUCCESS ? NS_OK :
115
13
                                                        NS_ERROR_FAILURE;
116
13
  }
117
118
  /**
119
   * NotifyAll
120
   * @see prmon.h
121
   **/
122
  nsresult NotifyAll()
123
0
  {
124
0
    return PR_NotifyAll(mReentrantMonitor) == PR_SUCCESS ? NS_OK :
125
0
                                                           NS_ERROR_FAILURE;
126
0
  }
127
128
#ifdef DEBUG
129
  /**
130
   * AssertCurrentThreadIn
131
   * @see prmon.h
132
   **/
133
  void AssertCurrentThreadIn()
134
  {
135
    PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mReentrantMonitor);
136
  }
137
138
  /**
139
   * AssertNotCurrentThreadIn
140
   * @see prmon.h
141
   **/
142
  void AssertNotCurrentThreadIn()
143
  {
144
    // FIXME bug 476536
145
  }
146
147
#else
148
0
  void AssertCurrentThreadIn() {}
149
0
  void AssertNotCurrentThreadIn() {}
150
151
#endif  // ifdef DEBUG
152
153
private:
154
  ReentrantMonitor();
155
  ReentrantMonitor(const ReentrantMonitor&);
156
  ReentrantMonitor& operator=(const ReentrantMonitor&);
157
158
  PRMonitor* mReentrantMonitor;
159
#ifdef DEBUG
160
  int32_t mEntryCount;
161
#endif
162
};
163
164
165
/**
166
 * ReentrantMonitorAutoEnter
167
 * Enters the ReentrantMonitor when it enters scope, and exits it when
168
 * it leaves scope.
169
 *
170
 * MUCH PREFERRED to bare calls to ReentrantMonitor.Enter and Exit.
171
 */
172
class MOZ_STACK_CLASS ReentrantMonitorAutoEnter
173
{
174
public:
175
  /**
176
   * Constructor
177
   * The constructor aquires the given lock.  The destructor
178
   * releases the lock.
179
   *
180
   * @param aReentrantMonitor A valid mozilla::ReentrantMonitor*.
181
   **/
182
  explicit ReentrantMonitorAutoEnter(mozilla::ReentrantMonitor& aReentrantMonitor)
183
    : mReentrantMonitor(&aReentrantMonitor)
184
30
  {
185
30
    NS_ASSERTION(mReentrantMonitor, "null monitor");
186
30
    mReentrantMonitor->Enter();
187
30
  }
188
189
  ~ReentrantMonitorAutoEnter(void)
190
30
  {
191
30
    mReentrantMonitor->Exit();
192
30
  }
193
194
  nsresult Wait(PRIntervalTime aInterval = PR_INTERVAL_NO_TIMEOUT)
195
13
  {
196
13
    return mReentrantMonitor->Wait(aInterval);
197
13
  }
198
199
13
  nsresult Notify() { return mReentrantMonitor->Notify(); }
200
0
  nsresult NotifyAll() { return mReentrantMonitor->NotifyAll(); }
201
202
private:
203
  ReentrantMonitorAutoEnter();
204
  ReentrantMonitorAutoEnter(const ReentrantMonitorAutoEnter&);
205
  ReentrantMonitorAutoEnter& operator=(const ReentrantMonitorAutoEnter&);
206
  static void* operator new(size_t) CPP_THROW_NEW;
207
208
  friend class ReentrantMonitorAutoExit;
209
210
  mozilla::ReentrantMonitor* mReentrantMonitor;
211
};
212
213
/**
214
 * ReentrantMonitorAutoExit
215
 * Exit the ReentrantMonitor when it enters scope, and enters it when it leaves
216
 * scope.
217
 *
218
 * MUCH PREFERRED to bare calls to ReentrantMonitor.Exit and Enter.
219
 */
220
class MOZ_STACK_CLASS ReentrantMonitorAutoExit
221
{
222
public:
223
  /**
224
   * Constructor
225
   * The constructor releases the given lock.  The destructor
226
   * acquires the lock. The lock must be held before constructing
227
   * this object!
228
   *
229
   * @param aReentrantMonitor A valid mozilla::ReentrantMonitor*. It
230
   *                 must be already locked.
231
   **/
232
  explicit ReentrantMonitorAutoExit(ReentrantMonitor& aReentrantMonitor)
233
    : mReentrantMonitor(&aReentrantMonitor)
234
0
  {
235
0
    NS_ASSERTION(mReentrantMonitor, "null monitor");
236
0
    mReentrantMonitor->AssertCurrentThreadIn();
237
0
    mReentrantMonitor->Exit();
238
0
  }
239
240
  explicit ReentrantMonitorAutoExit(
241
    ReentrantMonitorAutoEnter& aReentrantMonitorAutoEnter)
242
    : mReentrantMonitor(aReentrantMonitorAutoEnter.mReentrantMonitor)
243
0
  {
244
0
    NS_ASSERTION(mReentrantMonitor, "null monitor");
245
0
    mReentrantMonitor->AssertCurrentThreadIn();
246
0
    mReentrantMonitor->Exit();
247
0
  }
248
249
  ~ReentrantMonitorAutoExit(void)
250
0
  {
251
0
    mReentrantMonitor->Enter();
252
0
  }
253
254
private:
255
  ReentrantMonitorAutoExit();
256
  ReentrantMonitorAutoExit(const ReentrantMonitorAutoExit&);
257
  ReentrantMonitorAutoExit& operator=(const ReentrantMonitorAutoExit&);
258
  static void* operator new(size_t) CPP_THROW_NEW;
259
260
  ReentrantMonitor* mReentrantMonitor;
261
};
262
263
} // namespace mozilla
264
265
#endif // ifndef mozilla_ReentrantMonitor_h