Added threaded extools logging as an alternative to rust_g logging.
This commit is contained in:
@@ -0,0 +1 @@
|
||||
#define EXTOOLS (world.system_type == MS_WINDOWS ? "byond-extools.dll" : "libbyond-extools.so")
|
||||
@@ -281,8 +281,6 @@ GLOBAL_LIST_INIT(atmos_adjacent_savings, list(0,0))
|
||||
#define CALCULATE_ADJACENT_TURFS(T) SSadjacent_air.queue[T] = 1
|
||||
#endif
|
||||
|
||||
#define EXTOOLS (world.system_type == MS_WINDOWS ? "byond-extools.dll" : "libbyond-extools.so")
|
||||
|
||||
GLOBAL_VAR(atmos_extools_initialized) // this must be an uninitialized (null) one or init_monstermos will be called twice because reasons
|
||||
#define ATMOS_EXTOOLS_CHECK if(!GLOB.atmos_extools_initialized){\
|
||||
GLOB.atmos_extools_initialized=TRUE;\
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
TFFI - Threaded FFI
|
||||
All DLL calls are automatically threaded off.
|
||||
Black magic is used to suspend (sleep) the currently executing proc, allowing non-blocking FFI.
|
||||
You may call a DLL function and sleep until it returns, pass a callback to be called with the result,
|
||||
or call resolve() on the /datum/promise to receive the return value at any time.
|
||||
Example:
|
||||
var/x = call_wait("sample.dll", "do_work", "arg1", "arg2", "arg3")
|
||||
- Calls the do_work function from sample.dll with 3 arguments. The proc sleeps until do_work returns.
|
||||
var/datum/promise/P = call_async("sample.dll", "do_work", "arg1")
|
||||
... do something else ...
|
||||
var/result = P.resolve()
|
||||
- Calls do_work with 1 argument. Returns a promise object. Runs some other code before calling P.resolve() to obtain the result.
|
||||
/proc/print_result(result)
|
||||
world << result
|
||||
call_cb("sample.dll", "do_work", /proc/print_result, "arg1", "arg2")
|
||||
- Calls do_work with 2 arguments. The callback is invoked with the result as the single argument. Execution resumes immediately.
|
||||
*/
|
||||
|
||||
/proc/tffi_initialize()
|
||||
return call(EXTOOLS, "tffi_initialize")()
|
||||
|
||||
var/fallback_alerted = FALSE
|
||||
var/next_promise_id = 0
|
||||
|
||||
/datum/promise
|
||||
var/completed = FALSE
|
||||
var/result = ""
|
||||
var/callback_context = GLOBAL_PROC
|
||||
var/callback_proc = null
|
||||
var/__id = 0
|
||||
|
||||
/datum/promise/New()
|
||||
__id = next_promise_id++ //please don't create more than 10^38 promises in a single tick
|
||||
|
||||
//This proc's bytecode is overwritten to allow suspending and resuming on demand.
|
||||
//None of the code here should run.
|
||||
/datum/promise/proc/__internal_resolve(ref, id)
|
||||
if(!fallback_alerted && world.system_type != UNIX) // the rewriting is currently broken on Linux.
|
||||
world << "<b>TFFI: __internal_resolve has not been rewritten, the TFFI DLL was not loaded correctly.</b>"
|
||||
world.log << "<b>TFFI: __internal_resolve has not been rewritten, the TFFI DLL was not loaded correctly.</b>"
|
||||
fallback_alerted = TRUE
|
||||
while(!completed)
|
||||
sleep(1)
|
||||
//It might be better to just fail and notify the user that something went wrong.
|
||||
|
||||
/datum/promise/proc/__resolve_callback()
|
||||
__internal_resolve("\ref[src]", __id)
|
||||
if(callback_context == GLOBAL_PROC)
|
||||
call(callback_proc)(result)
|
||||
else
|
||||
call(callback_context, callback_proc)(result)
|
||||
|
||||
/datum/promise/proc/resolve()
|
||||
__internal_resolve("\ref[src]", __id)
|
||||
return result
|
||||
|
||||
/proc/call_async()
|
||||
var/list/arguments = args.Copy()
|
||||
var/datum/promise/P = new
|
||||
arguments.Insert(1, "\ref[P]")
|
||||
call(EXTOOLS, "call_async")(arglist(arguments))
|
||||
return P
|
||||
|
||||
/proc/call_cb()
|
||||
var/list/arguments = args.Copy()
|
||||
var/context = arguments[3]
|
||||
var/callback = arguments[4]
|
||||
arguments.Cut(3, 5)
|
||||
var/datum/promise/P = new
|
||||
P.callback_context = context
|
||||
P.callback_proc = callback
|
||||
arguments.Insert(1, "\ref[P]")
|
||||
call(EXTOOLS, "call_async")(arglist(arguments))
|
||||
spawn(0)
|
||||
P.__resolve_callback()
|
||||
|
||||
/proc/call_wait()
|
||||
return call_async(arglist(args)).resolve()
|
||||
|
||||
/*
|
||||
Logging -- same exact interface as rust_g logging, but threaded and doesn't go through call()().
|
||||
*/
|
||||
|
||||
#define EXTOOLS_LOGGING // rust_g is used as a fallback if this is undefined
|
||||
|
||||
/proc/extools_log_write()
|
||||
|
||||
/proc/extools_finalize_logging()
|
||||
@@ -4,10 +4,15 @@
|
||||
#define SEND_SOUND(target, sound) DIRECT_OUTPUT(target, sound)
|
||||
#define SEND_TEXT(target, text) DIRECT_OUTPUT(target, text)
|
||||
#define WRITE_FILE(file, text) DIRECT_OUTPUT(file, text)
|
||||
#ifdef EXTOOLS_LOGGING
|
||||
// proc hooked, so we can just put in standard TRUE and FALSE
|
||||
#define WRITE_LOG(log, text) extools_log_write(log,text,TRUE)
|
||||
#define WRITE_LOG_NO_FORMAT(log, text) extools_log_write(log,text,FALSE)
|
||||
#else
|
||||
//This is an external call, "true" and "false" are how rust parses out booleans
|
||||
#define WRITE_LOG(log, text) rustg_log_write(log, text, "true")
|
||||
#define WRITE_LOG_NO_FORMAT(log, text) rustg_log_write(log, text, "false")
|
||||
|
||||
#endif
|
||||
//print a warning message to world.log
|
||||
#define WARNING(MSG) warning("[MSG] in [__FILE__] at line [__LINE__] src: [UNLINT(src)] usr: [usr].")
|
||||
/proc/warning(msg)
|
||||
@@ -216,7 +221,11 @@
|
||||
|
||||
/* Close open log handles. This should be called as late as possible, and no logging should hapen after. */
|
||||
/proc/shutdown_logging()
|
||||
#ifdef EXTOOLS_LOGGING
|
||||
extools_finalize_logging()
|
||||
#else
|
||||
rustg_log_close_all()
|
||||
#endif
|
||||
|
||||
|
||||
/* Helper procs for building detailed log lines */
|
||||
|
||||
@@ -11,6 +11,11 @@ GLOBAL_LIST(topic_status_cache)
|
||||
/world/New()
|
||||
if (fexists(EXTOOLS))
|
||||
call(EXTOOLS, "maptick_initialize")()
|
||||
#ifdef EXTOOLS_LOGGING
|
||||
call(EXTOOLS, "init_logging")()
|
||||
else
|
||||
CRASH("[EXTOOLS] does not exist!")
|
||||
#endif
|
||||
enable_debugger()
|
||||
#ifdef REFERENCE_TRACKING
|
||||
enable_reference_tracking()
|
||||
|
||||
Reference in New Issue
Block a user