File: scope_exit.h

package info (click to toggle)
dolphin-emu 2512%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 76,328 kB
  • sloc: cpp: 499,023; ansic: 119,674; python: 6,547; sh: 2,338; makefile: 1,093; asm: 726; pascal: 257; javascript: 183; perl: 97; objc: 75; xml: 30
file content (77 lines) | stat: -rw-r--r-- 1,825 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/**
 * \file libipc/scope_exit.h
 * \author mutouyun (orz@orzz.org)
 * \brief Execute guard function when the enclosing scope exits.
 */
#pragma once

#include <utility>      // std::forward, std::move
#include <functional>   // std::function
#include <type_traits>

#include "libipc/imp/detect_plat.h"

namespace ipc {

template <typename F = std::function<void()>>
class scope_exit {
  F destructor_;
  mutable bool released_;

public:
  template <typename G>
  explicit scope_exit(G &&destructor) noexcept
    : destructor_(std::forward<G>(destructor))
    , released_  (false) {}

  scope_exit(scope_exit &&other) noexcept
    : destructor_(std::move(other.destructor_))
    , released_  (std::exchange(other.released_, true)) /*release rhs*/ {}

  scope_exit &operator=(scope_exit &&other) noexcept {
    destructor_ = std::move(other.destructor_);
    released_   = std::exchange(other.released_, true);
    return *this;
  }

  ~scope_exit() noexcept {
    if (!released_) destructor_();
  }

  void release() const noexcept {
    released_ = true;
  }

  void do_exit() noexcept {
    if (released_) return;
    destructor_();
    released_ = true;
  }

  void swap(scope_exit &other) noexcept {
    std::swap(destructor_, other.destructor_);
    std::swap(released_  , other.released_);
  }
};

/// \brief Creates a scope_exit object.
template <typename F>
auto make_scope_exit(F &&destructor) noexcept {
  return scope_exit<std::decay_t<F>>(std::forward<F>(destructor));
}

namespace detail_scope_exit {

struct scope_exit_helper {
  template <typename F>
  auto operator=(F &&f) const noexcept {
    return make_scope_exit(std::forward<F>(f));
  }
};

} // namespace detail_scope_exit

#define LIBIPC_SCOPE_EXIT($VAL) \
  LIBIPC_UNUSED auto $VAL = ::ipc::detail_scope_exit::scope_exit_helper{}

} // namespace ipc