rippled
Loading...
Searching...
No Matches
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 <xrpl/beast/utility/instrumentation.h>
24
25#include <exception>
26#include <mutex>
27#include <type_traits>
28#include <utility>
29
30namespace ripple {
31
32// RAII scope helpers. As specified in Library Fundamental, Version 3
33// Basic design of idea: https://www.youtube.com/watch?v=WjTrfoiB0MQ
34// Specification:
35// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/n4873.html#scopeguard
36
37// This implementation deviates from the spec slightly:
38// The scope_exit and scope_fail constructors taking a functor are not
39// permitted to throw an exception. This was done because some compilers
40// did not like the superfluous try/catch in the common instantiations
41// where the construction was noexcept. Instead a static_assert is used
42// to enforce this restriction.
43
44template <class EF>
46{
49
50public:
52 {
55 }
56
57 scope_exit(scope_exit&& rhs) noexcept(
58 std::is_nothrow_move_constructible_v<EF> ||
59 std::is_nothrow_copy_constructible_v<EF>)
60 : exit_function_{std::forward<EF>(rhs.exit_function_)}
61 , execute_on_destruction_{rhs.execute_on_destruction_}
62 {
63 rhs.release();
64 }
65
67 operator=(scope_exit&&) = delete;
68
69 template <class EFP>
70 explicit scope_exit(
71 EFP&& f,
74 std::is_constructible_v<EF, EFP>>* = 0) noexcept
75 : exit_function_{std::forward<EFP>(f)}
76 {
77 static_assert(
78 std::
79 is_nothrow_constructible_v<EF, decltype(std::forward<EFP>(f))>);
80 }
81
82 void
83 release() noexcept
84 {
86 }
87};
88
89template <class EF>
91
92template <class EF>
94{
98
99public:
101 {
105 }
106
107 scope_fail(scope_fail&& rhs) noexcept(
108 std::is_nothrow_move_constructible_v<EF> ||
109 std::is_nothrow_copy_constructible_v<EF>)
110 : exit_function_{std::forward<EF>(rhs.exit_function_)}
111 , execute_on_destruction_{rhs.execute_on_destruction_}
112 , uncaught_on_creation_{rhs.uncaught_on_creation_}
113 {
114 rhs.release();
115 }
116
119
120 template <class EFP>
121 explicit scope_fail(
122 EFP&& f,
125 std::is_constructible_v<EF, EFP>>* = 0) noexcept
126 : exit_function_{std::forward<EFP>(f)}
127 {
128 static_assert(
129 std::
130 is_nothrow_constructible_v<EF, decltype(std::forward<EFP>(f))>);
131 }
132
133 void
134 release() noexcept
135 {
137 }
138};
139
140template <class EF>
142
143template <class EF>
145{
149
150public:
151 ~scope_success() noexcept(noexcept(exit_function_()))
152 {
156 }
157
159 std::is_nothrow_move_constructible_v<EF> ||
160 std::is_nothrow_copy_constructible_v<EF>)
161 : exit_function_{std::forward<EF>(rhs.exit_function_)}
162 , execute_on_destruction_{rhs.execute_on_destruction_}
163 , uncaught_on_creation_{rhs.uncaught_on_creation_}
164 {
165 rhs.release();
166 }
167
170
171 template <class EFP>
173 EFP&& f,
176 std::is_constructible_v<EF, EFP>>* =
177 0) noexcept(std::is_nothrow_constructible_v<EF, EFP> || std::is_nothrow_constructible_v<EF, EFP&>)
178 : exit_function_{std::forward<EFP>(f)}
179 {
180 }
181
182 void
183 release() noexcept
184 {
186 }
187};
188
189template <class EF>
191
229template <class Mutex>
231{
233
234public:
235 explicit scope_unlock(std::unique_lock<Mutex>& lock) noexcept(true)
236 : plock(&lock)
237 {
238 XRPL_ASSERT(
239 plock->owns_lock(),
240 "ripple::scope_unlock::scope_unlock : mutex must be locked");
241 plock->unlock();
242 }
243
244 // Immovable type
245 scope_unlock(scope_unlock const&) = delete;
247 operator=(scope_unlock const&) = delete;
248
249 ~scope_unlock() noexcept(true)
250 {
251 plock->lock();
252 }
253};
254
255template <class Mutex>
257
258} // namespace ripple
259
260#endif
scope_exit(scope_exit &&rhs) noexcept(std::is_nothrow_move_constructible_v< EF >||std::is_nothrow_copy_constructible_v< EF >)
Definition: scope.h:57
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:70
scope_exit & operator=(scope_exit &&)=delete
bool execute_on_destruction_
Definition: scope.h:48
void release() noexcept
Definition: scope.h:83
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:121
void release() noexcept
Definition: scope.h:134
int uncaught_on_creation_
Definition: scope.h:97
scope_fail & operator=(scope_fail &&)=delete
bool execute_on_destruction_
Definition: scope.h:96
scope_fail(scope_fail &&rhs) noexcept(std::is_nothrow_move_constructible_v< EF >||std::is_nothrow_copy_constructible_v< EF >)
Definition: scope.h:107
bool execute_on_destruction_
Definition: scope.h:147
scope_success & operator=(scope_success &&)=delete
void release() noexcept
Definition: scope.h:183
scope_success(scope_success &&rhs) noexcept(std::is_nothrow_move_constructible_v< EF >||std::is_nothrow_copy_constructible_v< EF >)
Definition: scope.h:158
int uncaught_on_creation_
Definition: scope.h:148
~scope_success() noexcept(noexcept(exit_function_()))
Definition: scope.h:151
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:172
Automatically unlocks and re-locks a unique_lock object.
Definition: scope.h:231
scope_unlock(std::unique_lock< Mutex > &lock) noexcept(true)
Definition: scope.h:235
scope_unlock & operator=(scope_unlock const &)=delete
std::unique_lock< Mutex > * plock
Definition: scope.h:232
~scope_unlock() noexcept(true)
Definition: scope.h:249
scope_unlock(scope_unlock const &)=delete
T is_same_v
T lock(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
STL namespace.
T owns_lock(T... args)
T uncaught_exceptions(T... args)
T unlock(T... args)