aboutsummaryrefslogtreecommitdiff
path: root/include/cru/base/Guard.h
blob: 6b6cf851d3189545bbc86cbfc66754217bd4bdd6 (plain)
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
#pragma once

#include <cstdlib>
#include <functional>

namespace cru {
struct Guard {
  using ExitFunc = std::function<void()>;

  Guard() = default;
  explicit Guard(const ExitFunc& f) : on_exit(f) {}
  explicit Guard(ExitFunc&& f) : on_exit(std::move(f)) {}
  Guard(const Guard&) = delete;
  Guard(Guard&&) = default;
  Guard& operator=(const Guard&) = delete;
  Guard& operator=(Guard&&) = default;
  ~Guard() {
    if (on_exit) {
      on_exit();
    }
  }

  void Drop() { on_exit = {}; }

  ExitFunc on_exit;
};

template <typename T>
struct FreeLater {
  FreeLater(T* ptr) : ptr(ptr) {}
  ~FreeLater() { ::free(ptr); }

  FreeLater(const FreeLater& other) = delete;
  FreeLater& operator=(const FreeLater& other) = delete;

  FreeLater(FreeLater&& other) : ptr(other.ptr) { other.ptr = nullptr; }
  FreeLater& operator=(FreeLater&& other) {
    if (this != &other) {
      ::free(ptr);
      ptr = other.ptr;
      other.ptr = nullptr;
    }
    return *this;
  }

  operator T*() const { return ptr; }
  T* operator->() { return ptr; }

  T* ptr;
};

}  // namespace cru