Ладно, это немного не подходит для стека, но я постараюсь сделать его как можно короче.
Я получил поток, который берет задачи из списка и выполняет их. Просто как это (Рабочий класс имеет свой собственный поток и запускает doTask m_thread(&Worker::doTask, this)
):
void Worker::doTask()
{
while (m_running)
{
auto task = m_tasks.pop_front();
task->execute();
if (task->isContinuous())
m_tasks.push_pack(task);
}
}
Сам список / должен быть потокобезопасным:
Заголовок:
class TaskQueue
{
public:
void push_pack(std::shared_ptr<Task> t);
std::shared_ptr<Task> pop_front();
private:
std::list<std::shared_ptr<Task>> m_tasks;
std::condition_variable m_cond;
std::mutex m_mutex;
void TaskQueue::push_pack(std::shared_ptr<Task> t)
}
Значения важной части:
void TaskQueue::push_pack(std::shared_ptr<Task> t)
{
m_tasks.push_back(t);
//notify that there is one more task, so one thread can work now
m_cond.notify_one();
}
std::shared_ptr<Task> TaskQueue::pop_front()
{
//regular lock so noone else acces this area now
std::unique_lock<std::mutex> lock(m_mutex);
while (m_tasks.size() == 0)
m_cond.wait(lock);
auto task = m_tasks.front();
m_tasks.pop_front();
return task;
}
И последнее, но не менее важное:
class Task
{
public:
virtual ~Task()
{
}
virtual void execute() = 0;
virtual bool isContinuous()
{
return false;
};
};
Так что, если я попытаюсь добавить эту задачу:
class NetworkRequestTask:public Task
{
public:
NetworkRequestTask(TaskQueue &q);
~NetworkRequestTask();
void execute() override;
bool isContinuous() override;
private:
TaskQueue &m_tasks;
};
Impl:
NetworkRequestTask::NetworkRequestTask(TaskQueue& q): m_tasks(q)
{
}
NetworkRequestTask::~NetworkRequestTask()
{
}
void NetworkRequestTask::execute()
{
while(dosomething)
{
//do something here
}
}
bool NetworkRequestTask::isContinuous()
{
return true;
}
Главный:
int main(int argc, char* argv[])
{
TaskQueue tasks;
tasks.push_pack(std::make_shared<NetworkRequestTask>(tasks));
}
он попадает в плохое состояние:
Expression: list iterator not derefercable
Я сбит с толку. Это происходит только в том случае, если я переопределяю Continouse, и это происходит только при выполнении этой задачи. Если я добавлю очередь в другую задачу Continouse в качестве ссылки, она не попадет в это плохое состояние.
Так что здесь происходит не так и важно, что я сделал не так?
Что касается комментариев, я уже пытался заблокировать метод push_back, который ничего не изменил в поведении. (Вы можете обменять его на обычный мьютекс, это не имеет значения.)
void TaskQueue::push_pack(std::shared_ptr<Task> t)
{
std::lock_guard<SpinLock> lock(m_spin);
m_tasks.push_back(t);
//notify that there is one more task, so one thread can work now
m_cond.notify_one();
}
Задача ещё не решена.