diff options
Diffstat (limited to 'src/keeper.hpp')
-rw-r--r-- | src/keeper.hpp | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/keeper.hpp b/src/keeper.hpp new file mode 100644 index 0000000..2354c2e --- /dev/null +++ b/src/keeper.hpp | |||
@@ -0,0 +1,90 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include "uniquekey.hpp" | ||
4 | |||
5 | // forwards | ||
6 | class Linda; | ||
7 | enum class LookupMode; | ||
8 | class Universe; | ||
9 | |||
10 | DECLARE_UNIQUE_TYPE(KeeperState,lua_State*); | ||
11 | DECLARE_UNIQUE_TYPE(LindaLimit, int); | ||
12 | DECLARE_UNIQUE_TYPE(KeeperIndex, int); | ||
13 | |||
14 | // ################################################################################################# | ||
15 | |||
16 | struct Keeper | ||
17 | { | ||
18 | std::mutex mutex; | ||
19 | KeeperState K{ static_cast<lua_State*>(nullptr) }; | ||
20 | |||
21 | [[nodiscard]] static void* operator new[](size_t size_, Universe* U_) noexcept; | ||
22 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception | ||
23 | static void operator delete[](void* p_, Universe* U_); | ||
24 | |||
25 | |||
26 | ~Keeper() = default; | ||
27 | Keeper() = default; | ||
28 | // non-copyable, non-movable | ||
29 | Keeper(Keeper const&) = delete; | ||
30 | Keeper(Keeper const&&) = delete; | ||
31 | Keeper& operator=(Keeper const&) = delete; | ||
32 | Keeper& operator=(Keeper const&&) = delete; | ||
33 | |||
34 | [[nodiscard]] static int PushLindaStorage(Linda& linda_, DestState L_); | ||
35 | }; | ||
36 | |||
37 | // ################################################################################################# | ||
38 | |||
39 | struct Keepers | ||
40 | { | ||
41 | private: | ||
42 | struct DeleteKV | ||
43 | { | ||
44 | Universe* U{}; | ||
45 | size_t count{}; | ||
46 | void operator()(Keeper* k_) const; | ||
47 | }; | ||
48 | // can't use std::vector<Keeper> because Keeper contains a mutex, so we need a raw memory buffer | ||
49 | struct KV | ||
50 | { | ||
51 | std::unique_ptr<Keeper[], DeleteKV> keepers; | ||
52 | size_t nbKeepers{}; | ||
53 | }; | ||
54 | std::variant<std::monostate, Keeper, KV> keeper_array; | ||
55 | std::atomic_flag isClosing; | ||
56 | |||
57 | public: | ||
58 | int gc_threshold{ 0 }; | ||
59 | |||
60 | public: | ||
61 | // can only be instanced as a data member | ||
62 | static void* operator new(size_t size_) = delete; | ||
63 | |||
64 | Keepers() = default; | ||
65 | void close(); | ||
66 | [[nodiscard]] Keeper* getKeeper(KeeperIndex idx_); | ||
67 | [[nodiscard]] int getNbKeepers() const; | ||
68 | void initialize(Universe& U_, lua_State* L_, size_t nbKeepers_, int gc_threshold_); | ||
69 | }; | ||
70 | |||
71 | // ################################################################################################# | ||
72 | |||
73 | // xxh64 of string "kNilSentinel" generated at https://www.pelock.com/products/hash-calculator | ||
74 | static constexpr UniqueKey kNilSentinel{ 0xC457D4EDDB05B5E4ull, "lanes.null" }; | ||
75 | |||
76 | using keeper_api_t = lua_CFunction; | ||
77 | #define KEEPER_API(_op) keepercall_##_op | ||
78 | |||
79 | // lua_Cfunctions to run inside a keeper state | ||
80 | [[nodiscard]] int keepercall_count(lua_State* L_); | ||
81 | [[nodiscard]] int keepercall_destruct(lua_State* L_); | ||
82 | [[nodiscard]] int keepercall_get(lua_State* L_); | ||
83 | [[nodiscard]] int keepercall_limit(lua_State* L_); | ||
84 | [[nodiscard]] int keepercall_receive(lua_State* L_); | ||
85 | [[nodiscard]] int keepercall_receive_batched(lua_State* L_); | ||
86 | [[nodiscard]] int keepercall_send(lua_State* L_); | ||
87 | [[nodiscard]] int keepercall_set(lua_State* L_); | ||
88 | |||
89 | DECLARE_UNIQUE_TYPE(KeeperCallResult, std::optional<int>); | ||
90 | [[nodiscard]] KeeperCallResult keeper_call(KeeperState K_, keeper_api_t func_, lua_State* L_, Linda* linda_, StackIndex starting_index_); | ||