Belle II Software  release-05-02-19
ScopeGuard.h
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2018 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Martin Ritter *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 #pragma once
11 
12 #include <functional>
13 #include <ios>
14 #include <TSystem.h>
15 #include <TROOT.h>
16 #include <string>
17 
18 namespace Belle2 {
38  class ScopeGuard {
39  private:
41  std::function<void()> m_exitfunc;
43  bool m_engaged{true};
44  public:
46  template<class Callable> explicit ScopeGuard(Callable&& f): m_exitfunc{std::forward<Callable>(f)} {}
48  ScopeGuard(const ScopeGuard&) = delete;
50  ScopeGuard(ScopeGuard&& sg) = delete;
52  ScopeGuard& operator=(const ScopeGuard&) = delete;
56  ~ScopeGuard() { if (m_engaged) m_exitfunc(); }
58  void release() { m_engaged = false; }
59 
78  template<class T> [[nodiscard]] static ScopeGuard guardValue(T& reference)
79  {
80  // the [[nodiscard]] will issue warnings when users just call this
81  // function and don't assign the ScopeGuard
82  const T old = reference;
83  // This works even without any assignment or move constructors since
84  // C++17 guarantees that this temporary object will be constructed in
85  // place and no movement is required (tags: RVO, copy elision)
86  return ScopeGuard([&reference, old]() { reference = old; });
87  }
88 
110  template<class T, class V> [[nodiscard]] static ScopeGuard guardValue(T& reference, const V& newValue)
111  {
112  const T old = reference;
113  reference = newValue;
114  return ScopeGuard([&reference, old]() { reference = old; });
115  }
116 
138  template<class Getter, class Setter> [[nodiscard]]
139  static ScopeGuard guardGetterSetter(Getter getter, Setter setter)
140  {
141  const auto old = getter();
142  return ScopeGuard([setter, old]() { setter(old); });
143  }
144 
169  template<class Getter, class Setter> [[nodiscard]]
170  static ScopeGuard guardGetterSetter(const Getter& getter, Setter setter,
171  const typename std::result_of<Getter()>::type newValue)
172  {
173  const auto old = getter();
174  setter(newValue);
175  return ScopeGuard([setter, old]() { setter(old); });
176  }
177 
190  template<class Functor> [[nodiscard]] static ScopeGuard guardFunctor(Functor functor)
191  {
192  typedef typename std::result_of<Functor()>::type value_type;
193  std::function<void(const value_type&)> setter(functor);
194  const auto old = functor();
195  return ScopeGuard([setter, old] {setter(old);});
196  }
197 
211  template<class Functor> [[nodiscard]]
212  static ScopeGuard guardFunctor(Functor functor, const typename std::result_of<Functor()>::type& newValue)
213  {
214  typedef typename std::result_of<Functor()>::type value_type;
215  std::function<void(const value_type&)> setter(functor);
216  const auto old = functor();
217  setter(newValue);
218  return ScopeGuard([setter, old] {setter(old);});
219  }
220 
241  template <class T> [[nodiscard]] static ScopeGuard guardDeletion(T*& pointer)
242  {
243  return ScopeGuard([&pointer]() { delete pointer; pointer = nullptr; });
244  }
245 
263  template<class CharT, class Traits = typename std::char_traits<CharT>> [[nodiscard]]
264  static ScopeGuard guardStreamState(std::basic_ios<CharT, Traits>& stream)
265  {
266  const std::ios::fmtflags flags{stream.flags()};
267  const std::streamsize precision{stream.precision()};
268  const std::streamsize width{stream.width()};
269  const CharT fill{stream.fill()};
270 
271  return ScopeGuard([ =, &stream]() {
272  stream.flags(flags);
273  stream.precision(precision);
274  stream.width(width);
275  stream.fill(fill);
276  });
277  }
278 
298  [[nodiscard]] static ScopeGuard guardWorkingDirectory()
299  {
300  const std::string old{gSystem->GetWorkingDirectory()};
301  return ScopeGuard([old]() {gSystem->ChangeDirectory(old.c_str());});
302  }
303 
325  [[nodiscard]] static ScopeGuard guardWorkingDirectory(const std::string& newDirectory)
326  {
327  const std::string old{gSystem->GetWorkingDirectory()};
328  gSystem->ChangeDirectory(newDirectory.c_str());
329  return ScopeGuard([old]() {gSystem->ChangeDirectory(old.c_str());});
330  }
331 
354  [[nodiscard]] static ScopeGuard guardBatchMode(bool batchMode = true)
355  {
356  auto getBatchMode = []() {
357  return gROOT->IsBatch();
358  };
359 
360  auto setBatchMode = [](bool batchMode_) {
361  gROOT->SetBatch(batchMode_);
362  };
363 
364  return guardGetterSetter(getBatchMode, setBatchMode, batchMode);
365  }
366  };
368 }
Belle2::ScopeGuard::guardWorkingDirectory
static ScopeGuard guardWorkingDirectory()
Create a ScopeGuard of the current working directory.
Definition: ScopeGuard.h:306
Belle2::ScopeGuard
Simple ScopeGuard to execute a function at the end of the object lifetime.
Definition: ScopeGuard.h:46
Belle2::ScopeGuard::ScopeGuard
ScopeGuard(Callable &&f)
Construct a object with a callable function to be called on destruction.
Definition: ScopeGuard.h:54
Belle2::ScopeGuard::release
void release()
Release the guard without calling the cleanup function.
Definition: ScopeGuard.h:66
Belle2::ScopeGuard::guardBatchMode
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:362
Belle2::ScopeGuard::operator=
ScopeGuard & operator=(const ScopeGuard &)=delete
No assignment.
Belle2::ScopeGuard::guardFunctor
static ScopeGuard guardFunctor(Functor functor)
Create a ScopeGuard from a functor object with appropriately overloaded operator() calls to get and s...
Definition: ScopeGuard.h:198
Belle2::ScopeGuard::~ScopeGuard
~ScopeGuard()
Call function on destruct unless released has been called.
Definition: ScopeGuard.h:64
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::ScopeGuard::m_engaged
bool m_engaged
Indicate whether function should be called.
Definition: ScopeGuard.h:51
Belle2::ScopeGuard::guardDeletion
static ScopeGuard guardDeletion(T *&pointer)
Create a ScopeGuard to delete a raw pointer at the end of the scope.
Definition: ScopeGuard.h:249
Belle2::ScopeGuard::guardGetterSetter
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:147
Belle2::ScopeGuard::guardValue
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:86
Belle2::ScopeGuard::guardStreamState
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:272
Belle2::ScopeGuard::m_exitfunc
std::function< void()> m_exitfunc
Function to be called on exit.
Definition: ScopeGuard.h:49