diff --git a/code/__DEFINES/qdel.dm b/code/__DEFINES/qdel.dm index 0d20e14a743..14fd6ea0e36 100644 --- a/code/__DEFINES/qdel.dm +++ b/code/__DEFINES/qdel.dm @@ -8,6 +8,7 @@ #define QDEL_HINT_HARDDEL_NOW 4 //qdel should assume this object won't gc, and hard del it post haste. #define QDEL_HINT_FINDREFERENCE 5 //functionally identical to QDEL_HINT_QUEUE if TESTING is not enabled in _compiler_options.dm. //if TESTING is enabled, qdel will call this object's find_references() verb. +#define QDEL_HINT_IFFAIL_FINDREFERENCE 6 //Above but only if gc fails. //defines for the gc_destroyed var #define GC_QUEUE_PREQUEUE 1 diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index 5e336033b6e..05dab2bd97b 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -25,6 +25,10 @@ SUBSYSTEM_DEF(garbage) //Queue var/list/queues + #ifdef TESTING + var/list/reference_find_on_fail = list() + #endif + /datum/controller/subsystem/garbage/PreInit() queues = new(GC_QUEUE_COUNT) @@ -154,6 +158,9 @@ SUBSYSTEM_DEF(garbage) ++gcedlasttick ++totalgcs pass_counts[level]++ + #ifdef TESTING + reference_find_on_fail -= refID //It's deleted we don't care anymore. + #endif if(MC_TICK_CHECK) break continue @@ -162,8 +169,14 @@ SUBSYSTEM_DEF(garbage) fail_counts[level]++ switch(level) if(GC_QUEUE_CHECK) + #ifdef TESTING + if(reference_find_on_fail[refID]) + D.find_references() #ifdef GC_FAILURE_HARD_LOOKUP - D.find_references() + else + D.find_references() + #endif + reference_find_on_fail -= refID #endif var/type = D.type var/datum/qdel_item/I = items[type] @@ -263,6 +276,11 @@ SUBSYSTEM_DEF(garbage) /datum/qdel_item/New(mytype) name = "[mytype]" +#ifdef TESTING +/proc/qdel_and_find_ref_if_fail(datum/D, force = FALSE) + SSgarbage.reference_find_on_fail["\ref[D]"] = TRUE + qdel(D, force) +#endif // Should be treated as a replacement for the 'del' keyword. // Datums passed to this will be given a chance to clean up references to allow the GC to collect them. @@ -319,6 +337,11 @@ SUBSYSTEM_DEF(garbage) #ifdef TESTING D.find_references() #endif + if(QDEL_HINT_IFFAIL_FINDREFERENCE) + SSgarbage.PreQueue(D) + #ifdef TESTING + SSgarbage.reference_find_on_fail["\ref[D]"] = TRUE + #endif else #ifdef TESTING if(!I.no_hint) @@ -388,10 +411,17 @@ SUBSYSTEM_DEF(garbage) set name = "qdel() then Find References" set src in world - qdel(src) + qdel(src, TRUE) //Force. if(!running_find_references) find_references(TRUE) +/datum/verb/qdel_then_if_fail_find_references() + set category = "Debug" + set name = "qdel() then Find References if GC failure" + set src in world + + qdel_and_find_ref_if_fail(src, TRUE) + /datum/proc/DoSearchVar(X, Xname, recursive_limit = 64) if(usr && usr.client && !usr.client.running_find_references) return diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index 748e5ac9bb6..0a6ea8c784d 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -1,6 +1,4 @@ /obj/machinery/bodyscanner - var/mob/living/carbon/occupant - var/locked name = "body scanner" icon = 'icons/obj/Cryogenic2.dmi' icon_state = "bodyscanner-open" @@ -11,6 +9,16 @@ active_power_usage = 2500 light_color = "#00FF00" + var/obj/machinery/body_scanconsole/console = null + var/mob/living/carbon/occupant = null + var/locked + +/obj/machinery/bodyscanner/Destroy() + go_out() + if(console) + console.connected = null + console = null + return ..() /obj/machinery/bodyscanner/power_change() ..() @@ -207,9 +215,6 @@ return /obj/machinery/body_scanconsole - var/obj/machinery/bodyscanner/connected - var/delete - var/temphtml name = "Body Scanner Console" icon = 'icons/obj/Cryogenic2.dmi' icon_state = "bodyscannerconsole" @@ -218,6 +223,9 @@ dir = 8 idle_power_usage = 250 active_power_usage = 500 + var/obj/machinery/bodyscanner/connected = null + var/delete + var/temphtml var/printing = null var/printing_text = null var/known_implants = list(/obj/item/weapon/implant/chem, /obj/item/weapon/implant/death_alarm, /obj/item/weapon/implant/mindshield, /obj/item/weapon/implant/tracking, /obj/item/weapon/implant/health) @@ -243,6 +251,12 @@ RefreshParts() findscanner() +/obj/machinery/body_scanconsole/Destroy() + if(connected) + connected.console = null + connected = null + return ..() + /obj/machinery/body_scanconsole/ex_act(severity) switch(severity) if(1.0) @@ -269,15 +283,13 @@ return /obj/machinery/body_scanconsole/proc/findscanner() - var/obj/machinery/bodyscanner/bodyscannernew = null - // Loop through every direction for(dir in list(NORTH,EAST,SOUTH,WEST)) // Try to find a scanner in that direction var/temp = locate(/obj/machinery/bodyscanner, get_step(src, dir)) - if(!isnull(temp)) - bodyscannernew = temp - src.connected = bodyscannernew - return + if(temp) + connected = temp + connected.console = src + break /obj/machinery/body_scanconsole/attackby(var/obj/item/weapon/G as obj, var/mob/user as mob, params)