Pigweed
 
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
29template <typename GuardedType,
30 typename LockType = pw::sync::VirtualBasicLockable>
32 public:
35 if (lock_ != nullptr) {
36 lock_->unlock();
37 }
38 }
39
50 template <typename G, typename L>
52 : lock_(other.lock_), object_(other.object_) {
53 static_assert(
54 std::is_assignable_v<GuardedType*&, G*>,
55 "Attempted to construct a BorrowedPointer from another whose "
56 "GuardedType* is not assignable to this object's GuardedType*.");
57 static_assert(std::is_assignable_v<LockType*&, L*>,
58 "Attempted to construct a BorrowedPointer from another whose "
59 "LockType* is not assignable to this object's Lock*.");
60 other.lock_ = nullptr;
61 other.object_ = nullptr;
62 }
63
74 template <typename G, typename L>
76 static_assert(
77 std::is_assignable_v<GuardedType*&, G*>,
78 "Attempted to construct a BorrowedPointer from another whose "
79 "GuardedType* is not assignable to this object's GuardedType*.");
80 static_assert(std::is_assignable_v<LockType*&, L*>,
81 "Attempted to construct a BorrowedPointer from another whose "
82 "LockType* is not assignable to this object's Lock*.");
83 lock_ = other.lock_;
84 object_ = other.object_;
85 other.lock_ = nullptr;
86 other.object_ = nullptr;
87 return *this;
88 }
89 BorrowedPointer(const BorrowedPointer&) = delete;
91
93 GuardedType* operator->() {
94 PW_ASSERT(object_ != nullptr); // Ensure this isn't a stale moved instance.
95 return object_;
96 }
97
99 const GuardedType* operator->() const {
100 PW_ASSERT(object_ != nullptr); // Ensure this isn't a stale moved instance.
101 return object_;
102 }
103
115 GuardedType& operator*() {
116 PW_ASSERT(object_ != nullptr); // Ensure this isn't a stale moved instance.
117 return *object_;
118 }
119
121 const GuardedType& operator*() const {
122 PW_ASSERT(object_ != nullptr); // Ensure this isn't a stale moved instance.
123 return *object_;
124 }
125
126 private:
128 template <typename, typename>
129 friend class Borrowable;
130
131 constexpr BorrowedPointer(LockType& lock, GuardedType& object)
132 : lock_(&lock), object_(&object) {}
133
134 LockType* lock_;
135 GuardedType* object_;
136
139 template <typename, typename>
140 friend class BorrowedPointer;
141};
142
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
183 PW_NO_LOCK_SAFETY_ANALYSIS {
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
194 PW_NO_LOCK_SAFETY_ANALYSIS {
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
217} // 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:31
BorrowedPointer(BorrowedPointer< G, L > &&other)
Definition: borrow.h:51
GuardedType * operator->()
Provides access to the borrowed object's members.
Definition: borrow.h:93
BorrowedPointer & operator=(BorrowedPointer< G, L > &&other)
Definition: borrow.h:75
friend class BorrowedPointer
Definition: borrow.h:140
GuardedType & operator*()
Definition: borrow.h:115
const GuardedType & operator*() const
Const overload.
Definition: borrow.h:121
const GuardedType * operator->() const
Const overload.
Definition: borrow.h:99
~BorrowedPointer()
Release the lock on destruction.
Definition: borrow.h:34
Definition: timed_borrow.h:32
Definition: virtual_basic_lockable.h:29