1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-10-05 19:31:04 +00:00

Add API to cancel async jobs (#14602)

* Implement API to cancel async jobs

Co-authored-by: sfan5 <sfan5@live.de>

* update AsyncJob:cancel documentation from review

* Use IPC to unblock async

* review

* review async unblocking

* review

* Apply suggestions from code review

Co-authored-by: sfan5 <sfan5@live.de>

* minor licensing

---------

Co-authored-by: y5nw <y5nw@protonmail.com>
Co-authored-by: sfan5 <sfan5@live.de>
This commit is contained in:
y5nw 2025-08-26 12:40:31 +02:00 committed by GitHub
parent 7cbe62fe7b
commit f390137d6e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 229 additions and 78 deletions

View file

@ -96,38 +96,44 @@ void AsyncEngine::addWorkerThread()
}
/******************************************************************************/
u32 AsyncEngine::queueAsyncJob(std::string &&func, std::string &&params,
const std::string &mod_origin)
u32 AsyncEngine::queueAsyncJob(LuaJobInfo &&job)
{
MutexAutoLock autolock(jobQueueMutex);
u32 jobId = jobIdCounter++;
jobQueue.emplace_back();
auto &to_add = jobQueue.back();
to_add.id = jobId;
to_add.function = std::move(func);
to_add.params = std::move(params);
to_add.mod_origin = mod_origin;
assert(!job.function.empty());
job.id = jobId;
jobQueue.push_back(std::move(job));
jobQueueCounter.post();
return jobId;
}
u32 AsyncEngine::queueAsyncJob(std::string &&func, std::string &&params,
const std::string &mod_origin)
{
LuaJobInfo to_add(std::move(func), std::move(params), mod_origin);
return queueAsyncJob(std::move(to_add));
}
u32 AsyncEngine::queueAsyncJob(std::string &&func, PackedValue *params,
const std::string &mod_origin)
{
LuaJobInfo to_add(std::move(func), params, mod_origin);
return queueAsyncJob(std::move(to_add));
}
bool AsyncEngine::cancelAsyncJob(u32 id)
{
MutexAutoLock autolock(jobQueueMutex);
u32 jobId = jobIdCounter++;
jobQueue.emplace_back();
auto &to_add = jobQueue.back();
to_add.id = jobId;
to_add.function = std::move(func);
to_add.params_ext.reset(params);
to_add.mod_origin = mod_origin;
jobQueueCounter.post();
return jobId;
for (auto job = jobQueue.begin(); job != jobQueue.end(); job++) {
if (job->id == id) {
jobQueue.erase(job);
return true;
}
}
return false;
}
/******************************************************************************/
@ -419,3 +425,19 @@ void* AsyncWorkerThread::run()
return 0;
}
u32 ScriptApiAsync::queueAsync(std::string &&serialized_func,
PackedValue *param, const std::string &mod_origin)
{
return asyncEngine.queueAsyncJob(std::move(serialized_func),
param, mod_origin);
}
bool ScriptApiAsync::cancelAsync(u32 id)
{
return asyncEngine.cancelAsyncJob(id);
}
void ScriptApiAsync::stepAsync()
{
asyncEngine.step(getStack());
}

View file

@ -26,6 +26,12 @@ class AsyncEngine;
struct LuaJobInfo
{
LuaJobInfo() = default;
LuaJobInfo(std::string &&func, std::string &&params, const std::string &mod_origin = "") :
function(func), params(params), mod_origin(mod_origin) {}
LuaJobInfo(std::string &&func, PackedValue *params, const std::string &mod_origin = "") :
function(func), mod_origin(mod_origin) {
params_ext.reset(params);
}
// Function to be called in async environment (from string.dump)
std::string function;
@ -102,12 +108,26 @@ public:
u32 queueAsyncJob(std::string &&func, PackedValue *params,
const std::string &mod_origin = "");
/**
* Try to cancel an async job
* @param id The ID of the job
* @return Whether the job was cancelled
*/
bool cancelAsyncJob(u32 id);
/**
* Engine step to process finished jobs
* @param L The Lua stack
*/
void step(lua_State *L);
/**
* Get the maximum number of threads that can be used by the async environment
*/
unsigned int getThreadingCapacity() const {
return MYMAX(workerThreads.size(), autoscaleMaxWorkers);
}
protected:
/**
* Get a Job from queue to be processed
@ -117,6 +137,13 @@ protected:
*/
bool getJob(LuaJobInfo *job);
/**
* Queue an async job
* @param job The job to queue (takes ownership!)
* @return Id of the queued job
*/
u32 queueAsyncJob(LuaJobInfo &&job);
/**
* Put a Job result back to result queue
* @param result result of completed job
@ -206,3 +233,23 @@ private:
// Counter semaphore for job dispatching
Semaphore jobQueueCounter;
};
class ScriptApiAsync:
virtual public ScriptApiBase
{
public:
ScriptApiAsync(Server *server): asyncEngine(server) {}
virtual void initAsync() = 0;
void stepAsync();
u32 queueAsync(std::string &&serialized_func,
PackedValue *param, const std::string &mod_origin);
bool cancelAsync(u32 id);
unsigned int getThreadingCapacity() const {
return asyncEngine.getThreadingCapacity();
}
protected:
AsyncEngine asyncEngine;
};