rippled
scope.h
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2021 Ripple Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #ifndef RIPPLE_BASICS_SCOPE_H_INCLUDED
21 #define RIPPLE_BASICS_SCOPE_H_INCLUDED
22 
23 #include <exception>
24 #include <type_traits>
25 #include <utility>
26 
27 namespace ripple {
28 
29 // RAII scope helpers. As specified in Library Fundamental, Version 3
30 // Basic design of idea: https://www.youtube.com/watch?v=WjTrfoiB0MQ
31 // Specification:
32 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/n4873.html#scopeguard
33 
34 // This implementation deviates from the spec slightly:
35 // The scope_exit and scope_fail constructors taking a functor are not
36 // permitted to throw an exception. This was done because some compilers
37 // did not like the superfluous try/catch in the common instantiations
38 // where the construction was noexcept. Instead a static_assert is used
39 // to enforce this restriction.
40 
41 template <class EF>
43 {
46 
47 public:
49  {
52  }
53 
54  scope_exit(scope_exit&& rhs) noexcept(
55  std::is_nothrow_move_constructible_v<EF> ||
56  std::is_nothrow_copy_constructible_v<EF>)
57  : exit_function_{std::forward<EF>(rhs.exit_function_)}
58  , execute_on_destruction_{rhs.execute_on_destruction_}
59  {
60  rhs.release();
61  }
62 
63  scope_exit&
64  operator=(scope_exit&&) = delete;
65 
66  template <class EFP>
67  explicit scope_exit(
68  EFP&& f,
71  std::is_constructible_v<EF, EFP>>* = 0) noexcept
72  : exit_function_{std::forward<EFP>(f)}
73  {
74  static_assert(
75  std::
76  is_nothrow_constructible_v<EF, decltype(std::forward<EFP>(f))>);
77  }
78 
79  void
80  release() noexcept
81  {
83  }
84 };
85 
86 template <class EF>
87 scope_exit(EF) -> scope_exit<EF>;
88 
89 template <class EF>
91 {
95 
96 public:
98  {
101  exit_function_();
102  }
103 
104  scope_fail(scope_fail&& rhs) noexcept(
105  std::is_nothrow_move_constructible_v<EF> ||
106  std::is_nothrow_copy_constructible_v<EF>)
107  : exit_function_{std::forward<EF>(rhs.exit_function_)}
108  , execute_on_destruction_{rhs.execute_on_destruction_}
109  , uncaught_on_creation_{rhs.uncaught_on_creation_}
110  {
111  rhs.release();
112  }
113 
114  scope_fail&
115  operator=(scope_fail&&) = delete;
116 
117  template <class EFP>
118  explicit scope_fail(
119  EFP&& f,
122  std::is_constructible_v<EF, EFP>>* = 0) noexcept
123  : exit_function_{std::forward<EFP>(f)}
124  {
125  static_assert(
126  std::
127  is_nothrow_constructible_v<EF, decltype(std::forward<EFP>(f))>);
128  }
129 
130  void
131  release() noexcept
132  {
133  execute_on_destruction_ = false;
134  }
135 };
136 
137 template <class EF>
138 scope_fail(EF) -> scope_fail<EF>;
139 
140 template <class EF>
142 {
146 
147 public:
148  ~scope_success() noexcept(noexcept(exit_function_()))
149  {
152  exit_function_();
153  }
154 
155  scope_success(scope_success&& rhs) noexcept(
156  std::is_nothrow_move_constructible_v<EF> ||
157  std::is_nothrow_copy_constructible_v<EF>)
158  : exit_function_{std::forward<EF>(rhs.exit_function_)}
159  , execute_on_destruction_{rhs.execute_on_destruction_}
160  , uncaught_on_creation_{rhs.uncaught_on_creation_}
161  {
162  rhs.release();
163  }
164 
166  operator=(scope_success&&) = delete;
167 
168  template <class EFP>
169  explicit scope_success(
170  EFP&& f,
173  std::is_constructible_v<EF, EFP>>* =
174  0) noexcept(std::is_nothrow_constructible_v<EF, EFP> || std::is_nothrow_constructible_v<EF, EFP&>)
175  : exit_function_{std::forward<EFP>(f)}
176  {
177  }
178 
179  void
180  release() noexcept
181  {
182  execute_on_destruction_ = false;
183  }
184 };
185 
186 template <class EF>
187 scope_success(EF) -> scope_success<EF>;
188 
189 } // namespace ripple
190 
191 #endif
ripple::scope_success::uncaught_on_creation_
int uncaught_on_creation_
Definition: scope.h:145
std::is_same_v
T is_same_v
utility
exception
ripple::scope_success
Definition: scope.h:141
ripple::scope_exit
scope_exit(EF) -> scope_exit< EF >
ripple::scope_fail::scope_fail
scope_fail(scope_fail &&rhs) noexcept(std::is_nothrow_move_constructible_v< EF >||std::is_nothrow_copy_constructible_v< EF >)
Definition: scope.h:104
ripple::scope_success::scope_success
scope_success(EFP &&f, std::enable_if_t< !std::is_same_v< std::remove_cv_t< EFP >, scope_success > &&std::is_constructible_v< EF, EFP >> *=0) noexcept(std::is_nothrow_constructible_v< EF, EFP >||std::is_nothrow_constructible_v< EF, EFP & >)
Definition: scope.h:169
ripple::scope_fail::operator=
scope_fail & operator=(scope_fail &&)=delete
ripple::scope_success::execute_on_destruction_
bool execute_on_destruction_
Definition: scope.h:144
ripple::scope_fail::exit_function_
EF exit_function_
Definition: scope.h:92
ripple::scope_exit::~scope_exit
~scope_exit()
Definition: scope.h:48
ripple::scope_success::~scope_success
~scope_success() noexcept(noexcept(exit_function_()))
Definition: scope.h:148
std::enable_if_t
ripple::scope_fail
Definition: scope.h:90
ripple::scope_exit
Definition: scope.h:42
ripple::scope_exit::scope_exit
scope_exit(scope_exit &&rhs) noexcept(std::is_nothrow_move_constructible_v< EF >||std::is_nothrow_copy_constructible_v< EF >)
Definition: scope.h:54
ripple::scope_fail::uncaught_on_creation_
int uncaught_on_creation_
Definition: scope.h:94
ripple::scope_fail::scope_fail
scope_fail(EFP &&f, std::enable_if_t< !std::is_same_v< std::remove_cv_t< EFP >, scope_fail > &&std::is_constructible_v< EF, EFP >> *=0) noexcept
Definition: scope.h:118
ripple::scope_success
scope_success(EF) -> scope_success< EF >
ripple::scope_exit::execute_on_destruction_
bool execute_on_destruction_
Definition: scope.h:45
ripple::scope_success::release
void release() noexcept
Definition: scope.h:180
ripple::scope_exit::operator=
scope_exit & operator=(scope_exit &&)=delete
ripple::scope_success::operator=
scope_success & operator=(scope_success &&)=delete
ripple::scope_exit::exit_function_
EF exit_function_
Definition: scope.h:44
ripple::scope_success::exit_function_
EF exit_function_
Definition: scope.h:143
ripple::scope_exit::release
void release() noexcept
Definition: scope.h:80
ripple::scope_success::scope_success
scope_success(scope_success &&rhs) noexcept(std::is_nothrow_move_constructible_v< EF >||std::is_nothrow_copy_constructible_v< EF >)
Definition: scope.h:155
std::uncaught_exceptions
T uncaught_exceptions(T... args)
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::scope_exit::scope_exit
scope_exit(EFP &&f, std::enable_if_t< !std::is_same_v< std::remove_cv_t< EFP >, scope_exit > &&std::is_constructible_v< EF, EFP >> *=0) noexcept
Definition: scope.h:67
std
STL namespace.
ripple::scope_fail::release
void release() noexcept
Definition: scope.h:131
std::remove_cv_t
ripple::scope_fail::execute_on_destruction_
bool execute_on_destruction_
Definition: scope.h:93
ripple::scope_fail::~scope_fail
~scope_fail()
Definition: scope.h:97
type_traits
ripple::scope_fail
scope_fail(EF) -> scope_fail< EF >