-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtask_ref.hpp
81 lines (57 loc) · 1.33 KB
/
task_ref.hpp
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
78
79
//
// Author Janos Meny (on 10/7/19). Email janos.meny@googlemail.com.
//
#pragma once
#include "generate_vtable.hpp"
#include <cstdint>
#include <algorithm>
template<class L>
class SmallTaskRef
{
public:
SmallTaskRef() = default;
template<class F>
explicit SmallTaskRef(F& f)
{
using I = mp_find<L, F>;
using S = mp_size<L>;
static_assert(I() < S());
set(std::addressof(f), I());
}
auto execute() const
{
return ptrs_[index()](ptr());
}
private:
[[nodiscard]] void* ptr() const {
return reinterpret_cast<void*>(data_ & ((1ull << 48ull) - 1ull));
}
[[nodiscard]] std::uint16_t index() const {
return data_ >> 48ull;
}
void set(void* p, std::uint16_t v) {
auto ip = reinterpret_cast<std::uintptr_t>(p);
assert(!(ip >> 48ull));
ip |= static_cast<std::uintptr_t>(v) << 48ull;
data_ = ip;
}
static constexpr auto ptrs_ = initPtrs<L>();
std::uintptr_t data_;
};
class TaskRef
{
public:
TaskRef() = default;
template<class F>
explicit TaskRef(F& f) : f_(std::addressof(f))
{
caller_ = +[](void* p){return (*reinterpret_cast<F*>(p)).execute();};
}
auto execute() const
{
caller_(f_);
}
private:
void (*caller_)(void*);
void* f_;
};