Belle II Software  release-08-01-10
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 
16 namespace 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::result_of<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::result_of<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
static ScopeGuard guardDeletion(T *&pointer)
Create a ScopeGuard to delete a raw pointer at the end of the scope.
Definition: ScopeGuard.h:239
ScopeGuard & operator=(const ScopeGuard &)=delete
No assignment.
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 & operator=(ScopeGuard &&)=delete
No move assignment.
~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.
Abstract base class for different kinds of events.