Необходимо поставить в очередь Task
(не копируемый, только перемещаемый) из функции Enqueue
, а затем делегировать обработку функции Process
в отдельном потоке.
Enqueue
функция вызывается несколькими потоками.
Да, это может быть сделано с помощью очереди, но на данный момент мне нужен только один task
.compare_and_exchange
выглядит лучше, чем полноценная очередь с несколькими производителями и одним потребителем или блокировка очереди одного производителя и одного потребителя.
// multiple enqueuers
bool Enqueue(Task task) {
auto task_ptr = new Task{std::move(task)};
Task* expected = nullptr;
while(!this->enqueud_task_.compare_exchange_strong(expected, task_ptr)) {
if (!somecondition) {
delete task_ptr;
return false;
}
}
return true;
}
// process
void Process() {
auto task = this->enqueud_task_.load();
if (task) {
auto t = task;
this->do_store(std::move(*t)); // Store the moved object to internal data structure.
delete t;
this->enqueud_task_ = nullptr;
}
}
Проблема в том, что я выделяю новую Task
который перенесен из исходного задания.Это заставляет меня вручную вызывать delete
.
std::atomic<std::unique_ptr<Task>>
не является допустимым типом, а также std::atomic<Task>
, так как Task не может быть легко скопирован.