Closed lowercase-g closed 3 days ago
Thanks. I'll start reviewing this tonight and push revisions. The Readme is not necessary.
I need permission to write to your branch.
Enumerating objects: 54, done.
Counting objects: 100% (54/54), done.
Delta compression using up to 32 threads
Compressing objects: 100% (46/46), done.
Writing objects: 100% (47/47), 6.26 KiB | 6.26 MiB/s, done.
Total 47 (delta 34), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (34/34), completed with 5 local objects.
remote: error: GH006: Protected branch update failed for refs/heads/Job-System.
remote: error: At least 1 approving review is required by reviewers with write access.
To https://github.com/i-am-the-gabe/OpenTESArena.git
! [remote rejected] pr/247 -> Job-System (protected branch hook declined)
error: failed to push some refs to 'https://github.com/i-am-the-gabe/OpenTESArena.git'
I need permission to write to your branch.
Enumerating objects: 54, done. Counting objects: 100% (54/54), done. Delta compression using up to 32 threads Compressing objects: 100% (46/46), done. Writing objects: 100% (47/47), 6.26 KiB | 6.26 MiB/s, done. Total 47 (delta 34), reused 0 (delta 0), pack-reused 0 remote: Resolving deltas: 100% (34/34), completed with 5 local objects. remote: error: GH006: Protected branch update failed for refs/heads/Job-System. remote: error: At least 1 approving review is required by reviewers with write access. To https://github.com/i-am-the-gabe/OpenTESArena.git ! [remote rejected] pr/247 -> Job-System (protected branch hook declined) error: failed to push some refs to 'https://github.com/i-am-the-gabe/OpenTESArena.git'
My bad, bungled the branch protection. Should work now.
Okay, I made some changes to bring it more in line with what I'm looking for. Questions:
submitJob()
that takes one job? I think a common use case would be submitJob(...); submitJob(...); submitJob(...); wait();
. It can use submitJobs()
internally.std::unique_ptr
?I'll handle # 2.
Taking down (4) as we speak.
Edit: Looked into it, and it might not be necessary. It just sounds strange to have a job scheduler manage and request worker threads while being a worker thread itself. It'd also make the wait() implementation that much more confusing, and we need to keep it as simple as possible before categories are implemented.
I tried this in Game::loop()
but I don't understand why the main thread is blocked until the jobs are done. Maybe I'm misunderstanding locks/mutexes.
JobManager jobManager;
jobManager.init(8);
std::mutex mut;
auto lamb = [&mut](int i)
{
return [&mut, i]()
{
std::unique_lock<std::mutex> lock(mut);
std::cout << "lamb " << i << '\n';
lock.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
};
};
std::vector<Job> jobs;
for (int i = 0; i < 200; i++)
{
jobs.emplace_back(lamb(i));
}
jobManager.submitJobs(jobs);
Job job = [&mut]()
{
std::lock_guard<std::mutex> lock(mut);
std::cout << "Last job" << '\n';
};
jobManager.submitJob(job);
// Primary game loop.
int frame = 0;
while (this->running)
{
std::unique_lock<std::mutex> lock(mut);
std::cout << "frame " << frame << '\n';
lock.unlock();
frame++;
The output is
...
lamb 197
lamb 198
lamb 199
Last job
frame 0
frame 1
frame 2
But I expected like
lamb 0
lamb 1
frame 0
lamb 3
lamb 2
...
Edit: looks like if I comment out the submitJob()
then it works as expected.
Also I'm not sure if this is an easy change but Worker::invoke()
should not create a new thread, it should reuse the std::thread
it was initialized with. I don't want std::this_thread::get_id()
changing for the same worker.
This implements a job system (hopefully closes #245).
Examples:
Essentially, when a
JobManager
is constructed with ann_threads
argument, it creates a privateThreadPool
. ThatThreadPool
, in turn, creates n_threadsWorkers
.JobManager::run()
spawns a background thread to do the following: 1) While the job queue is not empty, ask the thread pool for an idle worker.2) When an idle worker has been obtained, pop a job from the front of the queue and tell the idle worker to do it.
JobManager
, if given a list of jobs in its constructor (optional), immediately starts running the job distributor. Otherwise,JobManager::run()
only runs when the following conditions are met: 1)JobManager::submitJobs()
has been called.2)
JobManager::isRunning()
returns false.3) The job queue is not empty.
This means the only job-performing method you need to worry about is
JobManager::submitJobs()
, and that adding jobs to an already-running queue is completely safe and intended behaviour:To do: