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