Add cleanup hooking system (closes #24)

This commit is contained in:
JeremyStar™ 2024-04-14 23:48:53 +02:00
parent 0123618214
commit 15d78eb0d7
Signed by: JeremyStarTM
GPG key ID: E366BAEF67E4704D
2 changed files with 74 additions and 3 deletions

View file

@ -36,6 +36,11 @@ Used internally for loading, managing and unloading modules.
Do not modify this. Do not modify this.
::: :::
Stores the path to CORE's installation directory. Stores the path to CORE's installation directory.
### *Dictionary* <u>cleanup_hooks</u> = *{}*
:::danger[Don't modify]
Do not modify this.
:::
Contains a list of all registered cleanup hooks.
### *Dictionary* <u>custom_modules</u> = *{}* ### *Dictionary* <u>custom_modules</u> = *{}*
### *void* <u>_ready</u>() ### *void* <u>_ready</u>()
:::danger[Don't modify] :::danger[Don't modify]
@ -96,6 +101,13 @@ Applies the a configuration.
### *void* <u>cleanup</u>() ### *void* <u>cleanup</u>()
Makes sure that CORE does not leak memory on shutdown/unload. \ Makes sure that CORE does not leak memory on shutdown/unload. \
Unloads all custom modules, built-in modules, frees any of CORE's classes and lastly itself. Unloads all custom modules, built-in modules, frees any of CORE's classes and lastly itself.
### *int* <u>register_cleanup_hook</u>(*Callable* <u>callable</u>)
Registers a new cleanup hook. \
Returns the hook id.
### *bool* <u>unregister_cleanup_hook_by_id</u>(*int* <u>id</u>)
Unregisters a cleanup hook by it's id.
### *bool* <u>unregister_cleanup_hook_by_ref</u>(*Callable* <u>callable</u>)
Unregisters a cleanup hook by it's reference.
### *bool* <u>is_devmode</u>() ### *bool* <u>is_devmode</u>()
Returns if the framework is in development mode. Returns if the framework is in development mode.
### *String* <u>get_format_string</u>(*String* <u>string</u>) ### *String* <u>get_format_string</u>(*String* <u>string</u>)

View file

@ -57,6 +57,9 @@ var storage: CoreBaseModule
## Stores the path to CORE's installation directory.[br] ## Stores the path to CORE's installation directory.[br]
## [b]Danger: [i]Don't modify this.[/i][/b] ## [b]Danger: [i]Don't modify this.[/i][/b]
var basepath: String var basepath: String
## Contains a list of all registered cleanup hooks.[br]
## [b]Danger: [i]Don't modify this.[/i][/b]
var cleanup_hooks: Dictionary = {}
## Contains a list of all loaded custom modules.[br] ## Contains a list of all loaded custom modules.[br]
## [b]Danger: [i]Don't modify this.[/i][/b] ## [b]Danger: [i]Don't modify this.[/i][/b]
var custom_modules: Dictionary = {} var custom_modules: Dictionary = {}
@ -223,24 +226,80 @@ func get_custom_module(module_name: String) -> CoreBaseModule:
return null return null
return custom_modules[module_name] return custom_modules[module_name]
# +++ etc ++ # +++ cleanup ++
## Makes sure that CORE does not leak memory on shutdown/unload.[br] ## Makes sure that CORE does not leak memory on shutdown/unload.[br]
## Unloads all custom modules, built-in modules, frees any of CORE's classes and lastly itself. ## Unloads all custom modules, built-in modules, frees any of CORE's classes and lastly itself.[br]
## Only call this function if you're sure that your application or game no longer uses the CORE Framework.
func cleanup() -> void: func cleanup() -> void:
loggeri.info("Cleaning up") loggeri.info("Cleaning up")
loggeri.verb("Calling cleanup hooks")
for hook in cleanup_hooks:
if !cleanup_hooks[hook].is_valid():
loggeri.error("Cleanup hook #" + str(hook) + " is invalid")
else:
loggeri.diag("Calling cleanup hook #" + str(hook))
await cleanup_hooks[hook].call()
loggeri.verb("Unregistering custom modules")
for module in custom_modules_node.get_children(): await unregister_custom_module(module.name) for module in custom_modules_node.get_children(): await unregister_custom_module(module.name)
loggeri.verb("Removing custom module support")
remove_child(custom_modules_node) remove_child(custom_modules_node)
custom_modules_node.queue_free() custom_modules_node.queue_free()
loggeri.verb("Unloading built-in modules")
var modules_reverse: Array[String] = modules.duplicate() var modules_reverse: Array[String] = modules.duplicate()
modules_reverse.reverse() modules_reverse.reverse()
for module in modules_reverse: for module in modules_reverse:
await get(module)._cleanup() await get(module)._cleanup()
get(module).loggeri.queue_free()
get(module).queue_free() get(module).queue_free()
print("Freeing configuration")
config.queue_free() config.queue_free()
await get_tree().process_frame await get_tree().process_frame
print("Freeing")
queue_free() queue_free()
# Generates a new cleanup hook id
func _generate_hook_id() -> int:
var id = randi()
if cleanup_hooks.has(id):
loggeri.warn("New cleanup hook id #" + str(id) + " is already taken")
return _generate_hook_id()
elif id == -1:
loggeri.warn("Invalid cleanup hook id '-1'")
return _generate_hook_id()
return id
## Registers a new cleanup hook.[br]
## Returns the hook id.
func register_cleanup_hook(callable: Callable) -> int:
if !callable.is_valid():
loggeri.error("Could not add cleanup hook: Callable is not valid")
return -1
var id: int = _generate_hook_id()
loggeri.verb("Adding new cleanup hook #" + str(id))
cleanup_hooks.merge({ id: callable })
return id
## Unregisters a cleanup hook by it's id.
func unregister_cleanup_hook_by_id(id: int) -> bool:
if !cleanup_hooks.has(id):
loggeri.error("Could not remove cleanup hook (id): Hook #" + str(id) + " does not exist")
return false
loggeri.verb("Removed cleanup hook #" + str(id) + " (id)")
cleanup_hooks.erase(id)
return true
## Unregisters a cleanup hook by it's reference.
func unregister_cleanup_hook_by_ref(callable: Callable) -> bool:
var id: Variant = cleanup_hooks.find_key(callable)
if id == null:
loggeri.error("Could not remove cleanup hook (ref): Could not find a matching hook")
return false
if typeof(id) != TYPE_INT: await loggeri.crash("Could not remove cleanup hook (ref): find_key did not return an integer (returned '" + str(id) + "')")
loggeri.verb("Removed cleanup hook #" + str(id) + " (ref)")
cleanup_hooks.erase(id)
return true
# +++ etc +++
## Returns if the framework is in development mode. ## Returns if the framework is in development mode.
func is_devmode() -> bool: func is_devmode() -> bool:
return config.development return config.development