diff options
Diffstat (limited to 'src/core/lib/promise/promise_mutex.h')
-rw-r--r-- | src/core/lib/promise/promise_mutex.h | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/src/core/lib/promise/promise_mutex.h b/src/core/lib/promise/promise_mutex.h new file mode 100644 index 0000000000..80129eeb99 --- /dev/null +++ b/src/core/lib/promise/promise_mutex.h @@ -0,0 +1,92 @@ +// 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 <grpc/support/port_platform.h> + +#include <utility> + +#include <grpc/support/log.h> + +#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 <typename T> +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<Lock> { + 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 |