I using TBB to load data in a queue in parallel. In the class below, the method load_data
works fine. I'm writing the method cancel_load
which should cancel the loading process and reset arena
and task
so that I can restart the loading process from the beginning. After the loading process is stopped, I will clear the queue using clear_queue
method.
In the method cancel_load
, task.cancel
works fine. However, when I try to reset the members arena
and task
to new instances, I see error: use of deleted function
when compiling.
Can anyone explain why this is happening? I have not deleted task
object. I'm just trying to reset it using a new instance. Is there a better way to reset these class members?
#include <iostream>
#include <tbb/concurrent_queue.h>
#include <tbb/task_group.h>
#include <tbb/tbb_thread.h>
class ParallelDataset {
public:
tbb::concurrent_bounded_queue<record_data::Record> MyQueue;
tbb::task_arena arena;
tbb::task_group task;
~ParallelDataset()
{
task.wait();
}
void load_() {
// start loading data into MyQueue
}
void load_data() {
arena.execute([&]() {
task.run([&]() {
load_();
});
});
}
void cancel_load() {
task.cancel();
tbb::task_arena new_arena;
tbb::task_group new_task;
arena = new_arena;
task = new_task;
std::cout << "Data loading is cancelled. Arena and Task have been reset" << std::endl;
}
void clear_queue() {
MyQueue.clear();
}
}
Error
/home/src/dataset.cpp: In member function 'void ParallelDataset::cancel_load()':
/home/src/dataset.cpp:275:16: error: use of deleted function 'tbb::task_group& tbb::task_group::operator=(const tbb::task_group&)'
275 | task = new_group;
| ^~~~~~~~~
In file included from /home/src/dataset.cpp:6:
/usr/include/tbb/task_group.h:192:7: note: 'tbb::task_group& tbb::task_group::operator=(const tbb::task_group&)' is implicitly deleted because the default definition would be ill-formed:
192 | class task_group : public internal::task_group_base {
| ^~~~~~~~~~
/usr/include/tbb/task_group.h:192:7: error: use of deleted function 'tbb::internal::task_group_base& tbb::internal::task_group_base::operator=(const tbb::internal::task_group_base&)'
/usr/include/tbb/task_group.h:92:7: note: 'tbb::internal::task_group_base& tbb::internal::task_group_base::operator=(const tbb::internal::task_group_base&)' is implicitly deleted because the default definition would be ill-formed:
92 | class task_group_base : internal::no_copy {
| ^~~~~~~~~~~~~~~
/usr/include/tbb/task_group.h:92:7: error: use of deleted function 'tbb::internal::no_copy& tbb::internal::no_copy::operator=(const tbb::internal::no_copy&)'
In file included from /usr/include/tbb/task.h:23,
from /usr/include/tbb/parallel_for.h:24,
from /home/src/dataset.cpp:4:
/usr/include/tbb/tbb_stddef.h:330:7: note: 'tbb::internal::no_copy& tbb::internal::no_copy::operator=(const tbb::internal::no_copy&)' is implicitly deleted because the default definition would be ill-formed:
330 | class no_copy: no_assign {
| ^~~~~~~
/usr/include/tbb/tbb_stddef.h:330:7: error: use of deleted function 'void tbb::internal::no_assign::operator=(const tbb::internal::no_assign&)'
/usr/include/tbb/tbb_stddef.h:324:10: note: declared here
324 | void operator=( const no_assign& ) = delete;
| ^~~~~~~~
In file included from /home/src/dataset.cpp:6:
/usr/include/tbb/task_group.h:92:7: error: use of deleted function 'tbb::task_group_context& tbb::task_group_context::operator=(const tbb::task_group_context&)'
92 | class task_group_base : internal::no_copy {
| ^~~~~~~~~~~~~~~
In file included from /usr/include/tbb/parallel_for.h:24,
from /home/src/dataset.cpp:4:
/usr/include/tbb/task.h:347:7: note: 'tbb::task_group_context& tbb::task_group_context::operator=(const tbb::task_group_context&)' is implicitly deleted because the default definition would be ill-formed:
347 | class task_group_context : internal::no_copy {
| ^~~~~~~~~~~~~~~~~~
/usr/include/tbb/task.h:347:7: error: use of deleted function 'tbb::internal::no_copy& tbb::internal::no_copy::operator=(const tbb::internal::no_copy&)'
CodePudding user response:
The tbb::task_arena
and tbb::task_group
objects are non-copyable, like you may also know from std::unique_ptr
. This is realized by deleted operator=
, explaining the compiler's error message.
You have to reinitialize your members in another way or use pointers so you can instantiate their replacements in-place.
In your scenario, I would assume that task.cancel()
and arena.terminate()
should do the job.
CodePudding user response:
Based on @ypnos comment about using unique pointers, I came up with the following solution that works.
#include <iostream>
#include <tbb/concurrent_queue.h>
#include <tbb/task_group.h>
#include <tbb/tbb_thread.h>
class ParallelDataset {
public:
tbb::concurrent_bounded_queue<record_data::Record> MyQueue;
std::unique_ptr<tbb::task_arena> arena;
std::unique_ptr<tbb::task_group> task;
ParallelDataset () : arena(std::make_unique<tbb::task_arena>()),
task(std::make_unique<tbb::task_group>()) {}
~ParallelDataset()
{
task->wait();
}
void load_() {
// start loading data into MyQueue
}
void load_data() {
arena->execute([&]() {
task->run([&]() {
load_();
});
});
}
void cancel_load() {
task->cancel();
arena = std::move(std::make_unique<tbb::task_arena>());
task = std::move(std::make_unique<tbb::task_group>());
std::cout << "Data loading is cancelled. Arena and Task have been reset" << std::endl;
}
void clear_queue() {
MyQueue.clear();
}
}