1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #ifndef _THRIFT_CONCURRENCY_MONITOR_H_
21 #define _THRIFT_CONCURRENCY_MONITOR_H_ 1
22 
23 #include <chrono>
24 #include <thrift/concurrency/Exception.h>
25 #include <thrift/concurrency/Mutex.h>
26 #include <thrift/TNonCopyable.h>
27 
28 namespace apache {
29 namespace thrift {
30 namespace concurrency {
31 
32 /**
33  * A monitor is a combination mutex and condition-event.  Waiting and
34  * notifying condition events requires that the caller own the mutex.  Mutex
35  * lock and unlock operations can be performed independently of condition
36  * events.  This is more or less analogous to java.lang.Object multi-thread
37  * operations.
38  *
39  * Note the Monitor can create a new, internal mutex; alternatively, a
40  * separate Mutex can be passed in and the Monitor will re-use it without
41  * taking ownership.  It's the user's responsibility to make sure that the
42  * Mutex is not deallocated before the Monitor.
43  *
44  * Note that all methods are const.  Monitors implement logical constness, not
45  * bit constness.  This allows const methods to call monitor methods without
46  * needing to cast away constness or change to non-const signatures.
47  *
48  * @version $Id:$
49  */
50 class Monitor : apache::thrift::TNonCopyable {
51 public:
52   /** Creates a new mutex, and takes ownership of it. */
53   Monitor();
54 
55   /** Uses the provided mutex without taking ownership. */
56   explicit Monitor(Mutex* mutex);
57 
58   /** Uses the mutex inside the provided Monitor without taking ownership. */
59   explicit Monitor(Monitor* monitor);
60 
61   /** Deallocates the mutex only if we own it. */
62   virtual ~Monitor();
63 
64   Mutex& mutex() const;
65 
66   virtual void lock() const;
67 
68   virtual void unlock() const;
69 
70   /**
71    * Waits a maximum of the specified timeout in milliseconds for the condition
72    * to occur, or waits forever if timeout is zero.
73    *
74    * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code.
75    */
76   int waitForTimeRelative(const std::chrono::milliseconds &timeout) const;
77 
waitForTimeRelative(uint64_t timeout_ms)78   int waitForTimeRelative(uint64_t timeout_ms) const { return waitForTimeRelative(std::chrono::milliseconds(timeout_ms)); }
79 
80   /**
81    * Waits until the absolute time specified by abstime.
82    * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code.
83    */
84   int waitForTime(const std::chrono::time_point<std::chrono::steady_clock>& abstime) const;
85 
86   /**
87    * Waits forever until the condition occurs.
88    * Returns 0 if condition occurs, or an error code otherwise.
89    */
90   int waitForever() const;
91 
92   /**
93    * Exception-throwing version of waitForTimeRelative(), called simply
94    * wait(std::chrono::milliseconds) for historical reasons.  Timeout is in milliseconds.
95    *
96    * If the condition occurs, this function returns cleanly; on timeout or
97    * error an exception is thrown.
98    */
99   void wait(const std::chrono::milliseconds &timeout) const;
100 
101   void wait(uint64_t timeout_ms = 0ULL) const { this->wait(std::chrono::milliseconds(timeout_ms)); }
102 
103   /** Wakes up one thread waiting on this monitor. */
104   virtual void notify() const;
105 
106   /** Wakes up all waiting threads on this monitor. */
107   virtual void notifyAll() const;
108 
109 private:
110   class Impl;
111 
112   Impl* impl_;
113 };
114 
115 class Synchronized {
116 public:
Synchronized(const Monitor * monitor)117   Synchronized(const Monitor* monitor) : g(monitor->mutex()) {}
Synchronized(const Monitor & monitor)118   Synchronized(const Monitor& monitor) : g(monitor.mutex()) {}
119 
120 private:
121   Guard g;
122 };
123 }
124 }
125 } // apache::thrift::concurrency
126 
127 #endif // #ifndef _THRIFT_CONCURRENCY_MONITOR_H_
128