Last active
January 24, 2022 19:12
-
-
Save Karolis2011/4351f3ae54fe89a4f6580947aec48076 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define ASYNC_DEFAULT "snowflake__thing_should_dnot_bebused" | |
#define istask(t) istype(t, /task) | |
/task | |
parent_type = /datum | |
VAR_PRIVATE/object_src = ASYNC_DEFAULT | |
VAR_PRIVATE/result = ASYNC_DEFAULT | |
VAR_PRIVATE/is_complete = FALSE | |
var/error = null | |
/task/New(var/obj_src, var/return_value) | |
if(obj_src != null) | |
object_src = obj_src // TODO: Wekref | |
if(return_value != null) | |
result = return_value | |
/task/proc/isComplete() | |
return is_complete | |
/task/proc/Wait() | |
__internal_wait() | |
/task/proc/WaitResult() | |
__internal_wait_result() | |
/task/proc/GetResult() | |
return __internal_get_result() | |
/task/proc/__internal_complete() | |
is_complete = TRUE | |
/task/proc/__internal_result(var/result) | |
src.result = result | |
/task/proc/__internal_return(var/result) | |
is_complete = TRUE | |
src.result = result | |
/task/proc/__internal_handle_error(var/e) | |
error = e | |
// TODO: Make it handle error | |
/task/proc/__internal_wait() | |
while(!is_complete) | |
sleep(world.tick_lag) | |
/task/proc/__internal_wait_result() | |
while(result == ASYNC_DEFAULT) | |
sleep(world.tick_lag) | |
/task/proc/__internal_get_result() | |
if(src.result == ASYNC_DEFAULT) | |
return null | |
else | |
return src.result | |
#define BEGINASYNC set waitfor = FALSE; RETURN_TYPE(/task); . = new /task(src, .); try | |
#define ENDASYNC catch (var/e) { (.).__internal_handle_error(e) } (.).__internal_complete(); return; | |
#define ARETURN(value) (.).__internal_return((value)); return; | |
#define ARESULT(value) (.).__internal_result((value)); | |
#define AWAIT(task) (task).__internal_wait(); | |
#define AWAITR(v, task) (task).__internal_wait(); v = ((task).__internal_get_result()); | |
#define AWAITRESULT(v, task) (task).__internal_wait_result(); v = ((task).__internal_get_result()); | |
/proc/TaskWhenAny(...) | |
BEGINASYNC | |
var/list/tasks = args | |
if(islist(args[1])) | |
tasks = args[1].Copy() | |
for(var/task in tasks) | |
ASSERT(istask(task)) | |
while(TRUE) | |
for(var/task in tasks) | |
var/task/T = task | |
if(T.isComplete()) | |
ARETURN(T) | |
sleep(world.tick_lag) | |
ENDASYNC | |
/proc/TaskWhenAll(...) | |
BEGINASYNC | |
var/list/tasks = args | |
if(islist(args[1])) | |
tasks = args[1].Copy() | |
for(var/task in tasks) | |
ASSERT(istask(task)) | |
while(tasks.len) | |
for(var/task in tasks) | |
var/task/T = task | |
if(T.isComplete()) | |
tasks -= T | |
sleep(world.tick_lag) | |
ENDASYNC |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/proc/makeHttpRequestAsync(var/url, var/body) | |
BEGINASYNC | |
// Code using sleep(delay) ir AWAIT(task) | |
// ... | |
sleep(pick(1,2,3,4,5,6,7,8)) | |
ARETURN(url) | |
ENDASYNC | |
/proc/doMutipleRequestsAsync() | |
BEGINASYNC | |
var/task/githubTask = makeHttpRequestAsync("https://api.github.com/ping", null) | |
var/task/auroraTask = makeHttpRequestAsync("https://api.aurorastation.org/someLongTask", null) | |
var/task/cTask = TaskWhenAll(list(githubTask, auroraTask)) | |
// We can wait for all tasks to finish | |
AWAIT(cTask) | |
// Or we can wait just for any of them | |
var/task/finishedTask | |
cTask = TaskWhenAny(list(githubTask, auroraTask)) | |
AWAITR(finishedTask, cTask) | |
if(finishedTask == auroraTask) | |
world.log << "Aurora task finished first" | |
if(finishedTask == githubTask) | |
world.log << "GitHub task finished first" | |
// Or we can wait only for the result, useful when we need the result ASAP, but proc still has work to do. In such case proc would use ARETURNR(result) | |
var/response | |
AWAITRESULT(response, auroraTask) | |
ENDASYNC | |
/proc/NormalProc() | |
var/task/myTask = doMutipleRequestsAsync() | |
myTask.Wait() // Do sleep like lock | |
myTask.WaitResult() // Similar to wait, but it doesn't wait for completion, only the result, will be the same as Wait() if async proc doesn't use ARETURNR. | |
world.log << myTask.GetResult() // Access result safely, crashes if result is not there. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment