Post by jseighPost by jseightss_create lets you dynamically create thread local storage.
thread_local is static. Gets resolved at ld time. Doesn't
work too well if you want a per object instance of thread
local storage. Something like that in C++?
Joe Seigh
I figured something out so all good I think.
So basically just declare a thread local array. It will have
fixed size and you will have to manage allocation of array
slots and dtors and stuff. E.g.
thread_local void * x2[20];
Accessing a slot value, if you inline it with a uint64_t
key on x86 will get you something like
with %rax containing the index, i.e. the key,
which will beat calling tss_get which calls
pthread_getspecific.
Interesting. I need to check the call stack of accessing a thread_local
pointer. The g_per_thread wrt my recent code's ct_foo function that is
called from ct_thread:
void
ct_foo()
{
// Okay, what about this shit!
{
std::unique_lock<std::mutex>
lock(g_per_thread->m_shared.m_cout_lock);
std::cout << "ct_foo(" << g_per_thread->m_id << ")" << std::endl;
}
}
Full code for reference:
_______________________________________
#include <iostream>
#include <functional>
#include <thread>
#include <atomic>
#include <mutex>
#define CT_THREADS 5
struct ct_shared
{
std::mutex m_cout_lock;
};
struct ct_per_thread
{
ct_shared& m_shared;
unsigned long m_id;
ct_per_thread(
ct_shared& shared,
unsigned long id
): m_shared(shared),
m_id(id)
{
{
std::unique_lock<std::mutex> lock(m_shared.m_cout_lock);
std::cout << "ct_per_thread::ct_per_thread(" << m_id << ")"
<< std::endl;
}
}
~ct_per_thread()
{
{
std::unique_lock<std::mutex> lock(m_shared.m_cout_lock);
std::cout << "ct_per_thread::~ct_per_thread(" << m_id <<
")" << std::endl;
}
}
};
thread_local ct_per_thread* g_per_thread = nullptr;
void
ct_foo()
{
// Okay, what about this shit!
{
std::unique_lock<std::mutex>
lock(g_per_thread->m_shared.m_cout_lock);
std::cout << "ct_foo(" << g_per_thread->m_id << ")" << std::endl;
}
}
void
ct_thread(
ct_shared& shared,
unsigned long id
) {
{
thread_local ct_per_thread self(shared, id);
g_per_thread = &self;
}
ct_foo();
}
int
main()
{
std::cout << "ct_plot_pre_alpha... Testing 123! :^)\n\n";
std::cout << "_____________________________________________" <<
std::endl;
{
ct_shared shared;
{
std::thread threads[CT_THREADS];
std::cout << "launching " << CT_THREADS << " threads..." <<
std::endl;
for (unsigned long i = 0; i < CT_THREADS; ++i)
{
threads[i] = std::thread(ct_thread, std::ref(shared), i);
}
for (unsigned long i = 0; i < CT_THREADS; ++i)
{
threads[i].join();
}
}
}
std::cout << "_____________________________________________\n";
std::cout << "complete!\n";
return 0;
}
_______________________________________