Skip to content

Commit cc3ee37

Browse files
authored
Merge pull request #1667 from reOiL/thread_local_wrap
Added thread local wrapper
2 parents 00d8f2a + 1508d81 commit cc3ee37

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+12687
-12581
lines changed

examples/profile/test_profile.cpp

+23-28
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,9 @@ struct EsFunctionAnnotation : FunctionAnnotation {
203203
};
204204

205205
void * getComponentData ( const string & name ) {
206-
if (name == "pos") return g_pos.data();
207-
else if (name == "vel") return g_vel.data();
208-
else if (name == "velBoxed") return g_velBoxed.data();
206+
if (name == "pos") return g_pos->data();
207+
else if (name == "vel") return g_vel->data();
208+
else if (name == "velBoxed") return g_velBoxed->data();
209209
else return nullptr;
210210
}
211211

@@ -359,7 +359,7 @@ void aotEsRunBlock ( TextWriter & ss, EsAttributeTable * table, const vector<EsC
359359
});
360360
if ( a ) ss << ",";
361361
if ( it != components.end() ) {
362-
ss << "g_" << table->attributes[a].name << "[i]";
362+
ss << "(*g_" << table->attributes[a].name << ")[i]";
363363
} else {
364364
vec4f def = table->attributes[a].def;
365365
const char * def_s = table->attributes[a].def_s;
@@ -403,13 +403,13 @@ struct QueryEsFunctionAnnotation : FunctionAnnotation {
403403
auto mb = static_pointer_cast<ExprMakeBlock>(call->arguments[0]);
404404
auto closure = static_pointer_cast<ExprBlock>(mb->block);
405405
EsAttributeTable * table = (EsAttributeTable *) closure->annotationData;
406-
return aotEsRunBlockName(table, g_components);
406+
return aotEsRunBlockName(table, *g_components);
407407
}
408408
virtual void aotPrefix ( TextWriter & ss, ExprCallFunc * call ) override {
409409
auto mb = static_pointer_cast<ExprMakeBlock>(call->arguments[0]);
410410
auto closure = static_pointer_cast<ExprBlock>(mb->block);
411411
EsAttributeTable * table = (EsAttributeTable *) closure->annotationData;
412-
aotEsRunBlock(ss, table, g_components);
412+
aotEsRunBlock(ss, table, *g_components);
413413
}
414414
virtual bool verifyCall ( ExprCallFunc * call, const AnnotationArgumentList &, const AnnotationArgumentList &, string & err ) override {
415415
auto brt = call->arguments[0]->type->firstType;
@@ -441,41 +441,36 @@ struct QueryEsFunctionAnnotation : FunctionAnnotation {
441441
}
442442
};
443443

444-
DAS_THREAD_LOCAL(vector<float3>) g_pos;
445-
DAS_THREAD_LOCAL(vector<float3>) g_vel;
446-
DAS_THREAD_LOCAL(vector<float3 *>) g_velBoxed;
447-
DAS_THREAD_LOCAL(vector<EsComponent>) g_components;
448-
449444
template <typename TT>
450445
void releaseVec(vector<TT>& vec) {
451446
vector<TT> temp;
452447
vec.swap(temp);
453448
}
454449

455450
void releaseEsComponents() {
456-
releaseVec(g_pos);
457-
releaseVec(g_vel);
458-
releaseVec(g_velBoxed);
451+
releaseVec(*g_pos);
452+
releaseVec(*g_vel);
453+
releaseVec(*g_velBoxed);
459454
}
460455

461456
void initEsComponents() {
462457
// build components
463-
g_pos.resize(g_total);
464-
g_vel.resize(g_total);
465-
g_velBoxed.resize(g_total);
458+
g_pos->resize(g_total);
459+
g_vel->resize(g_total);
460+
g_velBoxed->resize(g_total);
466461
float f = 1.0f;
467462
for (int i = 0; i != g_total; ++i, ++f) {
468-
g_pos[i] = { f, f + 1, f + 2 };
469-
g_vel[i] = { 1.0f, 2.0f, 3.0f };
470-
g_velBoxed[i] = &g_vel[i];
463+
(*g_pos)[i] = { f, f + 1, f + 2 };
464+
(*g_vel)[i] = { 1.0f, 2.0f, 3.0f };
465+
(*g_velBoxed)[i] = &(*g_vel)[i];
471466
}
472467
}
473468

474469
void initEsComponentsTable() {
475-
g_components.clear();
476-
g_components.emplace_back("pos", sizeof(float3), sizeof(float3), false);
477-
g_components.emplace_back("vel", sizeof(float3), sizeof(float3), false);
478-
g_components.emplace_back("velBoxed", sizeof(float3), sizeof(float3 *), true );
470+
g_components->clear();
471+
g_components->emplace_back("pos", sizeof(float3), sizeof(float3), false);
472+
g_components->emplace_back("vel", sizeof(float3), sizeof(float3), false);
473+
g_components->emplace_back("velBoxed", sizeof(float3), sizeof(float3 *), true );
479474
}
480475

481476
void verifyEsComponents(Context * context, LineInfoArg * at) {
@@ -488,9 +483,9 @@ void verifyEsComponents(Context * context, LineInfoArg * at) {
488483
npos.x = apos.x + avel.x * t;
489484
npos.y = apos.y + avel.y * t;
490485
npos.z = apos.z + avel.z * t;
491-
if ( g_pos[i].x!=npos.x || g_pos[i].y!=npos.y || g_pos[i].z!=npos.z ) {
486+
if ( (*g_pos)[i].x!=npos.x || (*g_pos)[i].y!=npos.y || (*g_pos)[i].z!=npos.z ) {
492487
TextWriter twrt;
493-
twrt << "g_pos[" << i << "] (" << g_pos[i] << ") != npos (" << npos << ")\n";
488+
twrt << "g_pos[" << i << "] (" << (*g_pos)[i] << ") != npos (" << npos << ")\n";
494489
context->throw_error_at(at, "verifyEsComponents failed, %s\n", twrt.str().c_str());
495490
}
496491
}
@@ -505,14 +500,14 @@ void testEsUpdate ( char * pass, Context * ctx, LineInfoArg * at ) {
505500
}
506501
for ( auto & tab : EsGroupData::THAT->g_esPassTable ) {
507502
if ( tab->pass==pass ) {
508-
EsRunPass(*ctx, *tab, g_components, g_total);
503+
EsRunPass(*ctx, *tab, *g_components, g_total);
509504
}
510505
}
511506
}
512507

513508
uint32_t queryEs (const Block & block, Context * context, LineInfoArg * at) {
514509
das_stack_prologue guard(context,sizeof(Prologue), "queryEs " DAS_FILE_LINE);
515-
return EsRunBlock(*context, at, block, g_components, g_total);
510+
return EsRunBlock(*context, at, block, *g_components, g_total);
516511
}
517512

518513
#if DAS_USE_EASTL

examples/profile/test_profile.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,10 @@ struct EsComponent {
101101
};
102102

103103
constexpr int g_total = 100000;
104-
extern DAS_THREAD_LOCAL(das::vector<das::float3>) g_pos;
105-
extern DAS_THREAD_LOCAL(das::vector<das::float3>) g_vel;
106-
extern DAS_THREAD_LOCAL(das::vector<das::float3 *>) g_velBoxed;
107-
extern DAS_THREAD_LOCAL(das::vector<EsComponent>) g_components;
104+
inline DAS_THREAD_LOCAL(das::vector<das::float3>) g_pos;
105+
inline DAS_THREAD_LOCAL(das::vector<das::float3>) g_vel;
106+
inline DAS_THREAD_LOCAL(das::vector<das::float3 *>) g_velBoxed;
107+
inline DAS_THREAD_LOCAL(das::vector<EsComponent>) g_components;
108108

109109
void initEsComponents();
110110
void initEsComponentsTable ();

include/daScript/ast/ast.h

+8-8
Original file line numberDiff line numberDiff line change
@@ -1757,8 +1757,8 @@ namespace das
17571757
AstSerializer * serializer_write = nullptr;
17581758
DebugAgentInstance g_threadLocalDebugAgent;
17591759
uint64_t dataWalkerStringLimit = 0;
1760-
static DAS_THREAD_LOCAL(daScriptEnvironment *) bound;
1761-
static DAS_THREAD_LOCAL(daScriptEnvironment *) owned;
1760+
inline static DAS_THREAD_LOCAL(daScriptEnvironment *) bound;
1761+
inline static DAS_THREAD_LOCAL(daScriptEnvironment *) owned;
17621762
static void ensure();
17631763
};
17641764

@@ -1767,15 +1767,15 @@ namespace das
17671767
das::daScriptEnvironment *initialOwned;
17681768

17691769
daScriptEnvironmentGuard(das::daScriptEnvironment *bound = nullptr, das::daScriptEnvironment *owned = nullptr) {
1770-
initialBound = das::daScriptEnvironment::bound;
1771-
initialOwned = das::daScriptEnvironment::owned;
1772-
das::daScriptEnvironment::bound = bound;
1773-
das::daScriptEnvironment::owned = owned;
1770+
initialBound = *das::daScriptEnvironment::bound;
1771+
initialOwned = *das::daScriptEnvironment::owned;
1772+
*das::daScriptEnvironment::bound = bound;
1773+
*das::daScriptEnvironment::owned = owned;
17741774
}
17751775

17761776
~daScriptEnvironmentGuard() {
1777-
das::daScriptEnvironment::bound = initialBound;
1778-
das::daScriptEnvironment::owned = initialOwned;
1777+
*das::daScriptEnvironment::bound = initialBound;
1778+
*das::daScriptEnvironment::owned = initialOwned;
17791779
}
17801780
};
17811781
}

include/daScript/ast/ast_serializer.h

+1-13
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "daScript/ast/ast_expressions.h"
44
#include "daScript/ast/ast_handle.h"
55
#include "daScript/ast/ast.h"
6+
#include "daScript/misc/hash.h"
67
#include <optional>
78
#include <utility>
89

@@ -12,19 +13,6 @@
1213
#endif
1314

1415
namespace das {
15-
16-
// use FNV32 hash for tags. it's fast and good enough for our purposes
17-
constexpr uint32_t hash_tag(const char* block) {
18-
constexpr uint32_t FNV_offset_basis = 2166136261u;
19-
constexpr uint32_t FNV_prime = 16777619u;
20-
uint32_t h = FNV_offset_basis;
21-
while (*block) {
22-
h ^= uint8_t(*block++);
23-
h *= FNV_prime;
24-
}
25-
return h;
26-
}
27-
2816
struct SerializationStorage {
2917
vector<uint8_t> buffer;
3018
size_t bufferPos = 0;

include/daScript/daScriptModule.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33

44
namespace das
55
{
6-
extern DAS_THREAD_LOCAL(unsigned) ModuleKarma;
6+
inline DAS_THREAD_LOCAL(unsigned) ModuleKarma;
77
class Module;
88
};
99

1010
#define NEED_MODULE(ClassName) \
1111
extern das::Module * register_##ClassName (); \
12-
das::ModuleKarma += unsigned(intptr_t(register_##ClassName()));
12+
*das::ModuleKarma += unsigned(intptr_t(register_##ClassName()));
1313

1414
#define NEED_ALL_DEFAULT_MODULES \
1515
NEED_MODULE(Module_BuiltIn); \

include/daScript/misc/hash.h

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#pragma once
2+
#include <stdint.h>
3+
4+
namespace das {
5+
6+
// use FNV32 hash for tags. it's fast and good enough for our purposes
7+
constexpr uint32_t hash_tag(const char* block) {
8+
constexpr uint32_t FNV_offset_basis = 2166136261u;
9+
constexpr uint32_t FNV_prime = 16777619u;
10+
uint32_t h = FNV_offset_basis;
11+
while (*block) {
12+
h ^= uint8_t(*block++);
13+
h *= FNV_prime;
14+
}
15+
return h;
16+
}
17+
}

include/daScript/misc/macro.h

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#pragma once
2+
3+
4+
#define DAS_COMMENT(...)
5+
6+
#define DAS_STRINGIFY(x) #x
7+
#define DAS_TOSTRING(x) DAS_STRINGIFY(x)
8+
#define DAS_FILE_LINE_NAME(a,b) a " at line " DAS_TOSTRING(b)
9+
#define DAS_FILE_LINE DAS_FILE_LINE_NAME(__FILE__,__LINE__)

include/daScript/misc/platform.h

+28-1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@
8282
#include <stdint.h>
8383
#include <float.h>
8484
#include <daScript/das_config.h>
85+
#include <daScript/misc/hash.h>
86+
#include <daScript/misc/macro.h>
8587

8688
#if _TARGET_PC_MACOSX && __SSE__
8789
#define DAS_EVAL_ABI [[clang::vectorcall]]
@@ -380,8 +382,33 @@ inline size_t das_aligned_memsize(void * ptr){
380382
#define _msc_inline_bug __forceinline
381383
#endif
382384

385+
template<typename T, unsigned long long TAG>
386+
class DasThreadLocal final
387+
{
388+
public:
389+
using SelfType = DasThreadLocal<T, TAG>;
390+
391+
inline DasThreadLocal()
392+
{
393+
if (initCounter++)
394+
throw std::logic_error("Type with tag is already used, pls change tag!");
395+
}
396+
397+
DasThreadLocal(const SelfType & other) = delete;
398+
DasThreadLocal(SelfType&& other) = delete;
399+
DasThreadLocal & operator=(const SelfType & other) = delete;
400+
DasThreadLocal & operator=(SelfType && other) = delete;
401+
402+
inline T & operator *() noexcept { return value_; }
403+
inline T * operator->() noexcept { return &value_; }
404+
405+
private:
406+
inline static thread_local T value_{};
407+
inline static int initCounter = 0;
408+
};
409+
383410
#ifndef DAS_THREAD_LOCAL
384-
#define DAS_THREAD_LOCAL(X) thread_local X
411+
#define DAS_THREAD_LOCAL(X) DasThreadLocal<X, das::hash_tag(DAS_FILE_LINE)>
385412
#endif
386413

387414
#ifndef DAS_AOT_INLINE_LAMBDA

include/daScript/simulate/aot.h

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include "daScript/misc/callable.h"
4+
#include "daScript/misc/macro.h"
45
#include "daScript/simulate/runtime_profile.h"
56
#include "daScript/simulate/debug_print.h"
67
#include "daScript/simulate/sim_policy.h"
@@ -31,13 +32,6 @@ namespace das {
3132

3233
#define DAS_MAKE_ANNOTATION(name) ((TypeAnnotation*)(intptr_t(name)|1))
3334

34-
#define DAS_COMMENT(...)
35-
36-
#define DAS_STRINGIFY(x) #x
37-
#define DAS_TOSTRING(x) DAS_STRINGIFY(x)
38-
#define DAS_FILE_LINE_NAME(a,b) a " at line " DAS_TOSTRING(b)
39-
#define DAS_FILE_LINE DAS_FILE_LINE_NAME(__FILE__,__LINE__)
40-
4135
void das_debug ( Context * context, TypeInfo * typeInfo, const char * FILE, int LINE, vec4f res, const char * message = nullptr );
4236

4337
#if (!defined(DAS_ENABLE_EXCEPTIONS)) || (!DAS_ENABLE_EXCEPTIONS)

include/daScript/simulate/simulate.h

+6-6
Original file line numberDiff line numberDiff line change
@@ -898,19 +898,19 @@ namespace das
898898

899899
class SharedStackGuard {
900900
public:
901-
static DAS_THREAD_LOCAL(StackAllocator *) lastContextStack;
901+
inline static DAS_THREAD_LOCAL(StackAllocator *) lastContextStack;
902902
SharedStackGuard() = delete;
903903
SharedStackGuard(const SharedStackGuard &) = delete;
904904
SharedStackGuard & operator = (const SharedStackGuard &) = delete;
905905
__forceinline SharedStackGuard(Context & currentContext, StackAllocator & shared_stack) : savedStack(0) {
906906
savedStack.copy(currentContext.stack);
907-
currentContext.stack.copy(lastContextStack ? *lastContextStack : shared_stack);
908-
saveLastContextStack = lastContextStack;
909-
lastContextStack = &currentContext.stack;
907+
currentContext.stack.copy(*lastContextStack ? **lastContextStack : shared_stack);
908+
saveLastContextStack = *lastContextStack;
909+
*lastContextStack = &currentContext.stack;
910910
}
911911
__forceinline ~SharedStackGuard() {
912-
lastContextStack->copy(savedStack);
913-
lastContextStack = saveLastContextStack;
912+
(*lastContextStack)->copy(savedStack);
913+
*lastContextStack = saveLastContextStack;
914914
savedStack.letGo();
915915
}
916916
protected:

include/daScript/simulate/simulate_fusion.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ namespace das {
3131
typedef unique_ptr<FusionPoint> FusionPointPtr;
3232

3333
typedef das_hash_map<string,vector<FusionPointPtr>> FusionEngine; // note: unordered map for thread safety
34-
extern DAS_THREAD_LOCAL(unique_ptr<FusionEngine>) g_fusionEngine;
34+
// TODO: at some point we should share fusion engine
35+
inline DAS_THREAD_LOCAL(unique_ptr<FusionEngine>) g_fusionEngine;
3536

3637
const char * getSimSourceName(SimSourceType st);
3738

modules/dasAudio/src/dasAudio.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,8 @@ void data_callback(ma_device*, void* pOutput, const void*, ma_uint32 frameCount)
219219
buffer.size = buffer.capacity = frameCount * g_channels;
220220
buffer.lock = 1;
221221
lock_guard<recursive_mutex> guard(*g_mixer_context->contextMutex);
222-
auto saved = daScriptEnvironment::bound;
223-
daScriptEnvironment::bound = g_mixer_env;
222+
auto saved = *daScriptEnvironment::bound;
223+
*daScriptEnvironment::bound = g_mixer_env;
224224
g_mixer_context->restart();
225225
g_mixer_context.get()->runWithCatch([&](){
226226
das_invoke_function<void>::invoke<Array&,int32_t,int32_t>(g_mixer_context.get(),nullptr,g_mixer_function,buffer,g_channels,g_rate,fdt);
@@ -229,7 +229,7 @@ void data_callback(ma_device*, void* pOutput, const void*, ma_uint32 frameCount)
229229
if ( const char* exp = g_mixer_context->getException() ) {
230230
g_mixer_context->to_err(&g_mixer_context->exceptionAt, exp);
231231
}
232-
daScriptEnvironment::bound = saved;
232+
*daScriptEnvironment::bound = saved;
233233
}
234234

235235
Context & dasAudio_mixerContext ( Context * context, LineInfoArg * at ) {
@@ -258,7 +258,7 @@ bool dasAudio_init ( TFunc<void,TTemporary<TArray<float>>,int32_t,int32_t,float>
258258
}
259259
g_mixer_context.reset(get_clone_context(&context,uint32_t(ContextCategory::audio_context)));
260260
g_mixer_function = mixer;
261-
g_mixer_env = daScriptEnvironment::bound;
261+
g_mixer_env = *daScriptEnvironment::bound;
262262
if ( ma_device_start(&g_device) != MA_SUCCESS ) {
263263
ma_device_uninit(&g_device);
264264
g_mixer_context.reset();

src/ast/ast.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,15 @@ namespace das {
5757
DAS_THREAD_LOCAL(unique_ptr<AotLibrary>) g_AOT_lib;
5858

5959
AotLibrary & getGlobalAotLibrary() {
60-
if ( !g_AOT_lib ) {
61-
g_AOT_lib = make_unique<AotLibrary>();
62-
AotListBase::registerAot(*g_AOT_lib);
60+
if ( !*g_AOT_lib ) {
61+
*g_AOT_lib = make_unique<AotLibrary>();
62+
AotListBase::registerAot(**g_AOT_lib);
6363
}
64-
return *g_AOT_lib;
64+
return **g_AOT_lib;
6565
}
6666

6767
void clearGlobalAotLibrary() {
68-
g_AOT_lib.reset();
68+
g_AOT_lib->reset();
6969
}
7070

7171
// annotations

0 commit comments

Comments
 (0)