summaryrefslogtreecommitdiff
path: root/xpcom/glue/CondVar.h
blob: 5d05464ecad3de50ea95b6737e78c22c61a14403 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_CondVar_h
#define mozilla_CondVar_h

#include "prcvar.h"

#include "mozilla/BlockingResourceBase.h"
#include "mozilla/Mutex.h"

#ifdef MOZILLA_INTERNAL_API
#include "GeckoProfiler.h"
#endif //MOZILLA_INTERNAL_API

namespace mozilla {


/**
 * CondVar
 * Vanilla condition variable.  Please don't use this unless you have a
 * compelling reason --- Monitor provides a simpler API.
 */
class CondVar : BlockingResourceBase
{
public:
  /**
   * CondVar
   *
   * The CALLER owns |aLock|.
   *
   * @param aLock A Mutex to associate with this condition variable.
   * @param aName A name which can reference this monitor
   * @returns If failure, nullptr.
   *          If success, a valid Monitor* which must be destroyed
   *          by Monitor::DestroyMonitor()
   **/
  CondVar(Mutex& aLock, const char* aName)
    : BlockingResourceBase(aName, eCondVar)
    , mLock(&aLock)
  {
    MOZ_COUNT_CTOR(CondVar);
    // |aLock| must necessarily already be known to the deadlock detector
    mCvar = PR_NewCondVar(mLock->mLock);
    if (!mCvar) {
      NS_RUNTIMEABORT("Can't allocate mozilla::CondVar");
    }
  }

  /**
   * ~CondVar
   * Clean up after this CondVar, but NOT its associated Mutex.
   **/
  ~CondVar()
  {
    NS_ASSERTION(mCvar && mLock,
                 "improperly constructed CondVar or double free");
    PR_DestroyCondVar(mCvar);
    mCvar = 0;
    mLock = 0;
    MOZ_COUNT_DTOR(CondVar);
  }

#ifndef DEBUG
  /**
   * Wait
   * @see prcvar.h
   **/
  nsresult Wait(PRIntervalTime aInterval = PR_INTERVAL_NO_TIMEOUT)
  {

#ifdef MOZILLA_INTERNAL_API
    GeckoProfilerSleepRAII profiler_sleep;
#endif //MOZILLA_INTERNAL_API
    // NSPR checks for lock ownership
    return PR_WaitCondVar(mCvar, aInterval) == PR_SUCCESS ? NS_OK :
                                                            NS_ERROR_FAILURE;
  }
#else
  nsresult Wait(PRIntervalTime aInterval = PR_INTERVAL_NO_TIMEOUT);
#endif // ifndef DEBUG

  /**
   * Notify
   * @see prcvar.h
   **/
  nsresult Notify()
  {
    // NSPR checks for lock ownership
    return PR_NotifyCondVar(mCvar) == PR_SUCCESS ? NS_OK : NS_ERROR_FAILURE;
  }

  /**
   * NotifyAll
   * @see prcvar.h
   **/
  nsresult NotifyAll()
  {
    // NSPR checks for lock ownership
    return PR_NotifyAllCondVar(mCvar) == PR_SUCCESS ? NS_OK : NS_ERROR_FAILURE;
  }

#ifdef DEBUG
  /**
   * AssertCurrentThreadOwnsMutex
   * @see Mutex::AssertCurrentThreadOwns
   **/
  void AssertCurrentThreadOwnsMutex()
  {
    mLock->AssertCurrentThreadOwns();
  }

  /**
   * AssertNotCurrentThreadOwnsMutex
   * @see Mutex::AssertNotCurrentThreadOwns
   **/
  void AssertNotCurrentThreadOwnsMutex()
  {
    mLock->AssertNotCurrentThreadOwns();
  }

#else
  void AssertCurrentThreadOwnsMutex() {}
  void AssertNotCurrentThreadOwnsMutex() {}

#endif  // ifdef DEBUG

private:
  CondVar();
  CondVar(CondVar&);
  CondVar& operator=(CondVar&);

  Mutex* mLock;
  PRCondVar* mCvar;
};


} // namespace mozilla


#endif  // ifndef mozilla_CondVar_h