bshoshany/thread-pool

[REQ] Resource Binding

poor1017 opened this issue · 9 comments

Describe the new feature

Can we support binding a resource to a thread?

Code example

BS::thread_pool pool(12);
for (size_t i = 0; i < 12; ++i) {
    bool ret = pool.attach_resource(int thread_id, Resource *rsrc);
}
v1993 commented

I think a better solution would be to pass a function that takes thread id as a parameter to thread_pool constructor, then store relevant resources in thread_local variables. Such constructor will block until all thread initialization calls are complete to make addressing locals in caller safe. So your example becomes

constexpr auto thread_count = 12;
std::array<Resource, thread_count> resource_array;
thread_local Resource* thread_resource;
...
BS::thread_pool pool{thread_count, [&resource_array](int thread_id) {
	thread_resource = &resource_array[thread_id];
}};

In this case locking is not needed, but you can make array local to caller function (which is likely a good idea) and move its members to thread local variable instead of storing a pointer. Or initialize resources directly in threads instead of caller, which makes sense for a lot of resource types.

A major reason I'd like to see this approach implemented instead of resource binding is because it allows to set up OpenGL context for every thread in pool, something that specifically requires running initialization code once per thread. Merely binding resource to thread would not allow this (well, you can make a thread local flag and check it at the beginning of every task, but just doing initialization properly is a much better idea). Plus this should be easier to implement than resource binding approach.

@v1993

That's a good approach. I will try.

Thank you!

v1993 commented

@poor1017 You may want to take a look at PR #105, I've implemented initialization function accepting thread id in pool as an optional argument to constructor and reset method, like outlined in example I've provided above.

Got it

Thanks for opening this issue, @poor1017! However, I'm not sure why this is needed. Let's continue the discussion in #105 - hopefully one of you can provide a more detailed explanation and some concrete code examples. Meanwhile I am closing this issue, as PR #105 is already addressing it.

@v1993 According to your approach, the variable thread_local should belong to each thread. So, where do I create this variable? Is it in the constructor of thread_pool? And, once I submit a task, where do I get this variable from during any execution?

@v1993 Or we can create a map from std::this_thread::get_id() to thread_id in thread_init_function?

@poor1017 you should wait for v4.0.0, to be released soon, which will implement thread initialization functions and will show some examples of how to use them. It will also have a function to get the index of the current thread, so there's no need for a map.

nice!