Home > Blockchain >  ~__nat() deleted error in ThreadPool implementation
~__nat() deleted error in ThreadPool implementation

Time:07-23

I am trying to implement a ThreadPool,but the clang compiler is giving me an error, which I do not know how to fix. My ThreadPool consists of 1 thread for planning and adding tasks to the queue (Scheduler), 1 thread for taking the tasks out of the queue and assigning separate threads to them(Executor), and child threads for each task. The problem arises in the Executor section:

struct Executor {
    std::shared_ptr<SharedData> data_ptr_;

    // constructor
    explicit Executor (std::shared_ptr<SharedData>& data_ptr):
      data_ptr_ (data_ptr)
    {}


    // methods
    void execute () {
      while (true) {
        auto cur_task = data_ptr_ -> queue_.Take();
        if (cur_task == std::nullopt) break;
        std::thread child_thread {&Executor::executeChild, this, std::move(cur_task)};
        // ...
      }

      // join child threads here
    }

    void executeChild (Task task) {
      // ...
      task();
      // ...
    }

  }; 

The compiler does not like this line: std::thread child_thread {&Executor::executeChild, this, std::move(cur_task)};

The error message that it produces is incomprehensible to me :( In template: attempt to use a deleted function error occurred here in instantiation of function template specialization 'std::__thread_execute<std::unique_ptr<std::__thread_struct>, void (tp::Executor::*)(fu2::detail::function<fu2::detail::config<true, false, fu2::capacity_default>, fu2::detail::proper... in instantiation of function template specialization 'std::__thread_proxy<std::tuple<std::unique_ptr<std::__thread_struct>, void (tp::Executor::*)(fu2::detail::function<fu2::detail::config<true, false, fu2::capacity_default>, fu2::detai... in instantiation of function template specialization 'std::thread::thread<void (tp::Executor::*)(fu2::detail::function<fu2::detail::config<true, false, fu2::capacity_default>, fu2::detail::property<true, false, void ()>>), tp::Executor ... '~__nat' has been explicitly marked deleted here

Are there any errors in my code? What is the compiler saying?

CodePudding user response:

The issue that cur_task is a std::optional<Task> and you pass this std::optional<Task> directly to executeChild(). But executeChild() expects not a std::optional<Task> but a Task. Since you check if the optional is nullopt before creating the thread, you probably want to use

std::thread child_thread {&Executor::executeChild, this, std::move(*cur_task)};

The * in front of cur_task is operator*, which assumes that the optional contains a value and returns a reference to the contained value (if it doesn't, you have undefined behavior). Note there is also std::optional::value() which throws if the optional is empty.

Reproducible example: The following code was adapted from your code, and shows the '~__nat' has been explicitly marked deleted here error with clang 14 and libc (example on godbolt)

#include <memory>
#include <thread>
#include <optional>

struct Task{
    void operator()(){}
};

struct SharedData{
    std::optional<Task> Take() { return {}; }
};

struct Executor {
    std::shared_ptr<SharedData> data_ptr_;

    // constructor
    explicit Executor (std::shared_ptr<SharedData>& data_ptr):
      data_ptr_ (data_ptr)
    {}

    // methods
    void execute () {
      while (true) {
        auto cur_task = data_ptr_ -> Take();
        if (cur_task == std::nullopt) break;
        // Mistake in the following line: Need to use *cur_task
        std::thread child_thread {&Executor::executeChild, this, std::move(cur_task)};
        // ...
      }

      // join child threads here
    }

    void executeChild (Task task) {
      // ...
      task();
      // ...
    }
}; 

Error:

In file included from <source>:2:
/opt/compiler-explorer/clang-14.0.0/bin/../include/c  /v1/thread:282:5: error: attempt to use a deleted function
    _VSTD::__invoke(_VSTD::move(_VSTD::get<1>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...);
    ^
/opt/compiler-explorer/clang-14.0.0/bin/../include/c  /v1/__config:826:15: note: expanded from macro '_VSTD'
#define _VSTD std
              ^
/opt/compiler-explorer/clang-14.0.0/bin/../include/c  /v1/thread:293:12: note: in instantiation of function template specialization 'std::__thread_execute<std::unique_ptr<std::__thread_struct>, void (Executor::*)(Task), Executor *, std::optional<Task>, 2UL, 3UL>' requested here
    _VSTD::__thread_execute(*__p.get(), _Index());
           ^
/opt/compiler-explorer/clang-14.0.0/bin/../include/c  /v1/thread:309:54: note: in instantiation of function template specialization 'std::__thread_proxy<std::tuple<std::unique_ptr<std::__thread_struct>, void (Executor::*)(Task), Executor *, std::optional<Task>>>' requested here
    int __ec = _VSTD::__libcpp_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get());
                                                     ^
<source>:26:21: note: in instantiation of function template specialization 'std::thread::thread<void (Executor::*)(Task), Executor *, std::optional<Task>, void>' requested here
        std::thread child_thread {&Executor::executeChild, this, std::move(cur_task)};
                    ^
/opt/compiler-explorer/clang-14.0.0/bin/../include/c  /v1/type_traits:1885:5: note: '~__nat' has been explicitly marked deleted here
    ~__nat() = delete;
    ^
1 error generated.
Compiler returned: 1

So clang with libc does not really provide a helpful error message, but neither does clang with stdlibc nor gcc nor MSVC.

  • Related