Пример #1
0
uint32_t Processer::Run(ThreadLocalInfo &info, uint32_t &done_count)
{
    info.current_task = NULL;
    done_count = 0;
    uint32_t c = 0;
    SList<Task> slist = runnable_list_.pop_all();
    uint32_t do_count = slist.size();

    DebugPrint(dbg_scheduler, "Run [Proc(%d) do_count:%u] --------------------------", id_, do_count);

    SList<Task>::iterator it = slist.begin();
    for (; it != slist.end(); ++c)
    {
        Task* tk = &*it;
        info.current_task = tk;
        tk->state_ = TaskState::runnable;
        DebugPrint(dbg_switch, "enter task(%s)", tk->DebugInfo());
        RestoreStack(tk);
        int ret = swapcontext(&info.scheduler, &tk->ctx_);
        if (ret) {
            fprintf(stderr, "swapcontext error:%s\n", strerror(errno));
            runnable_list_.push(tk);
            ThrowError(eCoErrorCode::ec_swapcontext_failed);
        }
        DebugPrint(dbg_switch, "leave task(%s) state=%d", tk->DebugInfo(), tk->state_);
        info.current_task = NULL;

        switch (tk->state_) {
            case TaskState::runnable:
                ++it;
                break;

            case TaskState::io_block:
                it = slist.erase(it);
                g_Scheduler.io_wait_.SchedulerSwitch(tk);
                break;

            case TaskState::sleep:
                it = slist.erase(it);
                g_Scheduler.sleep_wait_.SchedulerSwitch(tk);
                break;

            case TaskState::sys_block:
            case TaskState::user_block:
                {
                    if (tk->block_) {
                        it = slist.erase(it);
                        if (!tk->block_->AddWaitTask(tk))
                            runnable_list_.push(tk);
                        tk->block_ = NULL;
                    } else {
                        std::unique_lock<LFLock> lock(g_Scheduler.user_wait_lock_);
                        auto &zone = g_Scheduler.user_wait_tasks_[tk->user_wait_type_];
                        auto &wait_pair = zone[tk->user_wait_id_];
                        auto &task_queue = wait_pair.second;
                        if (wait_pair.first) {
                            --wait_pair.first;
                            tk->state_ = TaskState::runnable;
                            ++it;
                        } else {
                            it = slist.erase(it);
                            task_queue.push(tk);
                        }
                        g_Scheduler.ClearWaitPairWithoutLock(tk->user_wait_type_,
                                tk->user_wait_id_, zone, wait_pair);
                    }
                }
                break;

            case TaskState::done:
            default:
                --task_count_;
                ++done_count;
                it = slist.erase(it);
                DebugPrint(dbg_task, "task(%s) done.", tk->DebugInfo());
                if (tk->eptr_) {
                    std::exception_ptr ep = tk->eptr_;
                    runnable_list_.push(slist);
                    tk->DecrementRef();
                    std::rethrow_exception(ep);
                } else
                    tk->DecrementRef();
                break;
        }
    }
    if (do_count)
        runnable_list_.push(slist);

    return c;
}