neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
i_shared_thread_local.hpp
Go to the documentation of this file.
1// i_shared_thread_local.hpp
2/*
3 * Copyright (c) 2023 Leigh Johnston.
4 *
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * * Neither the name of Leigh Johnston nor the names of any
19 * other contributors to this software may be used to endorse or
20 * promote products derived from this software without specific prior
21 * written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
24 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*/
35
36#pragma once
37
38#include <neolib/neolib.hpp>
40
41namespace neolib
42{
52 {
53 public:
55 {
56 void* memory;
58 };
59 public:
60 virtual result_type allocate_or_get(char const* aFullyQualifiedVariableName, std::size_t aVariableSize, void(*aDeleter)(void*)) = 0;
61 public:
62 template <typename T>
63 result_type allocate_or_get(char const* aFullyQualifiedVariableName, void(*aDeleter)(void*))
64 {
65 return allocate_or_get(aFullyQualifiedVariableName, sizeof(T), aDeleter);
66 }
67 public:
68 static uuid const& iid() { static uuid const sIid{ 0x975e11be, 0xd285, 0x4704, 0x9eef, { 0x28, 0xfb, 0x6b, 0x5e, 0xe0, 0x76 } }; return sIid; }
69 };
70
71 #define shared_thread_local_impl(VariableType, VariableScope, VariableName, InitialValue) \
72 thread_local auto const neolib_PartialResult_##VariableName = \
73 neolib::service<neolib::i_shared_thread_local>().allocate_or_get<VariableType>( \
74 STRING(VariableScope) "::" STRING(VariableName), \
75 [](void* aMemory) { using VariableTypeAlias = VariableType; static_cast<VariableType*>(aMemory)->~VariableTypeAlias(); }); \
76 auto const& neolib_CapturablePartialResult_##VariableName = neolib_PartialResult_##VariableName; \
77 thread_local auto& VariableName = [&neolib_CapturablePartialResult_##VariableName]() -> VariableType& \
78 { \
79 if (neolib_CapturablePartialResult_##VariableName.initializationRequired) \
80 { \
81 new (static_cast<VariableType*>(neolib_CapturablePartialResult_##VariableName.memory)) VariableType{ InitialValue }; \
82 } \
83 return *static_cast<VariableType*>(neolib_CapturablePartialResult_##VariableName.memory); \
84 }();
85
86 #define shared_thread_local_class_impl(VariableType, ClassType, VariableScope, VariableName, InitialValue) \
87 thread_local auto const neolib_PartialResult_##VariableName = \
88 neolib::service<neolib::i_shared_thread_local>().allocate_or_get<VariableType>( \
89 (std::string{ typeid(ClassType).name() } + "::" STRING(VariableScope) "::" STRING(VariableName)).c_str(), \
90 [](void* aMemory) { using neolib_VariableTypeAlias = VariableType; static_cast<VariableType*>(aMemory)->~neolib_VariableTypeAlias(); }); \
91 auto const& neolib_CapturablePartialResult_##VariableName = neolib_PartialResult_##VariableName; \
92 thread_local auto& VariableName = [&neolib_CapturablePartialResult_##VariableName]() -> VariableType& \
93 { \
94 if (neolib_CapturablePartialResult_##VariableName.initializationRequired) \
95 { \
96 new (static_cast<VariableType*>(neolib_CapturablePartialResult_##VariableName.memory)) VariableType{ InitialValue }; \
97 } \
98 return *static_cast<VariableType*>(neolib_CapturablePartialResult_##VariableName.memory); \
99 }();
100
101 #define shared_thread_local(VariableType, VariableScope, VariableName, ...) \
102 shared_thread_local_impl(VariableType, VariableScope, VariableName, __VA_ARGS__)
103
104 #define shared_thread_local_class(VariableType, ClassType, VariableScope, VariableName, ...) \
105 shared_thread_local_class_impl(VariableType, ClassType, VariableScope, VariableName, __VA_ARGS__)
106}
Shared thread local service.
result_type allocate_or_get(char const *aFullyQualifiedVariableName, void(*aDeleter)(void *))
virtual result_type allocate_or_get(char const *aFullyQualifiedVariableName, std::size_t aVariableSize, void(*aDeleter)(void *))=0