farm-ng-core
shared.h
Go to the documentation of this file.
1 // Copyright 2022, farm-ng inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://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,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 
19 
20 #include <memory>
21 
22 namespace farm_ng {
23 
24 // Represents a Non-nullable pointer with shared ownership
25 // Is essentially an adapter between std::shared_ptr and farm_ng::Expected
26 template <class TT>
27 class Shared {
28  public:
30  using BadExpectedAccess = tl::bad_expected_access<farm_ng::Error>;
31 
32  /// Construct from a possibly null shared_ptr
33  /// The return value is an object containing either a non-null Shared object
34  /// pointer,
35  // or an farm_ng::Error object
36  static ExpectedT tryFrom(std::shared_ptr<TT> const& maybe_null) noexcept {
37  if (!maybe_null) {
38  return FARM_UNEXPECTED("is null");
39  }
40  // For some reason, Expected seems to have trouble accepting an r-value
41  // Shared<T> with its deleted copy constructor.
42  Shared<TT> temp(maybe_null);
43  return temp;
44  }
45 
46  /// Construct and also makes interior object T
47  /// The return value is an object containing either a non-null Shared object
48  /// pointer, for the new object, or an farm_ng::Error object if memory
49  /// allocation failst or the constructor for the object throws
50  template <class... TArgs>
51  static ExpectedT tryMake(TArgs&&... args) noexcept {
52  try {
53  // can throw on bad memory allocation and exceptions in constructor of T.
54  return tryFrom(std::make_shared<TT>(std::forward<TArgs>(args)...));
55  } catch (std::exception& e) {
56  return FARM_UNEXPECTED(e.what());
57  }
58  return FARM_UNEXPECTED();
59  }
60 
61  /// Construct from a possibly null shared_ptr
62  /// Panics if shared is null. See `tryFrom()` for alternate.
63  static Shared from(std::shared_ptr<TT> const& shared) {
64  auto maybe = tryFrom(shared);
65  return FARM_UNWRAP(maybe);
66  }
67 
68  /// Construct and also makes interior object T
69  /// Panics if the constructor throws. See `tryFrom()` for alternate.
70  template <class... TArgs>
71  static Shared<TT> make(TArgs&&... args) {
72  auto maybe = tryMake(std::forward<TArgs>(args)...);
73  return FARM_UNWRAP(maybe);
74  }
75 
76  /// Returns the interior object which is guaranteed to be available
77  TT& operator*() { return *non_null_shared_; }
78 
79  /// Returns the interior object which is guaranteed to be available
80  TT const& operator*() const { return *non_null_shared_; }
81 
82  /// Returns the interior object which is guaranteed to be available
83  TT* operator->() { return non_null_shared_.get(); }
84 
85  /// Returns the interior object which is guaranteed to be available
86  TT const* operator->() const { return non_null_shared_.get(); }
87 
88  // Implicit conversion to a nullable std::shared_ptr okay
89  operator std::shared_ptr<TT>() const { return sharedPtr(); }
90 
91  // Return a nullable shared_ptr<T> from this Shared<T> object
92  [[nodiscard]] std::shared_ptr<TT> sharedPtr() const {
93  return non_null_shared_;
94  }
95 
96  // Return the raw point from this Shared<T> object
97  [[nodiscard]] TT const* ptr() const { return sharedPtr().get(); }
98 
99  // Return the raw point from this Shared<T> object
100  TT* ptr() { return sharedPtr().get(); }
101 
102  // Default constructable only if T is
103  Shared() requires(std::is_default_constructible<TT>::value)
104  : non_null_shared_(std::make_shared<TT>()) {
105  checkMaybeThrow();
106  }
107 
108  // Copy constructor from derived bases
109  template <DerivedFrom<TT> TDerived>
110  Shared(Shared<TDerived> const& other) : non_null_shared_(other.sharedPtr()) {
111  checkMaybeThrow();
112  }
113 
114  // Construct from shared_ptr
115  template <DerivedFrom<TT> TDerived>
116  Shared(std::shared_ptr<TDerived> const& panic_if_null)
117  : non_null_shared_(panic_if_null) {
118  checkMaybeThrow();
119  }
120 
121  // Take ownership from unique_ptr
122  template <DerivedFrom<TT> TDerived>
123  Shared(std::unique_ptr<TDerived>&& panic_if_null)
124  : non_null_shared_(std::move(panic_if_null)) {
125  checkMaybeThrow();
126  }
127 
128  // Not sure why this is needed when the generic one
129  // is defined above
130  Shared(std::shared_ptr<TT> const& panic_if_null)
131  : non_null_shared_(panic_if_null) {
132  checkMaybeThrow();
133  }
134 
135  Shared(Shared<TT>&& o) noexcept : non_null_shared_(o.non_null_shared_) {
136  // We mustn't move the internal shared_ptr
137  // because that would break the invariant.
138  }
139 
140  Shared<TT>& operator=(Shared<TT>&& o) noexcept {
141  // We maintain the invariant since
142  // o.non_null_shared_ must also be valid
143  non_null_shared_ = o.non_null_shared_;
144  return *this;
145  }
146 
147  Shared(Shared<TT> const&) = default;
148  Shared<TT>& operator=(Shared<TT> const&) = default;
149 
150  bool operator==(Shared<TT> const& rhs) const noexcept {
151  return this->non_null_shared_ == rhs.non_null_shared_;
152  }
153 
154  private:
155  void checkMaybeThrow() const {
156  if (!non_null_shared_) {
157  throw BadExpectedAccess(FARM_ERROR_REPORT("Shared is null."));
158  }
159  }
160 
161  // Class invariant:non_null_shared_ is guaranteed not to be null.
162  std::shared_ptr<TT> non_null_shared_;
163 };
164 
165 template <typename TT>
167 
168 template <class TT, class... TArgs>
169 static ExpectShared<TT> tryMakeShared(TArgs&&... args) noexcept {
170  return Shared<TT>::tryMake(std::forward<TArgs>(args)...);
171 }
172 
173 template <typename TT>
174 using SharedVector = std::vector<Shared<TT>>;
175 
176 } // namespace farm_ng
farm_ng
Definition: backtrace.cpp:102
farm_ng::Shared::operator=
Shared< TT > & operator=(Shared< TT > &&o) noexcept
Definition: shared.h:140
farm_ng::Shared::BadExpectedAccess
tl::bad_expected_access< farm_ng::Error > BadExpectedAccess
Definition: shared.h:30
farm_ng::Shared::Shared
Shared() requires(std
Definition: shared.h:103
farm_ng::Shared::Shared
Shared(Shared< TDerived > const &other)
Definition: shared.h:110
core.event_service.args
args
Definition: event_service.py:549
farm_ng::Shared::operator*
TT const & operator*() const
Returns the interior object which is guaranteed to be available.
Definition: shared.h:80
farm_ng::Shared::Shared
Shared(Shared< TT > &&o) noexcept
Definition: shared.h:135
farm_ng::Shared::make
static Shared< TT > make(TArgs &&... args)
Construct and also makes interior object T Panics if the constructor throws. See tryFrom() for altern...
Definition: shared.h:71
farm_ng::Shared::operator->
TT * operator->()
Returns the interior object which is guaranteed to be available.
Definition: shared.h:83
farm_ng::Shared::sharedPtr
std::shared_ptr< TT > sharedPtr() const
Definition: shared.h:92
expected.h
concept_utils.h
FARM_ERROR_REPORT
#define FARM_ERROR_REPORT(cstr,...)
Definition: expected.h:81
farm_ng::Shared::ExpectedT
farm_ng::Expected< Shared< TT > > ExpectedT
Definition: shared.h:29
FARM_UNEXPECTED
#define FARM_UNEXPECTED(cstr,...)
Definition: expected.h:86
farm_ng::Shared::Shared
Shared(std::shared_ptr< TT > const &panic_if_null)
Definition: shared.h:130
farm_ng::Shared::ptr
TT * ptr()
Definition: shared.h:100
farm_ng::Shared::operator==
bool operator==(Shared< TT > const &rhs) const noexcept
Definition: shared.h:150
farm_ng::Shared::tryMake
static ExpectedT tryMake(TArgs &&... args) noexcept
Construct and also makes interior object T The return value is an object containing either a non-null...
Definition: shared.h:51
farm_ng::Shared::ptr
TT const * ptr() const
Definition: shared.h:97
farm_ng::Shared::operator->
TT const * operator->() const
Returns the interior object which is guaranteed to be available.
Definition: shared.h:86
farm_ng::Shared
Definition: shared.h:27
farm_ng::Shared::Shared
Shared(std::unique_ptr< TDerived > &&panic_if_null)
Definition: shared.h:123
farm_ng::ExpectShared
farm_ng::Expected< Shared< TT > > ExpectShared
Definition: shared.h:166
farm_ng::Shared::tryFrom
static ExpectedT tryFrom(std::shared_ptr< TT > const &maybe_null) noexcept
Construct from a possibly null shared_ptr The return value is an object containing either a non-null ...
Definition: shared.h:36
farm_ng::Shared::Shared
Shared(std::shared_ptr< TDerived > const &panic_if_null)
Definition: shared.h:116
farm_ng::Expected
tl::expected< TT, TE > Expected
Definition: expected.h:37
farm_ng::SharedVector
std::vector< Shared< TT > > SharedVector
Definition: shared.h:174
FARM_UNWRAP
#define FARM_UNWRAP(wrapper,...)
Returns *wrapper, but panics if wrapper is nullopt or null.
Definition: logger.h:576
farm_ng::Shared::operator*
TT & operator*()
Returns the interior object which is guaranteed to be available.
Definition: shared.h:77
farm_ng::Shared::from
static Shared from(std::shared_ptr< TT > const &shared)
Construct from a possibly null shared_ptr Panics if shared is null. See tryFrom() for alternate.
Definition: shared.h:63