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