summaryrefslogtreecommitdiff
path: root/asl/base/defer.hpp
blob: 122312a9c7137dc4dd4e9238a5d31bc7bb03eea7 (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
#pragma once

#include "asl/base/utility.hpp"
#include "asl/base/functional.hpp"

namespace asl
{

template<invocable Callback>
class DeferCallback
{
    Callback m_callback;
    bool     m_moved = false;

public:
    template<typename T>
    explicit DeferCallback(T&& callback) : m_callback(ASL_FWD(callback))
    {
    }

    ASL_DELETE_COPY(DeferCallback);

    DeferCallback(DeferCallback&& other) :
        m_callback(ASL_MOVE(other.m_callback)), m_moved(exchange(other.m_moved, true))
    {
    }

    DeferCallback& operator=(DeferCallback&&) = delete;

    ~DeferCallback()
    {
        if (!m_moved) { invoke(m_callback); }
    }
};

struct DeferFactory
{
    template<invocable Callback>
    DeferCallback<Callback> operator<<(Callback&& callback) const
    {
        return DeferCallback<Callback>(ASL_FWD(callback));
    }
};

} // namespace asl

#define ASL_DEFER auto ASL_CONCAT(_defer_, __COUNTER__) = ::asl::DeferFactory{} <<