diff options
Diffstat (limited to 'src/linda.h')
-rw-r--r-- | src/linda.h | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/src/linda.h b/src/linda.h new file mode 100644 index 0000000..559ef24 --- /dev/null +++ b/src/linda.h | |||
@@ -0,0 +1,70 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include "cancel.h" | ||
4 | #include "deep.h" | ||
5 | #include "keeper.h" | ||
6 | #include "universe.h" | ||
7 | |||
8 | #include <array> | ||
9 | #include <condition_variable> | ||
10 | #include <variant> | ||
11 | |||
12 | struct Keeper; | ||
13 | |||
14 | // ################################################################################################# | ||
15 | |||
16 | using LindaGroup = Unique<int>; | ||
17 | |||
18 | class Linda : public DeepPrelude // Deep userdata MUST start with this header | ||
19 | { | ||
20 | private: | ||
21 | |||
22 | static constexpr size_t kEmbeddedNameLength = 24; | ||
23 | using EmbeddedName = std::array<char, kEmbeddedNameLength>; | ||
24 | struct AllocatedName | ||
25 | { | ||
26 | size_t len{ 0 }; | ||
27 | char* name{ nullptr }; | ||
28 | }; | ||
29 | // depending on the name length, it is either embedded inside the Linda, or allocated separately | ||
30 | std::variant<AllocatedName, EmbeddedName> m_name; | ||
31 | |||
32 | public: | ||
33 | |||
34 | std::condition_variable m_read_happened; | ||
35 | std::condition_variable m_write_happened; | ||
36 | Universe* const U{ nullptr }; // the universe this linda belongs to | ||
37 | int const m_keeper_index{ -1 }; // the keeper associated to this linda | ||
38 | CancelRequest simulate_cancel{ CancelRequest::None }; | ||
39 | |||
40 | public: | ||
41 | |||
42 | // a fifo full userdata has one uservalue, the table that holds the actual fifo contents | ||
43 | [[nodiscard]] static void* operator new(size_t size_, Universe* U_) noexcept { return U_->internal_allocator.alloc(size_); } | ||
44 | // always embedded somewhere else or "in-place constructed" as a full userdata | ||
45 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception | ||
46 | static void operator delete(void* p_, Universe* U_) { U_->internal_allocator.free(p_, sizeof(Linda)); } | ||
47 | // this one is for us, to make sure memory is freed by the correct allocator | ||
48 | static void operator delete(void* p_) { static_cast<Linda*>(p_)->U->internal_allocator.free(p_, sizeof(Linda)); } | ||
49 | |||
50 | ~Linda(); | ||
51 | Linda(Universe* U_, LindaGroup group_, char const* name_, size_t len_); | ||
52 | Linda() = delete; | ||
53 | Linda(Linda const&) = delete; | ||
54 | Linda(Linda const&&) = delete; | ||
55 | Linda& operator=(Linda const&) = delete; | ||
56 | Linda& operator=(Linda const&&) = delete; | ||
57 | |||
58 | static int ProtectedCall(lua_State* L, lua_CFunction f_); | ||
59 | |||
60 | private : | ||
61 | |||
62 | void setName(char const* name_, size_t len_); | ||
63 | |||
64 | public: | ||
65 | |||
66 | [[nodiscard]] char const* getName() const; | ||
67 | [[nodiscard]] Keeper* whichKeeper() const { return U->keepers->nb_keepers ? &U->keepers->keeper_array[m_keeper_index] : nullptr; } | ||
68 | [[nodiscard]] Keeper* acquireKeeper() const; | ||
69 | void releaseKeeper(Keeper* keeper_) const; | ||
70 | }; | ||