#include "dynamic_scheduler.hpp"

#include <boost/thread.hpp>

namespace {

struct DynState {
    int F;
    int next_frame;
    boost::mutex mtx;
};

struct DynArgs {
    int tid;
    int K;
    DynState* st;
    task_fn_t task;
    void* ctx;
    bool affinity;
};

void worker(DynArgs a) {
    if (a.affinity)
        set_thread_affinity(a.tid);

    while (true) {
        int f;
        {
            boost::mutex::scoped_lock lk(a.st->mtx);
            if (a.st->next_frame >= a.st->F)
                return;
            f = a.st->next_frame++;
        }
        a.task(f, a.tid, a.K, a.ctx);
    }
}

} // namespace

int run_dynamic_scheduler(int F, int K, task_fn_t task, void* ctx, bool affinity)
{
    if (F <= 0 || K <= 0 || task == nullptr)
        return -1;

    DynState st;
    st.F = F;
    st.next_frame = 0;

    boost::thread_group workers;
    for (int tid = 0; tid < K; ++tid) {
        DynArgs a{tid, K, &st, task, ctx, affinity};
        workers.create_thread(boost::bind(worker, a));
    }
    workers.join_all();
    return 0;
}
