{"id":13730000,"url":"https://github.com/nem0/lucy_job_system","last_synced_at":"2025-05-08T02:30:56.417Z","repository":{"id":75071892,"uuid":"192173943","full_name":"nem0/lucy_job_system","owner":"nem0","description":"Fiber-based job system with extremely simple API","archived":true,"fork":false,"pushed_at":"2021-02-15T23:12:36.000Z","size":296,"stargazers_count":80,"open_issues_count":1,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-11-14T20:38:51.596Z","etag":null,"topics":["fibers","job","multithreading"],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nem0.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-06-16T09:42:04.000Z","updated_at":"2024-09-03T22:41:36.000Z","dependencies_parsed_at":"2023-07-24T09:32:36.042Z","dependency_job_id":null,"html_url":"https://github.com/nem0/lucy_job_system","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nem0%2Flucy_job_system","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nem0%2Flucy_job_system/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nem0%2Flucy_job_system/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nem0%2Flucy_job_system/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nem0","download_url":"https://codeload.github.com/nem0/lucy_job_system/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252986651,"owners_count":21836201,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fibers","job","multithreading"],"created_at":"2024-08-03T02:01:08.635Z","updated_at":"2025-05-08T02:30:56.409Z","avatar_url":"https://github.com/nem0.png","language":"C++","funding_links":[],"categories":["C++"],"sub_categories":[],"readme":"# Lucy Job System\n\n**This is outdated compared to [Lumix Engine](https://github.com/nem0/LumixEngine/blob/master/src/engine/job_system.h). Use that instead.**\n\nFiber-based job system with extremely simple API. \n\nIt's a standalone version of job system used in [Lumix Engine](https://github.com/nem0/lumixengine).\nOnly Windows is supported now, although the Lumix Engine version has Linux support, I have to copy it here yet.\n\n## Demo \nCreate a solution with ```create_solution_vs2017.bat```. The solution is in ```build/tmp/```. Open the solution, compile and run.\n\n```cpp\n#include \"lucy.h\"\n#include \u003ccondition_variable\u003e\n#include \u003ccstdio\u003e\n#include \u003cmutex\u003e\n\n\nstd::mutex g_mutex;\nstd::condition_variable g_finished;\nstd::mutex g_finished_mutex;\n\n\nvoid print(const char* msg)\n{\n\tstd::lock_guard lock(g_mutex);\n\tprintf(msg);\n\tprintf(\"\\n\");\n}\n\n\nvoid jobB(void*)\n{\n\tprint(\"B begin\");\n\tprint(\"B end\");\n}\n\n\nvoid jobA(void*)\n{\n\tprint(\"A begin\");\n\tlucy::SignalHandle finished = lucy::INVALID_HANDLE;\n\tfor(int i = 0; i \u003c 10; ++i) {\n\t\tlucy::run(nullptr, jobB, \u0026finished);\n\t}\n\tlucy::wait(finished);\n\tprint(\"A end\");\n\tg_finished.notify_all();\n}\n\n\nint main(int argc, char* argv[])\n{\n\tlucy::init();\n\tlucy::run(nullptr, jobA, nullptr);\n\tstd::unique_lock\u003cstd::mutex\u003e lck(g_finished_mutex);\n\tg_finished.wait(lck);\n\tlucy::shutdown();\n}\n```\n\n## Integration\nJust put lucy.h and lucy.cpp in your project and you are good to go.\n\n## Docs\n\nSee ```src/main.cpp``` for an example.\n\n### Initialization / shutdown\n\n```lucy::init()``` must be called before any other function from lucy namespace\n```lucy::shutdown()``` call this when you don't want to run any more jobs. Make sure all jobs are finished before calling this, since it does not wait for jobs to finish.\n\n### Jobs\n\nJob is a function pointer with associated void data pointer. When job is executed, the function is called and the data pointer is passed as a parameter to this function.\n\n```lucy::run``` push a job to global queue\n\n```cpp\nint value = 42;\nlucy::run(\u0026value, [](void* data){\n\tprintf(\"%d\", *(int*)data);\n}, nullptr);\n```\n\nThis prints ```42```. Eventually, after the job is finished, a signal can be triggered, see signals for more information.\n\n### Signals\n\n```cpp\nlucy::SignalHandle signal = lucy::INVALID_HANDLE;\nlucy::wait(signal); // does not wait, since signal is invalid\nlucy::incSignal(\u0026signal);\nlucy::wait(signal); // wait until someone calls lucy::decSignal, execute other jobs in the meantime\n```\n\n```cpp\nlucy::SignalHandle signal = lucy::INVALID_HANDLE;\nfor (int i = 0; i \u003c N; ++i) {\n\tlucy::incSignal(\u0026signal);\n}\nlucy::wait(signal); // wait until lucy::decSignal is called N-times\n```\n\nIf a signal is passed to ```lucy::run``` (3rd parameter), then the signal is automatically incremented. It is decremented once all the job is finished.\n\n```cpp\nlucy::SignalHandle finished = lucy::INVALID_HANDLE;\nfor(int i = 0; i \u003c 10; ++i) {\n\tlucy::run(nullptr, job_fn, \u0026finished);\n}\nlucy::wait(finished); // wait for all 10 jobs to finish\n```\n\nThere's no need to destroy signals, it's \"garbage collected\".\n\nSignals can be used as preconditions to run a job. It means a job starts only after the signal is signalled:\n\n```cpp\nlucy::SignalHandle precondition = getPrecondition();\nlucy::runEx(nullptr, job_fn, nullptr, precondition, lucy::ANY_WORKER);\n```\n\nis functionally equivalent to:\n\n```cpp\nvoid job_fn(void*) { \n\tlucy::wait(precondition);\n\tdowork();\n}\nlucy::run(nullptr, job_fn, nullptr);\n```\n\nHowever, the ```lucy::runEx``` version has better performance.\n\nFinally, a job can be pinned to specific worker thread. This is useful for calling APIs which must be called from the same thread, e.g. OpenGL functions or WinAPI UI functions.\n\n```cpp\nlucy::runEx(nullptr, job_fn, nullptr, lucy::INVALID_HANDLE, 3); // run on worker thread 3\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnem0%2Flucy_job_system","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnem0%2Flucy_job_system","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnem0%2Flucy_job_system/lists"}