mirror of
https://github.com/boostorg/scope.git
synced 2026-01-19 04:42:10 +00:00
Added scope guards docs.
This commit is contained in:
1
doc/.gitignore
vendored
Normal file
1
doc/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
html
|
||||
113
doc/Jamfile
Normal file
113
doc/Jamfile
Normal file
@@ -0,0 +1,113 @@
|
||||
# Copyright 2023 Andrey Semashev
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# https://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
using quickbook ;
|
||||
using boostbook ;
|
||||
using doxygen ;
|
||||
using xsltproc ;
|
||||
|
||||
import set ;
|
||||
import doxygen ;
|
||||
import xsltproc ;
|
||||
import notfile ;
|
||||
import path ;
|
||||
import project ;
|
||||
|
||||
project boost/libs/scope/doc ;
|
||||
|
||||
local doxygen_params =
|
||||
<doxygen:param>RECURSIVE=YES
|
||||
<doxygen:param>ALPHABETICAL_INDEX=YES
|
||||
<doxygen:param>REPEAT_BRIEF=YES
|
||||
<doxygen:param>ALWAYS_DETAILED_SEC=YES
|
||||
<doxygen:param>BRIEF_MEMBER_DESC=NO
|
||||
<doxygen:param>ABBREVIATE_BRIEF=YES
|
||||
<doxygen:param>INHERIT_DOCS=YES
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
<doxygen:param>HIDE_UNDOC_CLASSES=YES
|
||||
<doxygen:param>HIDE_SCOPE_NAMES=YES
|
||||
<doxygen:param>EXTRACT_ALL=NO
|
||||
<doxygen:param>EXTRACT_PRIVATE=NO
|
||||
<doxygen:param>BUILTIN_STL_SUPPORT=YES
|
||||
<doxygen:param>ENABLE_PREPROCESSING=YES
|
||||
<doxygen:param>MACRO_EXPANSION=YES
|
||||
<doxygen:param>TAB_SIZE=4
|
||||
<doxygen:param>SOURCE_BROWSER=YES
|
||||
<doxygen:param>VERBATIM_HEADERS=NO
|
||||
# <doxygen:param>SEARCH_INCLUDES=YES
|
||||
# <doxygen:param>"INCLUDE_PATH=../../.."
|
||||
# <doxygen:param>EXCLUDE_SYMBOLS="detail detail::*"
|
||||
<doxygen:param>"PREDEFINED=BOOST_SCOPE_DOXYGEN \\
|
||||
BOOST_SCOPE_DETAIL_DOC_HIDDEN(...)=... \\
|
||||
BOOST_NO_CXX17_DEDUCTION_GUIDES=1 \\
|
||||
BOOST_SYMBOL_VISIBLE= \\
|
||||
BOOST_FORCEINLINE=inline \\
|
||||
BOOST_INLINE_VARIABLE=inline \\
|
||||
BOOST_CXX14_CONSTEXPR=constexpr"
|
||||
<xsl:param>boost.doxygen.detailns=detail
|
||||
# <xsl:param>boost.doxygen.detail=implementation_
|
||||
;
|
||||
|
||||
|
||||
local top_level_includes =
|
||||
[ glob
|
||||
../../../boost/scope/*.hpp
|
||||
] ;
|
||||
|
||||
|
||||
# This rule generates *.qbk files with macros with references to files, classes, etc. from the doxygen resulting *.xml files.
|
||||
rule gen-references ( target : source : properties * )
|
||||
{
|
||||
DEPENDS target : source ;
|
||||
local source-path = [ path.make [ on $(source) return $(LOCATE) ] ] ;
|
||||
STYLESHEET on $(target) = [ path.native [ path.join [ path.parent $(source-path) ] gen_references.xsl ] ] ;
|
||||
local target-name = $(source:B) ;
|
||||
TARGET on $(target) = [ path.native [ path.join $(source-path) $(target-name:S=.qbk) ] ] ;
|
||||
}
|
||||
actions gen-references
|
||||
{
|
||||
$(NAME:E=xsltproc) -o "$(TARGET)" "$(STYLESHEET)" "$(>)"
|
||||
}
|
||||
|
||||
|
||||
doxygen top_level_reference
|
||||
:
|
||||
$(top_level_includes)
|
||||
:
|
||||
$(doxygen_params)
|
||||
<xsl:param>"boost.doxygen.reftitle=Reference"
|
||||
<location>tmp
|
||||
;
|
||||
|
||||
notfile top_level_refs : @gen-references : top_level_reference.xml ;
|
||||
|
||||
|
||||
xml scope_doc
|
||||
:
|
||||
scope.qbk
|
||||
:
|
||||
<dependency>top_level_refs
|
||||
;
|
||||
|
||||
boostbook scope
|
||||
:
|
||||
scope_doc
|
||||
:
|
||||
<xsl:param>"boost.root=../../../.."
|
||||
<xsl:param>"boost.libraries=../../../libs/libraries.htm"
|
||||
<xsl:param>"nav.layout=none"
|
||||
<xsl:param>"boost.image=Boost"
|
||||
<xsl:param>"navig.graphics=1"
|
||||
<xsl:param>"chunk.section.depth=1"
|
||||
<xsl:param>"boost.compact.function=0"
|
||||
<format>pdf:<xsl:param>"boost.url.prefix=https://www.boost.org/doc/libs/release/libs/scope/doc/html"
|
||||
;
|
||||
|
||||
###############################################################################
|
||||
alias boostdoc ;
|
||||
explicit boostdoc ;
|
||||
alias boostrelease : scope ;
|
||||
explicit boostrelease ;
|
||||
17
doc/changelog.qbk
Normal file
17
doc/changelog.qbk
Normal file
@@ -0,0 +1,17 @@
|
||||
[/
|
||||
/ Copyright 2023 Andrey Semashev
|
||||
/
|
||||
/ Distributed under the Boost Software License, Version 1.0.
|
||||
/ (See accompanying file LICENSE_1_0.txt or copy at
|
||||
/ https://www.boost.org/LICENSE_1_0.txt)
|
||||
/
|
||||
/ This document is a part of Boost.Scope library documentation.
|
||||
/]
|
||||
|
||||
[section:changelog Changelog]
|
||||
|
||||
[heading 0.1]
|
||||
|
||||
Initial release for Boost review.
|
||||
|
||||
[endsect]
|
||||
81
doc/gen_references.xsl
Normal file
81
doc/gen_references.xsl
Normal file
@@ -0,0 +1,81 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<!--
|
||||
Copyright 2023 Andrey Semashev
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
https://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
This stylesheet extracts information about headers, classes, etc.
|
||||
from the Doxygen-generated reference documentation and writes
|
||||
it as QuickBook templates that refer to the according Reference sections.
|
||||
-->
|
||||
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
<xsl:output method="text"/>
|
||||
<xsl:template match="/library-reference">
|
||||
<xsl:text disable-output-escaping="yes">[/
|
||||
/ Copyright 2023 Andrey Semashev
|
||||
/
|
||||
/ Distributed under the Boost Software License, Version 1.0.
|
||||
/ (See accompanying file LICENSE_1_0.txt or copy at
|
||||
/ https://www.boost.org/LICENSE_1_0.txt)
|
||||
/
|
||||
/ This document is a part of Boost.Scope library documentation.
|
||||
/
|
||||
/ This document was automatically generated, DO NOT EDIT!
|
||||
/]
|
||||
</xsl:text>
|
||||
<xsl:apply-templates>
|
||||
<xsl:with-param name="namespace"/>
|
||||
<xsl:with-param name="enclosing_namespace"/>
|
||||
</xsl:apply-templates>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Skip any text nodes -->
|
||||
<xsl:template match="text()"/>
|
||||
|
||||
<!-- Headers -->
|
||||
<xsl:template match="header">
|
||||
<xsl:param name="namespace"/>
|
||||
<xsl:param name="enclosing_namespace"/>
|
||||
[template <xsl:value-of select="translate(@name, '/.', '__')"/>[][headerref <xsl:value-of select="@name"/>]]
|
||||
<xsl:apply-templates>
|
||||
<xsl:with-param name="namespace" select="$namespace"/>
|
||||
<xsl:with-param name="enclosing_namespace" select="$enclosing_namespace"/>
|
||||
</xsl:apply-templates>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Namespaces - only needed to construct fully qualified class names -->
|
||||
<xsl:template match="namespace">
|
||||
<xsl:param name="namespace"/>
|
||||
<xsl:param name="enclosing_namespace"/>
|
||||
<xsl:variable name="namespace_prefix">
|
||||
<xsl:value-of select="$namespace"/><xsl:if test="string-length($namespace) > 0"><xsl:text>::</xsl:text></xsl:if>
|
||||
</xsl:variable>
|
||||
<xsl:apply-templates>
|
||||
<xsl:with-param name="namespace" select="concat($namespace_prefix, @name)"/>
|
||||
<xsl:with-param name="enclosing_namespace" select="@name"/>
|
||||
</xsl:apply-templates>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Classses -->
|
||||
<xsl:template match="class|struct">
|
||||
<xsl:param name="namespace"/>
|
||||
<xsl:param name="enclosing_namespace"/>
|
||||
[template <xsl:value-of select="concat('class_', $enclosing_namespace, '_', @name)"/>[][classref <xsl:value-of select="concat($namespace, '::', @name)"/><xsl:text> </xsl:text><xsl:value-of select="@name"/>]]
|
||||
<xsl:apply-templates>
|
||||
<xsl:with-param name="namespace" select="concat($namespace, '::', @name)"/>
|
||||
<xsl:with-param name="enclosing_namespace" select="concat($enclosing_namespace, '_', @name)"/>
|
||||
</xsl:apply-templates>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Free functions - currently disabled because multiple overloads generate duplicate QuickBook templates -->
|
||||
<!--
|
||||
<xsl:template match="function">
|
||||
<xsl:param name="namespace"/>
|
||||
<xsl:param name="enclosing_namespace"/>
|
||||
[template <xsl:value-of select="concat('func_', $enclosing_namespace, '_', @name)"/>[][funcref <xsl:value-of select="concat($namespace, '::', @name)"/><xsl:text> </xsl:text><xsl:value-of select="@name"/>]]
|
||||
</xsl:template>
|
||||
-->
|
||||
|
||||
</xsl:transform>
|
||||
221
doc/scope.qbk
Normal file
221
doc/scope.qbk
Normal file
@@ -0,0 +1,221 @@
|
||||
[library Boost.Scope
|
||||
[quickbook 1.7]
|
||||
[authors [Semashev, Andrey]]
|
||||
[copyright 2022-2023 Andrey Semashev]
|
||||
[license
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
[@https://www.boost.org/LICENSE_1_0.txt]).
|
||||
]
|
||||
[id scope]
|
||||
[source-mode c++]
|
||||
]
|
||||
|
||||
[c++]
|
||||
|
||||
[/ Links to external resources /]
|
||||
[def __boost_config__ [@http://www.boost.org/doc/libs/release/libs/config/doc/html/index.html Boost.Config]]
|
||||
[def __boost_function__ [@https://www.boost.org/doc/libs/release/doc/html/function.html Boost.Function]]
|
||||
[def __boost_scope_exit__ [@http://www.boost.org/doc/libs/release/libs/scope_exit/doc/html/index.html Boost.ScopeExit]]
|
||||
[def __boost_smart_ptr__ [@http://www.boost.org/doc/libs/release/libs/smart_ptr/doc/html/smart_ptr.html Boost.SmartPtr]]
|
||||
|
||||
[template github_issue[key][@https://github.com/boostorg/scope/issues/[key] #[key]]]
|
||||
[template github_pr[key][@https://github.com/boostorg/scope/pull/[key] PR#[key]]]
|
||||
|
||||
[/ Auto-generated macros that refer to Reference sections /]
|
||||
[import tmp/top_level_reference.qbk]
|
||||
|
||||
[section:intro Introduction]
|
||||
|
||||
The Boost.Scope library is a collection of utilities helping code execution upon leaving a scope and automatic resource management. The library contains
|
||||
components that were defined in the [@https://cplusplus.github.io/fundamentals-ts/v3.html C++ Extensions for Library Fundamentals, Version 3] technical specification,
|
||||
in the [@https://cplusplus.github.io/fundamentals-ts/v3.html#scope.syn `<experimental/scope>`] standard library
|
||||
header. The library also contains extensions to the Fundamentals TS that improve usability or efficiency of the components.
|
||||
|
||||
The components provided by the library can be divided into two categories:
|
||||
|
||||
* A set of scope guards that allow executing arbitrary code when the scope guard is destroyed,
|
||||
* A generic resource handle that automatically frees the owned resource upon destruction.
|
||||
|
||||
There is some overlap in terms of functionality with __boost_scope_exit__, __boost_smart_ptr__ as well as C++ standard library smart-pointers. __boost_scope_exit__
|
||||
defines a set of macros for defining code blocks to be executed at scope exit. Scope guards provided by Boost.Scope provide similar functionality, but with
|
||||
simpler syntax and new features. You can see the syntax differences in the table below:
|
||||
|
||||
[table __boost_scope_exit__ and Boost.Scope comparison
|
||||
[[__boost_scope_exit__ (C++03)] [Boost.Scope (C++11)] [Boost.Scope (C++17)]]
|
||||
[[
|
||||
```
|
||||
class adder
|
||||
{
|
||||
int x, y;
|
||||
|
||||
public:
|
||||
int compute()
|
||||
{
|
||||
// Reset variables on return
|
||||
BOOST_SCOPE_EXIT(this_)
|
||||
{
|
||||
this_->x = 0;
|
||||
this_->y = 0;
|
||||
}
|
||||
BOOST_SCOPE_EXIT_END;
|
||||
|
||||
return x + y;
|
||||
}
|
||||
};
|
||||
```
|
||||
]
|
||||
[
|
||||
```
|
||||
class adder
|
||||
{
|
||||
int x, y;
|
||||
|
||||
public:
|
||||
int compute()
|
||||
{
|
||||
// Reset variables on return
|
||||
auto cleanup = boost::scope::make_scope_exit([this]
|
||||
{
|
||||
x = 0;
|
||||
y = 0;
|
||||
});
|
||||
|
||||
return x + y;
|
||||
}
|
||||
};
|
||||
```
|
||||
]
|
||||
[
|
||||
```
|
||||
class adder
|
||||
{
|
||||
int x, y;
|
||||
|
||||
public:
|
||||
int compute()
|
||||
{
|
||||
// Reset variables on return
|
||||
BOOST_SCOPE_FINAL [this]
|
||||
{
|
||||
x = 0;
|
||||
y = 0;
|
||||
};
|
||||
|
||||
return x + y;
|
||||
}
|
||||
};
|
||||
```
|
||||
]]
|
||||
[[
|
||||
```
|
||||
template< typename Object >
|
||||
class collection
|
||||
{
|
||||
std::set< Object > objects;
|
||||
|
||||
public:
|
||||
template< typename T >
|
||||
void add_object(T const& arg)
|
||||
{
|
||||
typename std::set< Object >::iterator it =
|
||||
objects.insert(Object());
|
||||
|
||||
// Remove the object on failure
|
||||
unsigned int uncaught_count =
|
||||
boost::core::uncaught_exceptions();
|
||||
BOOST_SCOPE_EXIT_TPL(this_, it, uncaught_count)
|
||||
{
|
||||
if (uncaught_count != boost::core::uncaught_exceptions())
|
||||
this_->objects.erase(it);
|
||||
}
|
||||
BOOST_SCOPE_EXIT_END;
|
||||
|
||||
// Throws on error
|
||||
it->activate(arg);
|
||||
}
|
||||
};
|
||||
```
|
||||
]
|
||||
[
|
||||
```
|
||||
template< typename Object >
|
||||
class collection
|
||||
{
|
||||
std::set< Object > objects;
|
||||
|
||||
public:
|
||||
template< typename T >
|
||||
void add_object(T&& arg)
|
||||
{
|
||||
auto it = objects.emplace();
|
||||
|
||||
// Remove the object on failure
|
||||
auto cleanup = boost::scope::make_scope_fail([this, it]
|
||||
{
|
||||
objects.erase(it);
|
||||
});
|
||||
|
||||
// Throws on error
|
||||
it->activate(std::forward< T >(arg));
|
||||
}
|
||||
};
|
||||
```
|
||||
]
|
||||
[
|
||||
```
|
||||
template< typename Object >
|
||||
class collection
|
||||
{
|
||||
std::set< Object > objects;
|
||||
|
||||
public:
|
||||
template< typename T >
|
||||
void add_object(T&& arg)
|
||||
{
|
||||
auto it = objects.emplace();
|
||||
|
||||
// Remove the object on failure
|
||||
boost::scope::scope_fail cleanup{[this, it]
|
||||
{
|
||||
objects.erase(it);
|
||||
}};
|
||||
|
||||
// Throws on error
|
||||
it->activate(std::forward< T >(arg));
|
||||
}
|
||||
};
|
||||
```
|
||||
]]
|
||||
]
|
||||
|
||||
Unique resource wrapper provided by Boost.Scope is a generalization of smart pointers like `std::unique_ptr` and `boost::scoped_ptr` from __boost_smart_ptr__. While
|
||||
smart pointers are suitable for managing resources represented by pointers (e.g. objects in dynamically allocated memory), unique resource wrapper can be used
|
||||
with any kind of resource types, such as integers (e.g. POSIX file descriptors) and user-defined types.
|
||||
|
||||
The library defines its components in namespace `boost::scope`. For brevity, the namespace qualification may be omitted in this documentation; readers should assume
|
||||
that unqualified names like `scope_exit` or `unique_resource` are defined in `boost::scope`.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:install_compat Installation and compatibility]
|
||||
|
||||
This library is header-only, it does not require separate compilation. You can add the path to Boost headers to your project, include the required Boost.Scope header
|
||||
and then use the component provided by that header in your code.
|
||||
|
||||
The library requires a C++11 compiler at the minimum. For certain fetures, C++17 support is required. The following compilers were tested with the library:
|
||||
|
||||
* gcc 4.8 and newer
|
||||
* clang 3.5 and newer
|
||||
* MSVC 14.0 and newer
|
||||
|
||||
Except for the POSIX file descriptor support, which is only available on POSIX systems, the library components are agnostic to the operating system.
|
||||
|
||||
[endsect]
|
||||
|
||||
[include scope_guards.qbk]
|
||||
[include unique_resource.qbk]
|
||||
|
||||
[xinclude tmp/top_level_reference.xml]
|
||||
|
||||
[include changelog.qbk]
|
||||
207
doc/scope_guards.qbk
Normal file
207
doc/scope_guards.qbk
Normal file
@@ -0,0 +1,207 @@
|
||||
[/
|
||||
/ Copyright 2023 Andrey Semashev
|
||||
/
|
||||
/ Distributed under the Boost Software License, Version 1.0.
|
||||
/ (See accompanying file LICENSE_1_0.txt or copy at
|
||||
/ https://www.boost.org/LICENSE_1_0.txt)
|
||||
/
|
||||
/ This document is a part of Boost.Scope library documentation.
|
||||
/]
|
||||
|
||||
[section:scope_guards Scope guards]
|
||||
|
||||
A scope guard is an object that invokes an arbitrary function object on destruction. Scope guards are useful for implementing actions
|
||||
that need to be reliably performed upon control leaving an execution scope, which is especially helpful for handling exceptions.
|
||||
|
||||
The wrapped function object is specified on the scope guard construction and cannot be changed afterwards. It must be one of:
|
||||
|
||||
* a user-defined class with a public `operator()` taking no arguments, or
|
||||
* an lvalue reference to such class, or
|
||||
* an lvalue reference to a function taking no arguments.
|
||||
|
||||
Boost.Scope provides four kinds of scope guards, differing in their features and conditions upon which the function object is called,
|
||||
summarised in the table below.
|
||||
|
||||
[table Scope guard comparison
|
||||
[[Feature] [[class_scope_scope_exit]] [[class_scope_scope_success]] [[class_scope_scope_fail]] [[class_scope_scope_final]]]
|
||||
[[Invokes function on normal scope exit?] [Yes] [Yes] [No] [Yes]]
|
||||
[[Invokes function on scope exit due to an exception?] [Yes] [No] [Yes] [Yes]]
|
||||
[[Function may throw?] [Yes] [Yes] [No] [Yes]]
|
||||
[[Can be (de)activated?] [Yes] [Yes] [Yes] [No]]
|
||||
[[Move-constructible? (requires function to be move-constructible)] [Yes] [Yes] [Yes] [No]]
|
||||
[[Has factory function? (C++11-friendly)] [Yes] [Yes] [Yes] [No]]
|
||||
]
|
||||
|
||||
[note Except for [class_scope_scope_fail], function objects wrapped in scope guards are allowed to throw exceptions upon execution.
|
||||
However, users should remember that [class_scope_scope_exit] and [class_scope_scope_final] invoke the wrapped function upon exceptions,
|
||||
and throwing an exception from the scope guard in this case will terminate the program. It is user's responsibility to ensure this
|
||||
doesn't happen. This problem doesn't exist for [class_scope_scope_success] because it doesn't invoke the wrapped function object on
|
||||
exceptions. However, it is generally recommended to use scope guards to implement actions that cannot throw and move all operations
|
||||
that may fail to the normal code flow.]
|
||||
|
||||
[section:conditional `scope_exit`, `scope_success` and `scope_fail`]
|
||||
|
||||
#include <``[boost_scope_scope_exit_hpp]``>
|
||||
#include <``[boost_scope_scope_success_hpp]``>
|
||||
#include <``[boost_scope_scope_fail_hpp]``>
|
||||
|
||||
The [class_scope_scope_exit], [class_scope_scope_success] and [class_scope_scope_fail] scope guards provide similar interfaces and
|
||||
capabilities and only differ in conditions when they invoke the wrapped function object. As shown in the table above,
|
||||
[class_scope_scope_success] only invokes the function object if it is destroyed normally, [class_scope_scope_fail] - if it is
|
||||
destroyed due to an exception being thrown, and [class_scope_scope_exit] acts regardless of the exception status.
|
||||
|
||||
In addition to the exception status, each of the scope guards supports active and inactive state. The wrapped function object will
|
||||
only be called if the scope guard is in active state while being destroyed. By default, scope guards are created in active state,
|
||||
but this can be changed by passing `false` as the second argument for the constructor. Scope guards can also be deactivated or
|
||||
re-activated during their lifetime, which can be useful if the scope guard needs to be activated based on some condition.
|
||||
|
||||
class collection
|
||||
{
|
||||
std::set< std::shared_ptr< object > > objects;
|
||||
|
||||
public:
|
||||
void add_object(std::shared_ptr< object > const& obj)
|
||||
{
|
||||
// Create a deactivated scope guard initially
|
||||
std::set< std::shared_ptr< object > >::iterator it;
|
||||
boost::scope::scope_fail rollback_guard{[&, this]
|
||||
{
|
||||
objects.erase(it);
|
||||
},
|
||||
false};
|
||||
|
||||
bool inserted;
|
||||
std::tie(it, inserted) = objects.insert(obj);
|
||||
if (inserted)
|
||||
{
|
||||
// Activate rollback guard
|
||||
rollback_guard.set_active(true);
|
||||
}
|
||||
|
||||
obj->on_added_to_collection(*this);
|
||||
}
|
||||
};
|
||||
|
||||
The code sample above relies on C++17 [@https://en.cppreference.com/w/cpp/language/class_template_argument_deduction class template
|
||||
argument deduction (CTAD)] for `scope_fail` to deduce the function object type (which is the lambda). If this feature is not available,
|
||||
the scope guard construction can be rewritten using a factory function, like this:
|
||||
|
||||
auto rollback_guard = boost::scope::make_scope_fail([&, this]
|
||||
{
|
||||
objects.erase(it);
|
||||
},
|
||||
false);
|
||||
|
||||
Factory functions are provided for each of the three scope guards described in this section and are compatible with C++11.
|
||||
|
||||
Scope guards described in this section are moveable, which requires the wrapped function objects to be moveable or copyable as well. After
|
||||
moving, the moved-from scope guard becomes inactive.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:unconditional `scope_final`]
|
||||
|
||||
#include <``[boost_scope_scope_final_hpp]``>
|
||||
|
||||
The [class_scope_scope_final] scope guard is similar to [class_scope_scope_exit] in terms of when it invokes the wrapped function. But it
|
||||
lacks support for moveability and activation/deactivation - this scope guard is always active upon construction. This allows to implement
|
||||
it more efficiently when these features are not needed.
|
||||
|
||||
[note [class_scope_scope_final] is a more lightweight version of [class_scope_scope_exit], similar to how `std::lock_guard` is a more
|
||||
lightweight version of `std::unique_lock`.]
|
||||
|
||||
Since [class_scope_scope_final] effectively provides no interface to interact with after construction, it is better suited for anonymous
|
||||
"set up and forget" kind of scope guards. To reinforce this affinity, the library provides a `BOOST_SCOPE_FINAL` macro, which acts as
|
||||
a keyword defining a uniquely named [class_scope_scope_final] scope guard. The macro should be followed by the function object to be
|
||||
invoked on scope exit.
|
||||
|
||||
BOOST_SCOPE_FINAL []
|
||||
{
|
||||
std::cout << "Hello world!" << std::endl;
|
||||
};
|
||||
|
||||
[note `BOOST_SCOPE_FINAL` requires support for C++17 [@https://en.cppreference.com/w/cpp/language/class_template_argument_deduction CTAD].
|
||||
The [class_scope_scope_final] class itself is compatible with C++11, but given that there is no factory function for it, C++17 support is
|
||||
very much desired.]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:runtime_defined Setting up scope exit actions at run time]
|
||||
|
||||
It is possible to use scope guard classes to implement scope exit actions that are initialized at run time. To implement this, one could use
|
||||
a function object wrapper such as `std::function` together with the scope guard to schedule the function call. For example:
|
||||
|
||||
using cleanup_func_t = std::function< void() >;
|
||||
// Create an inactive scope guard first, since the cleanup function is not set yet
|
||||
boost::scope::scope_exit< cleanup_func_t > cleanup(cleanup_func_t(), false);
|
||||
|
||||
// Later in the program, initialize the scope guard with the function selected at run time
|
||||
if (cond)
|
||||
{
|
||||
cleanup = boost::scope::scope_exit< cleanup_func_t >([]
|
||||
{
|
||||
std::cout << "cond is true" << std::endl;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
cleanup = boost::scope::scope_exit< cleanup_func_t >([]
|
||||
{
|
||||
std::cout << "cond is false" << std::endl;
|
||||
});
|
||||
}
|
||||
|
||||
It is also possible to do this with `BOOST_SCOPE_FINAL`, although it eliminates one of the advantages provided by this macro, namely not
|
||||
having to invent a variable name. Also note that the function wrapper must be valid at all times once the scope guard is constructed.
|
||||
|
||||
// Create a non-empty function wrapper that does nothing
|
||||
std::function< void() > cleanup_func = [] {};
|
||||
// Create a scope guard that refers to the function wrapper
|
||||
BOOST_SCOPE_FINAL std::ref(cleanup_func);
|
||||
|
||||
// Later in the program, initialize the function wrapper
|
||||
if (cond)
|
||||
{
|
||||
cleanup_func = []
|
||||
{
|
||||
std::cout << "cond is true" << std::endl;
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
cleanup_func = []
|
||||
{
|
||||
std::cout << "cond is false" << std::endl;
|
||||
};
|
||||
}
|
||||
|
||||
However, when setting up scope exit actions at run time like that, users should be aware that function wrappers typically use dynamic
|
||||
memory allocation internally and copy the function object data, which may involve calling copy constructors that may also fail with an
|
||||
exception. Although many standard library implementations use small object optimization for `std::function`, and this technique is also
|
||||
used in other implementations like __boost_function__, it is generally not guaranteed that initializing the function wrapper with a given
|
||||
function object will not throw. If setting up the scope exit action needs to be a non-throwing operation (for example, if the scope guard
|
||||
is supposed to revert the effects of the immediately preceding operation), it is recommended to initialize inactive scope guards beforehand
|
||||
and only activate one of them at a later point in the program.
|
||||
|
||||
// Create inactive scope guards for both branches
|
||||
boost::scope::scope_exit cleanup_true([]
|
||||
{
|
||||
std::cout << "cond is true" << std::endl;
|
||||
},
|
||||
false);
|
||||
boost::scope::scope_exit cleanup_false([]
|
||||
{
|
||||
std::cout << "cond is false" << std::endl;
|
||||
},
|
||||
false);
|
||||
|
||||
// Later in the program, activate one of the scope guards.
|
||||
// This won't throw.
|
||||
if (cond)
|
||||
cleanup_true.set_active(true);
|
||||
else
|
||||
cleanup_false.set_active(true);
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
2
doc/tmp/.gitignore
vendored
Normal file
2
doc/tmp/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*.qbk
|
||||
*.xml
|
||||
1
doc/tmp/boost-no-inspect
Normal file
1
doc/tmp/boost-no-inspect
Normal file
@@ -0,0 +1 @@
|
||||
This file tells boost inspect to ignore this directory and any sub-directories
|
||||
14
doc/unique_resource.qbk
Normal file
14
doc/unique_resource.qbk
Normal file
@@ -0,0 +1,14 @@
|
||||
[/
|
||||
/ Copyright 2023 Andrey Semashev
|
||||
/
|
||||
/ Distributed under the Boost Software License, Version 1.0.
|
||||
/ (See accompanying file LICENSE_1_0.txt or copy at
|
||||
/ https://www.boost.org/LICENSE_1_0.txt)
|
||||
/
|
||||
/ This document is a part of Boost.Scope library documentation.
|
||||
/]
|
||||
|
||||
[section:unique_resource Unique resource handle]
|
||||
|
||||
|
||||
[endsect]
|
||||
Reference in New Issue
Block a user