fix issues with coroutine scheduler threads locking up

master
Daniel Kolesa 2017-03-21 19:49:06 +01:00
parent 307123fd35
commit c1a1c4a1ac
1 changed files with 23 additions and 18 deletions

View File

@ -257,17 +257,11 @@ private:
func();
}
void yield(basic_coroutine_scheduler &sched) {
{
std::lock_guard<std::mutex> l{sched.p_lock};
sched.p_available.splice(
sched.p_available.cend(), sched.p_running, pos
);
}
yield_raw();
}
void yield_raw() {
void yield() {
/* we'll yield back to the thread we were scheduled to, which
* will appropriately notify one or all other waiting threads
* so we either get re-scheduled or the whole scheduler dies
*/
typename coro::yield_type{func}();
}
@ -299,7 +293,7 @@ private:
l.unlock();
task *curr = task::current();
p_sched.wait(this, p_waiting, curr);
curr->yield_raw();
curr->yield();
l.lock();
}
@ -378,7 +372,7 @@ public:
}
void yield() {
task::current()->yield(*this);
task::current()->yield();
}
template<typename T>
@ -403,10 +397,8 @@ private:
}
void destroy() {
p_cond.notify_all();
for (auto &tid: p_thrs) {
tid.join();
p_cond.notify_all();
}
}
@ -428,7 +420,7 @@ private:
wl = wl->next_waiting;
l.unlock();
p_cond.notify_one();
task::current()->yield(*this);
task::current()->yield();
}
void notify_all(task *&wl) {
@ -443,7 +435,7 @@ private:
l.lock();
}
}
task::current()->yield(*this);
task::current()->yield();
}
void thread_run() {
@ -470,8 +462,21 @@ private:
l.lock();
if (c.dead()) {
p_running.erase(it);
/* we're dead, notify all threads so they can be joined
* we check all three, saves the other threads some re-waiting
* when a task or tasks are already running, and those that do
* will do the final notify by themselves
*/
if (p_available.empty() && p_waiting.empty() && p_running.empty()) {
l.unlock();
p_cond.notify_all();
}
} else if (!c.waiting_on) {
/* reschedule to the end of the queue */
p_available.splice(p_available.cend(), p_running, it);
l.unlock();
p_cond.notify_one();
}
l.unlock();
}
std::condition_variable p_cond;