4 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 #include <dali/public-api/common/dali-common.h>
24 #include <condition_variable>
33 * @brief Class that implements a C++20 counting_semaphore like interface
35 template<std::ptrdiff_t LeastMaxValue = std::numeric_limits<std::ptrdiff_t>::max()>
40 * @brief Returns the internal counter's maximum possible value,
41 * which is greater than or equal to LeastMaxValue.
43 * @return the maximum value of the semaphore
45 static constexpr std::ptrdiff_t Max() noexcept
51 * @brief class constructor
53 * @param[in] desired the desired initial value of the semaphore
55 explicit Semaphore(std::ptrdiff_t desired)
58 if(mCount < 0 || mCount > Max())
60 ThrowInvalidParamException(desired);
65 * @brief Atomically increments the internal counter by the value of update.
67 * Any thread waiting for the counter to be greater than 0 will subsequently
70 * @param[in] update value to increment the semaphore
72 void Release(std::ptrdiff_t update = 1)
74 std::lock_guard<std::mutex> lock(mLock);
75 if(update < 0 || update > Max() - mCount)
77 ThrowInvalidParamException(update);
83 mCondVar.notify_one();
88 * @brief Atomically decrements the internal counter by one if it is greater
89 * than zero; otherwise blocks until it is greater than zero and can
90 * successfully decrement the internal counter.
94 std::unique_lock<std::mutex> lock(mLock);
103 * @brief Tries to atomically decrement the internal counter by one if it is
104 * greater than zero; no blocking occurs regardless.
106 * @return true if it decremented the counter, otherwise false.
110 std::lock_guard<std::mutex> lock(mLock);
121 * @brief Tries to atomically decrement the internal counter by one if it is greater
122 * than zero; otherwise blocks until it is greater than zero can successfully
123 * decrement the internal counter, or the relTime duration has been exceeded.
125 * @param[in] relTime the minimum duration the function must wait for to fail
127 * @return true if it decremented the internal counter, otherwise false
129 template<typename Rep, typename Period>
130 bool TryAcquireFor(const std::chrono::duration<Rep, Period>& relTime)
132 std::unique_lock<std::mutex> lock(mLock);
135 if(mCondVar.wait_for(lock, relTime) == std::cv_status::timeout)
145 * @brief Tries to atomically decrement the internal counter by one if it is greater
146 * than zero; otherwise blocks until it is greater than zero can successfully
147 * decrement the internal counter, or the absTime duration point has been passed.
149 * @param[in] absTime the earliest time the function must wait until in order to fail
151 * @return true if it decremented the internal counter, otherwise false
153 template<typename Clock, typename Duration>
154 bool TryAcquireUntil(const std::chrono::time_point<Clock, Duration>& absTime)
156 std::unique_lock<std::mutex> lock(mLock);
159 if(mCondVar.wait_until(lock, absTime) == std::cv_status::timeout)
169 void ThrowInvalidParamException(std::ptrdiff_t param) const
171 std::stringstream ss("Invalid parameter value ");
173 throw std::invalid_argument(ss.str());
176 std::condition_variable mCondVar;
178 std::ptrdiff_t mCount;