1 // Copyright 2023 gRPC authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef GRPC_SRC_CORE_LIB_PROMISE_PROMISE_MUTEX_H 16 #define GRPC_SRC_CORE_LIB_PROMISE_PROMISE_MUTEX_H 17 18 #include <grpc/support/port_platform.h> 19 20 #include <utility> 21 22 #include <grpc/support/log.h> 23 24 #include "src/core/lib/promise/activity.h" 25 #include "src/core/lib/promise/poll.h" 26 27 namespace grpc_core { 28 29 // A mutex that can be used to synchronize access to a value within one 30 // activity. 31 template <typename T> 32 class PromiseMutex { 33 public: 34 class Lock { 35 public: Lock()36 Lock() {} ~Lock()37 ~Lock() { 38 if (mutex_ != nullptr) { 39 GPR_ASSERT(mutex_->locked_); 40 mutex_->locked_ = false; 41 mutex_->waiter_.Wake(); 42 } 43 } 44 Lock(Lock && other)45 Lock(Lock&& other) noexcept 46 : mutex_(std::exchange(other.mutex_, nullptr)) {} 47 Lock& operator=(Lock&& other) noexcept { 48 std::swap(mutex_, other.mutex_); 49 return *this; 50 } 51 52 Lock(const Lock&) = delete; 53 Lock& operator=(const Lock&) noexcept = delete; 54 55 T* operator->() { 56 GPR_DEBUG_ASSERT(mutex_ != nullptr); 57 return &mutex_->value_; 58 } 59 T& operator*() { 60 GPR_DEBUG_ASSERT(mutex_ != nullptr); 61 return mutex_->value_; 62 } 63 64 private: 65 friend class PromiseMutex; Lock(PromiseMutex * mutex)66 explicit Lock(PromiseMutex* mutex) : mutex_(mutex) { 67 GPR_DEBUG_ASSERT(!mutex_->locked_); 68 mutex_->locked_ = true; 69 } 70 PromiseMutex* mutex_ = nullptr; 71 }; 72 73 PromiseMutex() = default; PromiseMutex(T value)74 explicit PromiseMutex(T value) : value_(std::move(value)) {} ~PromiseMutex()75 ~PromiseMutex() { GPR_DEBUG_ASSERT(!locked_); } 76 Acquire()77 auto Acquire() { 78 return [this]() -> Poll<Lock> { 79 if (locked_) return waiter_.pending(); 80 return Lock(this); 81 }; 82 } 83 84 private: 85 bool locked_ = false; 86 IntraActivityWaiter waiter_; 87 GPR_NO_UNIQUE_ADDRESS T value_; 88 }; 89 90 } // namespace grpc_core 91 92 #endif // GRPC_SRC_CORE_LIB_PROMISE_PROMISE_MUTEX_H 93