mirror of
https://github.com/PolarisSS13/Polaris.git
synced 2025-12-25 17:42:26 +00:00
Updates the atom_pool, now datum_pool, to handle any datum object.
Makes the garbage collector similarly robust. Continues the whole Destroy/qdel porting.
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
var/datum/controller/process/garbage_collector/garbage_collector
|
||||
var/list/delayed_garbage = list()
|
||||
|
||||
// #define GC_DEBUG 1
|
||||
#define GC_DEBUG 1
|
||||
/datum/controller/process/garbage_collector
|
||||
var/garbage_collect = 1 // Whether or not to actually do work
|
||||
var/collection_timeout = 300 //deciseconds to wait to let running procs finish before we just say fuck it and force del() the object
|
||||
var/max_checks_multiplier = 5 //multiplier (per-decisecond) for calculating max number of tests per tick. These tests check if our GC'd objects are actually GC'd
|
||||
var/max_forcedel_multiplier = 1 //multiplier (per-decisecond) for calculating max number of force del() calls per tick.
|
||||
@@ -16,14 +18,21 @@ var/datum/controller/process/garbage_collector/garbage_collector
|
||||
|
||||
/datum/controller/process/garbage_collector/setup()
|
||||
name = "garbage"
|
||||
schedule_interval = 20 // every 2 seconds
|
||||
schedule_interval = 6 SECONDS
|
||||
|
||||
if(!garbage_collector)
|
||||
garbage_collector = src
|
||||
|
||||
/datum/controller/process/garbage_collector/doWork()
|
||||
dels = 0
|
||||
for(var/garbage in delayed_garbage)
|
||||
qdel(garbage)
|
||||
delayed_garbage.Cut()
|
||||
delayed_garbage = null
|
||||
|
||||
/datum/controller/process/garbage_collector/doWork()
|
||||
if(!garbage_collect)
|
||||
return
|
||||
|
||||
dels = 0
|
||||
var/time_to_kill = world.time - collection_timeout // Anything qdel() but not GC'd BEFORE this time needs to be manually del()
|
||||
var/checkRemain = max_checks_multiplier * schedule_interval
|
||||
var/maxDels = max_forcedel_multiplier * schedule_interval
|
||||
@@ -31,21 +40,21 @@ var/datum/controller/process/garbage_collector/garbage_collector
|
||||
while(destroyed.len && --checkRemain >= 0)
|
||||
if(dels >= maxDels)
|
||||
#ifdef GC_DEBUG
|
||||
testing("GC: Reached max force dels per tick [dels] vs [GC_FORCE_DEL_PER_TICK]")
|
||||
testing("GC: Reached max force dels per tick [dels] vs [maxDels]")
|
||||
#endif
|
||||
break // Server's already pretty pounded, everything else can wait 2 seconds
|
||||
var/refID = destroyed[1]
|
||||
var/GCd_at_time = destroyed[refID]
|
||||
if(GCd_at_time > time_to_kill)
|
||||
#ifdef GC_DEBUG
|
||||
testing("GC: [refID] not old enough, breaking at [world.time] for [GCd_at_time - time_to_kill] deciseconds until [GCd_at_time + GC_COLLECTION_TIMEOUT]")
|
||||
testing("GC: [refID] not old enough, breaking at [world.time] for [GCd_at_time - time_to_kill] deciseconds until [GCd_at_time + collection_timeout]")
|
||||
#endif
|
||||
break // Everything else is newer, skip them
|
||||
var/atom/A = locate(refID)
|
||||
#ifdef GC_DEBUG
|
||||
testing("GC: [refID] old enough to test: GCd_at_time: [GCd_at_time] time_to_kill: [time_to_kill] current: [world.time]")
|
||||
#endif
|
||||
if(A && A.gc_destroyed == GCd_at_time) // So if something else coincidently gets the same ref, it's not deleted by mistake
|
||||
if(A && A.gcDestroyed == GCd_at_time) // So if something else coincidently gets the same ref, it's not deleted by mistake
|
||||
// Something's still referring to the qdel'd object. Kill it.
|
||||
testing("GC: -- \ref[A] | [A.type] was unable to be GC'd and was deleted --")
|
||||
logging["[A.type]"]++
|
||||
@@ -56,15 +65,14 @@ var/datum/controller/process/garbage_collector/garbage_collector
|
||||
testing("GC: [refID] properly GC'd at [world.time] with timeout [GCd_at_time]")
|
||||
#endif
|
||||
destroyed.Cut(1, 2)
|
||||
scheck()
|
||||
|
||||
/datum/controller/process/garbage_collector/proc/AddTrash(datum/A)
|
||||
if(!istype(A) || !isnull(A.gc_destroyed))
|
||||
if(!istype(A) || !isnull(A.gcDestroyed))
|
||||
return
|
||||
#ifdef GC_DEBUG
|
||||
testing("GC: AddTrash([A.type])")
|
||||
testing("GC: AddTrash(\ref[A] - [A.type])")
|
||||
#endif
|
||||
A.gc_destroyed = world.time
|
||||
A.gcDestroyed = world.time
|
||||
destroyed -= "\ref[A]" // Removing any previous references that were GC'd so that the current object will be at the end of the list.
|
||||
destroyed["\ref[A]"] = world.time
|
||||
|
||||
@@ -74,18 +82,39 @@ var/datum/controller/process/garbage_collector/garbage_collector
|
||||
/proc/qdel(var/datum/A)
|
||||
if(!A)
|
||||
return
|
||||
if(istype(A, /list))
|
||||
var/list/L = A
|
||||
for(var/E in L)
|
||||
qdel(E)
|
||||
return
|
||||
|
||||
if(!istype(A))
|
||||
//warning("qdel() passed object of type [A.type]. qdel() can only handle /datum types.")
|
||||
del(A)
|
||||
garbage_collector.dels++
|
||||
else if(isnull(A.gc_destroyed))
|
||||
// Let our friend know they're about to get fucked up.
|
||||
else if(isnull(A.gcDestroyed))
|
||||
// Let our friend know they're about to get collected
|
||||
. = !A.Destroy()
|
||||
if(. && A)
|
||||
A.finalize_qdel()
|
||||
|
||||
/datum/proc/finalize_qdel()
|
||||
garbage_collector.AddTrash(src)
|
||||
del(src)
|
||||
|
||||
/atom/finalize_qdel()
|
||||
if(garbage_collector)
|
||||
garbage_collector.AddTrash(src)
|
||||
else
|
||||
delayed_garbage |= src
|
||||
|
||||
/icon/finalize_qdel()
|
||||
del(src)
|
||||
|
||||
/imagine/finalize_qdel()
|
||||
del(src)
|
||||
|
||||
/mob/finalize_qdel()
|
||||
del(src)
|
||||
|
||||
/turf/finalize_qdel()
|
||||
del(src)
|
||||
@@ -97,11 +126,18 @@ var/datum/controller/process/garbage_collector/garbage_collector
|
||||
tag = null
|
||||
return
|
||||
|
||||
/datum/var/gc_destroyed //Time when this object was destroyed.
|
||||
|
||||
#define TESTING 1
|
||||
#ifdef TESTING
|
||||
/client/var/running_find_references
|
||||
|
||||
/mob/verb/create_thing()
|
||||
set category = "Debug"
|
||||
set name = "Create Thing"
|
||||
|
||||
var/path = input("Enter path")
|
||||
var/atom/thing = new path(loc)
|
||||
thing.find_references()
|
||||
|
||||
/atom/verb/find_references()
|
||||
set category = "Debug"
|
||||
set name = "Find References"
|
||||
@@ -120,8 +156,8 @@ var/datum/controller/process/garbage_collector/garbage_collector
|
||||
return
|
||||
|
||||
// Remove this object from the list of things to be auto-deleted.
|
||||
if(garbage)
|
||||
garbage.destroyed -= "\ref[src]"
|
||||
if(garbage_collector)
|
||||
garbage_collector.destroyed -= "\ref[src]"
|
||||
|
||||
usr.client.running_find_references = type
|
||||
testing("Beginning search for references to a [type].")
|
||||
@@ -147,13 +183,13 @@ var/datum/controller/process/garbage_collector/garbage_collector
|
||||
|
||||
/client/verb/purge_all_destroyed_objects()
|
||||
set category = "Debug"
|
||||
if(garbage)
|
||||
while(garbage.destroyed.len)
|
||||
var/datum/o = locate(garbage.destroyed[1])
|
||||
if(istype(o) && o.gc_destroyed)
|
||||
if(garbage_collector)
|
||||
while(garbage_collector.destroyed.len)
|
||||
var/datum/o = locate(garbage_collector.destroyed[1])
|
||||
if(istype(o) && o.gcDestroyed)
|
||||
del(o)
|
||||
garbage.dels++
|
||||
garbage.destroyed.Cut(1, 2)
|
||||
garbage_collector.dels++
|
||||
garbage_collector.destroyed.Cut(1, 2)
|
||||
#endif
|
||||
|
||||
#ifdef GC_DEBUG
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
if(!istype(C.mob, /mob/dead))
|
||||
log_access("AFK: [key_name(C)]")
|
||||
C << "<SPAN CLASS='warning'>You have been inactive for more than 10 minutes and have been disconnected.</SPAN>"
|
||||
del(C)
|
||||
del(C) // Don't qdel, cannot override finalize_qdel behaviour for clients.
|
||||
|
||||
scheck()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user