Belle II Software development
ScopeGuard.h
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8#pragma once
9
10#include <functional>
11#include <ios>
12#include <TSystem.h>
13#include <TROOT.h>
14#include <string>
15
16namespace Belle2 {
36 class ScopeGuard {
37 private:
39 std::function<void()> m_exitfunc;
41 bool m_engaged{true};
42 public:
44 template<class Callable> explicit ScopeGuard(Callable&& f): m_exitfunc{std::forward<Callable>(f)} {}
46 ScopeGuard(const ScopeGuard&) = delete;
48 ScopeGuard(ScopeGuard&& sg) = delete;
50 ScopeGuard& operator=(const ScopeGuard&) = delete;
56 void release() { m_engaged = false; }
57
76 template<class T> [[nodiscard]] static ScopeGuard guardValue(T& reference)
77 {
78 // the [[nodiscard]] will issue warnings when users just call this
79 // function and don't assign the ScopeGuard
80 const T old = reference;
81 // This works even without any assignment or move constructors since
82 // C++17 guarantees that this temporary object will be constructed in
83 // place and no movement is required (tags: RVO, copy elision)
84 return ScopeGuard([&reference, old]() { reference = old; });
85 }
86
108 template<class T, class V> [[nodiscard]] static ScopeGuard guardValue(T& reference, const V& newValue)
109 {
110 const T old = reference;
111 reference = newValue;
112 return ScopeGuard([&reference, old]() { reference = old; });
113 }
114
136 template<class Getter, class Setter> [[nodiscard]]
137 static ScopeGuard guardGetterSetter(Getter getter, Setter setter)
138 {
139 const auto old = getter();
140 return ScopeGuard([setter, old]() { setter(old); });
141 }
142
167 template<class Getter, class Setter> [[nodiscard]]
168 static ScopeGuard guardGetterSetter(const Getter& getter, Setter setter,
169 const typename std::result_of<Getter()>::type newValue)
170 {
171 const auto old = getter();
172 setter(newValue);
173 return ScopeGuard([setter, old]() { setter(old); });
174 }
175
188 template<class Functor> [[nodiscard]] static ScopeGuard guardFunctor(Functor functor)
189 {
190 typedef typename std::invoke_result<Functor>::type value_type;
191 std::function<void(const value_type&)> setter(functor);
192 const auto old = functor();
193 return ScopeGuard([setter, old] {setter(old);});
194 }
195
209 template<class Functor> [[nodiscard]]
210 static ScopeGuard guardFunctor(Functor functor, const typename std::result_of<Functor()>::type& newValue)
211 {
212 typedef typename std::invoke_result<Functor>::type value_type;
213 std::function<void(const value_type&)> setter(functor);
214 const auto old = functor();
215 setter(newValue);
216 return ScopeGuard([setter, old] {setter(old);});
217 }
218
239 template <class T> [[nodiscard]] static ScopeGuard guardDeletion(T*& pointer)
240 {
241 return ScopeGuard([&pointer]() { delete pointer; pointer = nullptr; });
242 }
243
261 template<class CharT, class Traits = typename std::char_traits<CharT>> [[nodiscard]]
262 static ScopeGuard guardStreamState(std::basic_ios<CharT, Traits>& stream)
263 {
264 const std::ios::fmtflags flags{stream.flags()};
265 const std::streamsize precision{stream.precision()};
266 const std::streamsize width{stream.width()};
267 const CharT fill{stream.fill()};
268
269 return ScopeGuard([ =, &stream]() {
270 stream.flags(flags);
271 stream.precision(precision);
272 stream.width(width);
273 stream.fill(fill);
274 });
275 }
276
296 [[nodiscard]] static ScopeGuard guardWorkingDirectory()
297 {
298 const std::string old{gSystem->GetWorkingDirectory()};
299 return ScopeGuard([old]() {gSystem->ChangeDirectory(old.c_str());});
300 }
301
323 [[nodiscard]] static ScopeGuard guardWorkingDirectory(const std::string& newDirectory)
324 {
325 const std::string old{gSystem->GetWorkingDirectory()};
326 gSystem->ChangeDirectory(newDirectory.c_str());
327 return ScopeGuard([old]() {gSystem->ChangeDirectory(old.c_str());});
328 }
329
352 [[nodiscard]] static ScopeGuard guardBatchMode(bool batchMode = true)
353 {
354 auto getBatchMode = []() {
355 return gROOT->IsBatch();
356 };
357
358 auto setBatchMode = [](bool batchMode_) {
359 gROOT->SetBatch(batchMode_);
360 };
361
362 return guardGetterSetter(getBatchMode, setBatchMode, batchMode);
363 }
364 };
366}
Simple ScopeGuard to execute a function at the end of the object lifetime.
Definition: ScopeGuard.h:36
static ScopeGuard guardStreamState(std::basic_ios< CharT, Traits > &stream)
Create a ScopeGuard for the state of a stream to reset all the formatting at the end of the object li...
Definition: ScopeGuard.h:262
static ScopeGuard guardValue(T &reference)
Create a ScopeGuard for a value: The content of reference will be copied and reset when the returned ...
Definition: ScopeGuard.h:76
ScopeGuard(Callable &&f)
Construct a object with a callable function to be called on destruction.
Definition: ScopeGuard.h:44
void release()
Release the guard without calling the cleanup function.
Definition: ScopeGuard.h:56
ScopeGuard(const ScopeGuard &)=delete
No copies.
std::function< void()> m_exitfunc
Function to be called on exit.
Definition: ScopeGuard.h:39
static ScopeGuard guardGetterSetter(Getter getter, Setter setter)
Create a ScopeGuard from a getter and setter: On construction the getter object is called to obtain a...
Definition: ScopeGuard.h:137
ScopeGuard & operator=(ScopeGuard &&)=delete
No move assignment.
static ScopeGuard guardDeletion(T *&pointer)
Create a ScopeGuard to delete a raw pointer at the end of the scope.
Definition: ScopeGuard.h:239
static ScopeGuard guardFunctor(Functor functor)
Create a ScopeGuard from a functor object with appropriately overloaded operator() calls to get and s...
Definition: ScopeGuard.h:188
static ScopeGuard guardValue(T &reference, const V &newValue)
Create a ScopeGuard for a value: The content of reference will be copied and reset when the returned ...
Definition: ScopeGuard.h:108
~ScopeGuard()
Call function on destruct unless released has been called.
Definition: ScopeGuard.h:54
static ScopeGuard guardWorkingDirectory(const std::string &newDirectory)
Create a ScopeGuard of the current working directory and change into a new directory.
Definition: ScopeGuard.h:323
static ScopeGuard guardBatchMode(bool batchMode=true)
Create a ScopeGuard to turn ROOT into batch mode and restore the initial batch mode status after the ...
Definition: ScopeGuard.h:352
bool m_engaged
Indicate whether function should be called.
Definition: ScopeGuard.h:41
static ScopeGuard guardGetterSetter(const Getter &getter, Setter setter, const typename std::result_of< Getter()>::type newValue)
Create a ScopeGuard from a getter and setter: On construction first the getter is called to get the o...
Definition: ScopeGuard.h:168
static ScopeGuard guardFunctor(Functor functor, const typename std::result_of< Functor()>::type &newValue)
Create a ScopeGuard from a functor object with appropriately overloaded operator() calls to get and s...
Definition: ScopeGuard.h:210
static ScopeGuard guardWorkingDirectory()
Create a ScopeGuard of the current working directory.
Definition: ScopeGuard.h:296
ScopeGuard(ScopeGuard &&sg)=delete
No move construction.
ScopeGuard & operator=(const ScopeGuard &)=delete
No assignment.
Abstract base class for different kinds of events.
STL namespace.