Skip to content

Garbage, qdel, and Destroy

Lohikar edited this page Jul 31, 2017 · 7 revisions

A new garbage collector has been introduced with SMC, this comes with new features for Destroy() as well as an enforced requirement to return parent in Destroy().

Basic Usage

The basic purpose of Destroy() is to clean up all references to the source object and to then return a garbage collection hint (generally done by returning the parent). Most of the time this should be done by putting return ..() at the end of your Destroy() proc, though it generally does not matter. If you do not return parent, you must still call it & you must return a hint. If applicable, Destroy() should also queue the deletion of child objects that are attached to the main object. Destroy() should never transform an object or create more objects (like mechs do).

This is how most Destroy() procs should generally be structured:

/obj/mything/Destroy()
	some_global_list_of_mythings -= src
	return ..()

Advanced Usage

The garbage collector also understands deletion hints. Most of the time you should not need these, but they can be used when objects require special deletion behavior, such as hard-deletion or deletion immortality. These are the hints that are understood:

Hint Behavior
QDEL_HINT_QUEUE Handle deletion normally. This is the default, you generally shouldn't need to manually specify this.
QDEL_HINT_LETMELIVE Do not delete on non-forced qdel. If you use this hint, you must respect force deletions. The GC will ignore this hint and complain if it is returned on force-delete.
QDEL_HINT_IWILLGC This object will handle GC itself and the GC should leave it alone. Functionally the same as LETMELIVE. Returning this hint will cause the GC to not check up on it to see if it deleted, and as such it will not be queued & use GC resources. Objects that use this hint do not need to obey force, but this hint should not be used to make objects that are immortal to force-delete.
QDEL_HINT_HARDDEL Hard-delete this object instead of attempting to GC it. Garbage will wait until the next tick where it has free processing time to delete. Can be expensive, avoid usage if possible.
QDEL_HINT_HARDDEL_NOW Hard-deletes this object ASAP (within the same stack as qdel). Works even if the garbage collector is not running or is non-responsive. Can be expensive, avoid usage if possible.
QDEL_HINT_FINDREFERENCE Functionally identical to QDEL_HINT_QUEUE, except the GC will run find-references on del if TESTING is defined. In a non-testing compile environment, has no special behavior. Be warned that find-references can take upwards of 10 minutes to run, during which it will cause a lot of lag.

To use a hint, return it instead of returning parent. You must still call parent. If you're using QDEL_HINT_LETMELIVE, you must respect the force parameter. If you do not respect the force parameter, the GC will delete you anyways on force delete and make noise in server logs. Admin-delete uses force-delete.

Example of a Destroy() with a hint:

/obj/mything/myotherthing/Destroy()
	some_global_list_of_myotherthings -= src
	..()
	return QDEL_HINT_HARDDEL

Example of a Destroy() with a force-respecting hint:

/obj/mything/myotherotherthing/Destroy(force = FALSE)
	if (!force)
		world << "Something tried to delete [src]!"
		return QDEL_HINT_LETMELIVE

	// force-deletion
	world << "[src] force-deleted."
	return ..()

Force Deletion

qdel() has a new optional parameter that follows the thing-to-be-deleted: force. If force is TRUE, the object is force-deleted. Force delete behavior is dependent on the object being deleted, but it generally will delete objects that return immortality hints such as LETMELIVE and sometimes (implementation dependent) cause IWILLGC objects to instead return QUEUE so that their deletion is confirmed.

GC Timeout

Objects that return a QUEUE hint are added to SSgarbage's queue. SSgarbage will give BYOND 5 minutes (by default) to GC the object before it intervenes. If an object has not been GC'd by the timeout period, SSgarbage will assume the object is not going to GC and will hard-delete it when it has spare CPU time. SSgarbage can only run one hard-delete per garbage tick, and hard-deletions may postpone further garbage ticks depending on how expensive the hard-delete was.

Reference Types

There are three types of datum references in this codebase: hard refs (just a normal BYOND var), soft refs (a naked locate()able string), and weak refs (a /datum/weakref). Hard refs will block GC, but soft refs and weak refs will not. In terms of speed, hard-refs are faster than soft-refs which are faster than weak-refs.

Hard-refs are the only ones that can be used to access variables on an object, but the other two can be converted into hard-refs.

Soft Refs

These are strings generated by SOFTREF(datum) or "\ref[datum]". They can be fed to locate() to convert them into a hard ref, but it is not guaranteed that they will still point at the same object they did when they were created - the object must be verified before use.

Usage

var/datum/mydatum = new
var/myref = SOFTREF(mydatum)
mydatum = null

var/datum/the_datum = locate(myref)
if (istype(the_datum))
	world << "Datum is valid!
else
	world << "Datum is invalid!"

Weak Refs

These are instances of /datum/weakref, as generated by the WEAKREF(datum) macro. /datum/weakref has a call resolve() which will return a hard ref to the original datum if it still exists and hasn't been marked for del by the GC, or null otherwise. These will handle validation for you, so a datum returned by resolve() is guaranteed to be the same datum originally given to WEAKREF(datum).

Note: Do not delete/qdelete the weakref datum! It will automatically be cleaned up when it is no longer in use.

Usage

var/datum/mydatum = new
var/datum/weakref/myref = WEAKREF(mydatum)
mydatum = null

var/datum/the_datum = myref.resolve()
if (the_datum)
	world << "Datum is valid!"
else
	world << "Datum is invalid!"

Standards and Guidelines

A collection of standards and guidelines applied to the codebase.

Common API Documentation

Documentation regarding common APIs which speed up feature implementation and should be known by all coders.

Less Common APIs

Documentation for less used APIs that are not often needed.

Subsystems

Documentation regarding our implementation of StonedMC (SMC).

Decrepit

Decrepit or unused systems.

  • Dynamic Maps (Not to be confused with the newer away mission implementation.)
Clone this wiki locally