// Copyright 2023 gRPC authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef GRPC_SRC_CORE_LIB_PROMISE_PROMISE_MUTEX_H #define GRPC_SRC_CORE_LIB_PROMISE_PROMISE_MUTEX_H #include #include #include #include "src/core/lib/promise/activity.h" #include "src/core/lib/promise/poll.h" namespace grpc_core { // A mutex that can be used to synchronize access to a value within one // activity. template class PromiseMutex { public: class Lock { public: Lock() {} ~Lock() { if (mutex_ != nullptr) { GPR_ASSERT(mutex_->locked_); mutex_->locked_ = false; mutex_->waiter_.Wake(); } } Lock(Lock&& other) noexcept : mutex_(std::exchange(other.mutex_, nullptr)) {} Lock& operator=(Lock&& other) noexcept { std::swap(mutex_, other.mutex_); return *this; } Lock(const Lock&) = delete; Lock& operator=(const Lock&) noexcept = delete; T* operator->() { GPR_DEBUG_ASSERT(mutex_ != nullptr); return &mutex_->value_; } T& operator*() { GPR_DEBUG_ASSERT(mutex_ != nullptr); return mutex_->value_; } private: friend class PromiseMutex; explicit Lock(PromiseMutex* mutex) : mutex_(mutex) { GPR_DEBUG_ASSERT(!mutex_->locked_); mutex_->locked_ = true; } PromiseMutex* mutex_ = nullptr; }; PromiseMutex() = default; explicit PromiseMutex(T value) : value_(std::move(value)) {} ~PromiseMutex() { GPR_DEBUG_ASSERT(!locked_); } auto Acquire() { return [this]() -> Poll { if (locked_) return waiter_.pending(); return Lock(this); }; } private: bool locked_ = false; IntraActivityWaiter waiter_; GPR_NO_UNIQUE_ADDRESS T value_; }; } // namespace grpc_core #endif // GRPC_SRC_CORE_LIB_PROMISE_PROMISE_MUTEX_H