Intel® oneAPI Threading Building Blocks
Ask questions and share information about adding parallelism to your applications when using this threading library.
Announcements
Welcome to the Intel Community. If you get an answer you like, please mark it as an Accepted Solution to help others. Thank you!

Understanding Internals of tbb::task

AJ13
New Contributor I
87 Views
Hi,

I'm very confused as to what the reinterpret_casts within the allocation functions do. I don't see how you can get a pointer to the proxy from an instance of a tbb::task.

For example:

//! Returns proxy for overloaded new that allocates a child task of *this.
internal::allocate_child_proxy& allocate_child() {
return *reinterpret_cast<:ALLOCATE_CHILD_PROXY>(this);
}


Thanks,

AJ
0 Kudos
2 Replies
RafSchietekat
Black Belt
87 Views
There is no actual proxy object: the pointer to "this" is just (temporarily) disguised as another type, to select a specific "operator new" overload (at compile time). I'm not sure what to think of it, though...
Alexey_K_Intel3
Employee
87 Views
> There is no actual proxy object: the pointer to "this" is just (temporarily) disguised as another type, to select a specific "operator new" overload (at compile time).
Not only that, but also the pointer to the current task is passed to the real allocation function via such a masquerade, and used there. See the following methods that complement allocate_child():
[cpp]// in task.h
inline void *operator new( size_t bytes, const tbb::internal::allocate_child_proxy& p ) {
    return &p.allocate(bytes);
}
// in task.cpp
task& allocate_child_proxy::allocate( size_t size ) const {
    task& t = *((task*)this);
    __TBB_ASSERT( AssertOkay(t), NULL );
    GenericScheduler* v = static_cast(t.prefix().owner);
    return v->allocate_task( size, __TBB_ALLOC_TASK_ARGS(&t, t.prefix().depth+1, t.prefix().context) );
}
[/cpp]

Considered that there now exists five different proxy objects and correspondingly five overloaded operators new, some kind of pointer casting seems inevitable in order to pass task pointer to each one. The implementation could differ however; e.g. we could use five different unions instead of reinterpret_cast.
Reply