Home > Enterprise >  Why tbb::enumerable_thread_specific does not accept types with not-const references in constructor a
Why tbb::enumerable_thread_specific does not accept types with not-const references in constructor a

Time:11-05

I would like to create thread local storage using tbb::enumerable_thread_specific for elements of type that takes not-const reference in the constructor. Unfortunetly, it does not work from the box, and I have to use std::ref for construction as a workaround. Here is an example:

#include <tbb/enumerable_thread_specific.h>

struct A {
    A(int &) {}
};

int main() {
    int i;

    // ok
    tbb::enumerable_thread_specific<A> ets1(std::ref(i));

    // error
    tbb::enumerable_thread_specific<A> ets(i);
}

The error is

In file included from /opt/compiler-explorer/libs/tbb/2021.4.0/include/tbb/enumerable_thread_specific.h:17,
                 from <source>:1:
/opt/compiler-explorer/libs/tbb/2021.4.0/include/oneapi/tbb/enumerable_thread_specific.h: In instantiation of 'void tbb::detail::d1::construct_by_args<T, P>::construct(void*) [with T = A; P = {int&}]':
/opt/compiler-explorer/libs/tbb/2021.4.0/include/oneapi/tbb/enumerable_thread_specific.h:685:31:   required from 'void tbb::detail::d1::callback_leaf<Constructor>::construct(void*) [with Constructor = tbb::detail::d1::construct_by_args<A, int&>]'
/opt/compiler-explorer/libs/tbb/2021.4.0/include/oneapi/tbb/enumerable_thread_specific.h:684:10:   required from here
/opt/compiler-explorer/libs/tbb/2021.4.0/include/oneapi/tbb/enumerable_thread_specific.h:648:12: error: binding reference of type 'int&' to 'const std::decay<int&>::type' {aka 'const int'} discards qualifiers
  648 |            new(where) T(args...);
      |            ^~~~~~~~~~~~~~~~~~~~~
<source>:4:7: note:   initializing argument 1 of 'A::A(int&)'
    4 |     A(int &) {}
      |       ^~~~~

Online demo: https://godbolt.org/z/qGx7cGz44

It looks like not-const reference becomes const reference inside TBB before it reaches A constructor. Is it intentional design decision or simply a bug in the implementation?

CodePudding user response:

This has essentially been answered in the comments by 463035818_is_not_an_ai relating it to the same logic behind std::thread, and then linking an answer regarding the same explicit use of ref with threads.

The issue you're encountering with tbb::enumerable_thread_specific and non-const references in constructor arguments is related to the design of tbb::enumerable_thread_specific. The library uses an underlying mechanism to construct and manage instances of the stored type, and this mechanism relies on certain characteristics of the type.

When you provide a non-const reference in the constructor argument, it can create complications in terms of thread safety and object management. enumerable_thread_specific is designed to manage instances of types efficiently across multiple threads, and dealing with non-const references in a thread-safe manner can be challenging.

As you've already figured out you can use std::reference_wrapper or a pointer instead of a non-const reference.

  • Related