xref: /aosp_15_r20/external/pigweed/pw_sync/public/pw_sync/internal/borrowable_storage.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2022 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 <tuple>
17 
18 namespace pw::sync::internal {
19 
20 // BorrowableStorage stores an object and associated lock. Both objects are
21 // constructed in-place.
22 template <typename ObjectType, typename Lock>
23 class BorrowableStorage {
24  protected:
25   // Construct the object in-place using a list of arguments.
26   template <typename... Args>
BorrowableStorage(std::in_place_t,Args &&...args)27   constexpr explicit BorrowableStorage(std::in_place_t, Args&&... args)
28       : object_{std::forward<Args>(args)...}, lock_{} {}
29 
30   // Construct the object and lock in-place using the provided parameters.
31   template <typename... ObjectArgs, typename... LockArgs>
BorrowableStorage(std::tuple<ObjectArgs...> && object_args,std::tuple<LockArgs...> && lock_args)32   constexpr BorrowableStorage(std::tuple<ObjectArgs...>&& object_args,
33                               std::tuple<LockArgs...>&& lock_args)
34       : object_{std::make_from_tuple<ObjectType>(
35             std::forward<std::tuple<ObjectArgs...>>(object_args))},
36         lock_{std::make_from_tuple<Lock>(
37             std::forward<std::tuple<LockArgs...>>(lock_args))} {}
38 
39   // Construct the object and lock in-place using the provided factories.
40   template <typename ObjectConstructor,
41             typename LockConstructor,
42             typename = std::enable_if_t<
43                 std::is_invocable_r_v<ObjectType&&, ObjectConstructor>>,
44             typename = std::enable_if_t<
45                 std::is_invocable_r_v<Lock&&, LockConstructor>>>
BorrowableStorage(const ObjectConstructor & object_ctor,const LockConstructor & lock_ctor)46   constexpr BorrowableStorage(const ObjectConstructor& object_ctor,
47                               const LockConstructor& lock_ctor)
48       : object_{object_ctor()}, lock_{lock_ctor()} {}
49 
50   template <typename ObjectConstructor,
51             typename LockConstructor,
52             typename = std::enable_if_t<
53                 std::is_invocable_r_v<ObjectType&&, ObjectConstructor>>,
54             typename = std::enable_if_t<
55                 std::is_invocable_r_v<Lock&&, LockConstructor>>>
BorrowableStorage(ObjectConstructor & object_ctor,const LockConstructor & lock_ctor)56   constexpr BorrowableStorage(ObjectConstructor& object_ctor,
57                               const LockConstructor& lock_ctor)
58       : object_{object_ctor()}, lock_{lock_ctor()} {}
59 
60   template <typename ObjectConstructor,
61             typename LockConstructor,
62             typename = std::enable_if_t<
63                 std::is_invocable_r_v<ObjectType&&, ObjectConstructor>>,
64             typename = std::enable_if_t<
65                 std::is_invocable_r_v<Lock&&, LockConstructor>>>
BorrowableStorage(const ObjectConstructor & object_ctor,LockConstructor & lock_ctor)66   constexpr BorrowableStorage(const ObjectConstructor& object_ctor,
67                               LockConstructor& lock_ctor)
68       : object_{object_ctor()}, lock_{lock_ctor()} {}
69 
70   template <typename ObjectConstructor,
71             typename LockConstructor,
72             typename = std::enable_if_t<
73                 std::is_invocable_r_v<ObjectType&&, ObjectConstructor>>,
74             typename = std::enable_if_t<
75                 std::is_invocable_r_v<Lock&&, LockConstructor>>>
BorrowableStorage(ObjectConstructor & object_ctor,LockConstructor & lock_ctor)76   constexpr BorrowableStorage(ObjectConstructor& object_ctor,
77                               LockConstructor& lock_ctor)
78       : object_{object_ctor()}, lock_{lock_ctor()} {}
79 
80   ObjectType object_;
81   Lock lock_;
82 };
83 
84 template <typename T>
DefaultConstruct()85 T DefaultConstruct() {
86   return T();
87 }
88 
89 }  // namespace pw::sync::internal
90