C/C++ API Reference
Loading...
Searching...
No Matches
borrow.h
1// Copyright 2021 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://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, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14#pragma once
15
16#include <optional>
17#include <type_traits>
18
19#include "pw_assert/assert.h"
20#include "pw_sync/lock_annotations.h"
21#include "pw_sync/lock_traits.h"
22#include "pw_sync/virtual_basic_lockable.h"
23
24namespace pw::sync {
25
27
31template <typename GuardedType,
32 typename LockType = pw::sync::VirtualBasicLockable>
34 public:
37 if (lock_ != nullptr) {
38 lock_->unlock();
39 }
40 }
41
52 template <typename G, typename L>
54 : lock_(other.lock_), object_(other.object_) {
55 static_assert(
56 std::is_assignable_v<GuardedType*&, G*>,
57 "Attempted to construct a BorrowedPointer from another whose "
58 "GuardedType* is not assignable to this object's GuardedType*.");
59 static_assert(std::is_assignable_v<LockType*&, L*>,
60 "Attempted to construct a BorrowedPointer from another whose "
61 "LockType* is not assignable to this object's Lock*.");
62 other.lock_ = nullptr;
63 other.object_ = nullptr;
64 }
65
76 template <typename G, typename L>
78 static_assert(
79 std::is_assignable_v<GuardedType*&, G*>,
80 "Attempted to construct a BorrowedPointer from another whose "
81 "GuardedType* is not assignable to this object's GuardedType*.");
82 static_assert(std::is_assignable_v<LockType*&, L*>,
83 "Attempted to construct a BorrowedPointer from another whose "
84 "LockType* is not assignable to this object's Lock*.");
85 lock_ = other.lock_;
86 object_ = other.object_;
87 other.lock_ = nullptr;
88 other.object_ = nullptr;
89 return *this;
90 }
91 BorrowedPointer(const BorrowedPointer&) = delete;
93
95 GuardedType* operator->() {
96 PW_ASSERT(object_ != nullptr); // Ensure this isn't a stale moved instance.
97 return object_;
98 }
99
101 const GuardedType* operator->() const {
102 PW_ASSERT(object_ != nullptr); // Ensure this isn't a stale moved instance.
103 return object_;
104 }
105
113 GuardedType& operator*() {
114 PW_ASSERT(object_ != nullptr); // Ensure this isn't a stale moved instance.
115 return *object_;
116 }
117
119 const GuardedType& operator*() const {
120 PW_ASSERT(object_ != nullptr); // Ensure this isn't a stale moved instance.
121 return *object_;
122 }
123
124 private:
126 template <typename, typename>
127 friend class Borrowable;
128
129 constexpr BorrowedPointer(LockType& lock, GuardedType& object)
130 : lock_(&lock), object_(&object) {}
131
132 LockType* lock_;
133 GuardedType* object_;
134
137 template <typename, typename>
138 friend class BorrowedPointer;
139};
140
141// clang-format off
161// clang-format on
162template <typename GuardedType,
163 typename LockType = pw::sync::VirtualBasicLockable>
165 public:
166 static_assert(is_basic_lockable_v<LockType>,
167 "lock type must satisfy BasicLockable");
168
169 constexpr Borrowable(GuardedType& object, LockType& lock) noexcept
170 : lock_(&lock), object_(&object) {}
171
172 template <typename U>
173 constexpr Borrowable(const Borrowable<U, LockType>& other)
174 : lock_(other.lock_), object_(other.object_) {}
175
176 Borrowable(const Borrowable&) = default;
177 Borrowable& operator=(const Borrowable&) = default;
178 Borrowable(Borrowable&& other) = default;
179 Borrowable& operator=(Borrowable&& other) = default;
180
184 lock_->lock();
185 return Borrow();
186 }
187
190 template <int&... ExplicitArgumentBarrier,
191 typename T = LockType,
192 typename = std::enable_if_t<is_lockable_v<T>>>
193 std::optional<BorrowedPointer<GuardedType, LockType>> try_acquire() const
195 if (!lock_->try_lock()) {
196 return std::nullopt;
197 }
198 return Borrow();
199 }
200
201 private:
202 // Befriend all template instantiations of this class and the Timed subtype.
203 template <typename, typename>
204 friend class Borrowable;
205
206 template <typename, typename>
207 friend class TimedBorrowable;
208
210 return BorrowedPointer<GuardedType, LockType>(*lock_, *object_);
211 }
212
213 LockType* lock_;
214 GuardedType* object_;
215};
216
218
219} // namespace pw::sync
Definition: borrow.h:164
std::optional< BorrowedPointer< GuardedType, LockType > > try_acquire() const
Definition: borrow.h:193
BorrowedPointer< GuardedType, LockType > acquire() const
Blocks indefinitely until the object can be borrowed. Failures are fatal.
Definition: borrow.h:182
Definition: borrow.h:33
BorrowedPointer(BorrowedPointer< G, L > &&other)
Definition: borrow.h:53
GuardedType * operator->()
Provides access to the borrowed object's members.
Definition: borrow.h:95
BorrowedPointer & operator=(BorrowedPointer< G, L > &&other)
Definition: borrow.h:77
friend class BorrowedPointer
Definition: borrow.h:138
GuardedType & operator*()
Definition: borrow.h:113
const GuardedType & operator*() const
Const overload.
Definition: borrow.h:119
const GuardedType * operator->() const
Const overload.
Definition: borrow.h:101
~BorrowedPointer()
Release the lock on destruction.
Definition: borrow.h:36
Definition: timed_borrow.h:34
Definition: virtual_basic_lockable.h:31
#define PW_NO_LOCK_SAFETY_ANALYSIS
Definition: lock_annotations.h:292
Definition: binary_semaphore.h:26