pw_sync/borrow: Do not use a reference type for Borrowable
Changes the Borrowable templatization to use the GuardedType instead
of the GuardedReference to be consistent with the STL approach for
types such as std::shared_ptr, etc.
Change-Id: I021ec6cfe6a7c67d788e13376cb9f0c1aaf57146
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/61901
Reviewed-by: David Palchak <palchak@google.com>
Reviewed-by: Wyatt Hepler <hepler@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
Pigweed-Auto-Submit: Ewout van Bekkum <ewout@google.com>
diff --git a/pw_sync/borrow_test.cc b/pw_sync/borrow_test.cc
index adec2af..5ab536f 100644
--- a/pw_sync/borrow_test.cc
+++ b/pw_sync/borrow_test.cc
@@ -41,7 +41,7 @@
};
Lock lock_;
Foo foo_;
- Borrowable<Foo&, Lock> borrowable_foo_;
+ Borrowable<Foo, Lock> borrowable_foo_;
};
class BasicLockable : public VirtualBasicLockable {
@@ -103,7 +103,7 @@
}
TEST_F(BorrowableBasicLockableTest, Moveable) {
- Borrowable<Foo&, BasicLockable> borrowable_foo = std::move(borrowable_foo_);
+ Borrowable<Foo, BasicLockable> borrowable_foo = std::move(borrowable_foo_);
{
BorrowedPointer<Foo, BasicLockable> borrowed_foo = borrowable_foo.acquire();
EXPECT_TRUE(lock_.locked()); // Ensure the lock is held.
@@ -114,8 +114,8 @@
}
TEST_F(BorrowableBasicLockableTest, Copyable) {
- const Borrowable<Foo&, BasicLockable>& other = borrowable_foo_;
- Borrowable<Foo&, BasicLockable> borrowable_foo(other);
+ const Borrowable<Foo, BasicLockable>& other = borrowable_foo_;
+ Borrowable<Foo, BasicLockable> borrowable_foo(other);
{
BorrowedPointer<Foo, BasicLockable> borrowed_foo = borrowable_foo.acquire();
EXPECT_TRUE(lock_.locked()); // Ensure the lock is held.
diff --git a/pw_sync/docs.rst b/pw_sync/docs.rst
index fd2bef8..31e6827 100644
--- a/pw_sync/docs.rst
+++ b/pw_sync/docs.rst
@@ -1093,7 +1093,7 @@
pw::sync::Mutex bobs_account_mutex;
BankAccount bobs_account PW_GUARDED_BY(bobs_account_mutex);
- pw::sync::Borrowable<BankAccount&, pw::sync::Mutex> bobs_acount(
+ pw::sync::Borrowable<BankAccount, pw::sync::Mutex> bobs_acount(
bobs_account_mutex, bobs_account);
This construct is useful when sharing objects or data which are transactional in
@@ -1133,7 +1133,7 @@
**Warning:** Be careful not to leak references to the borrowed object.
-.. cpp:class:: template <typename GuardedReference, typename Lock = pw::sync::VirtualBasicLockable> pw::sync::Borrowable
+.. cpp:class:: template <typename GuardedType, typename Lock = pw::sync::VirtualBasicLockable> pw::sync::Borrowable
.. cpp:function:: BorrowedPointer<GuardedType, Lock> acquire()
@@ -1174,7 +1174,7 @@
pw::sync::VirtualMutex i2c_mutex;
ExampleI2c i2c;
- pw::sync::Borrowable<ExampleI2c&> borrowable_i2c(i2c_mutex, i2c);
+ pw::sync::Borrowable<ExampleI2c> borrowable_i2c(i2c_mutex, i2c);
pw::Result<ConstByteSpan> ReadI2cData(ByteSpan buffer) {
// Block indefinitely waiting to borrow the i2c bus.
diff --git a/pw_sync/public/pw_sync/borrow.h b/pw_sync/public/pw_sync/borrow.h
index 038df5f..e6d2d90 100644
--- a/pw_sync/public/pw_sync/borrow.h
+++ b/pw_sync/public/pw_sync/borrow.h
@@ -87,16 +87,10 @@
//
// This class is compatible with locks which comply with BasicLockable,
// Lockable, and TimedLockable C++ named requirements.
-template <typename GuardedReference,
- typename Lock = pw::sync::VirtualBasicLockable>
+template <typename GuardedType, typename Lock = pw::sync::VirtualBasicLockable>
class Borrowable {
public:
- static_assert(std::is_reference<GuardedReference>::value,
- "GuardedReference must be a reference type");
-
- using guarded_type = typename std::remove_reference<GuardedReference>::type;
-
- constexpr Borrowable(Lock& lock, GuardedReference object)
+ constexpr Borrowable(Lock& lock, GuardedType& object)
: lock_(&lock), object_(&object) {}
Borrowable(const Borrowable&) = default;
@@ -105,50 +99,50 @@
Borrowable& operator=(Borrowable&& other) = default;
// Blocks indefinitely until the object can be borrowed. Failures are fatal.
- BorrowedPointer<guarded_type, Lock> acquire() {
+ BorrowedPointer<GuardedType, Lock> acquire() {
std::unique_lock unique_lock(*lock_);
- return BorrowedPointer<guarded_type, Lock>(std::move(unique_lock), object_);
+ return BorrowedPointer<GuardedType, Lock>(std::move(unique_lock), object_);
}
// Tries to borrow the object in a non-blocking manner. Returns a
// BorrowedPointer on success, otherwise std::nullopt (nothing).
- std::optional<BorrowedPointer<guarded_type, Lock>> try_acquire() {
+ std::optional<BorrowedPointer<GuardedType, Lock>> try_acquire() {
std::unique_lock unique_lock(*lock_, std::defer_lock);
if (!unique_lock.try_lock()) {
return std::nullopt;
}
- return BorrowedPointer<guarded_type, Lock>(std::move(unique_lock), object_);
+ return BorrowedPointer<GuardedType, Lock>(std::move(unique_lock), object_);
}
// Tries to borrow the object. Blocks until the specified timeout has elapsed
// or the object has been borrowed, whichever comes first. Returns a
// BorrowedPointer on success, otherwise std::nullopt (nothing).
template <class Rep, class Period>
- std::optional<BorrowedPointer<guarded_type, Lock>> try_acquire_for(
+ std::optional<BorrowedPointer<GuardedType, Lock>> try_acquire_for(
std::chrono::duration<Rep, Period> timeout) {
std::unique_lock unique_lock(*lock_, std::defer_lock);
if (!unique_lock.try_lock_for(timeout)) {
return std::nullopt;
}
- return BorrowedPointer<guarded_type, Lock>(std::move(unique_lock), object_);
+ return BorrowedPointer<GuardedType, Lock>(std::move(unique_lock), object_);
}
// Tries to borrow the object. Blocks until the specified deadline has passed
// or the object has been borrowed, whichever comes first. Returns a
// BorrowedPointer on success, otherwise std::nullopt (nothing).
template <class Clock, class Duration>
- std::optional<BorrowedPointer<guarded_type, Lock>> try_acquire_until(
+ std::optional<BorrowedPointer<GuardedType, Lock>> try_acquire_until(
std::chrono::time_point<Clock, Duration> deadline) {
std::unique_lock unique_lock(*lock_, std::defer_lock);
if (!unique_lock.try_lock_until(deadline)) {
return std::nullopt;
}
- return BorrowedPointer<guarded_type, Lock>(std::move(unique_lock), object_);
+ return BorrowedPointer<GuardedType, Lock>(std::move(unique_lock), object_);
}
private:
Lock* lock_;
- guarded_type* object_;
+ GuardedType* object_;
};
} // namespace pw::sync