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