Transformed the machinery processor into an StonedMC subsystem

* This is PHASE 1 of a multi-phase conversion.  In this first phase we implement the subsystem, but leave it processing the existing global list variables.  In the next phase we will switch to use datum variables in the subsystem.  The main reason for splitting into two phases is ease of code review; change the meaningful code without the hundreds of machines -> SSmachines.machinery substitutions.
* We did declare macros for adding/removing things to the processing lists, and convert everywhere to use the macros.
* Added var/is_processing to /datum to keep track of whether an instance is already in a processing list (prevents it being in the list twice!) and also debugging, making sure its not in two lists etc.
* NOTE: The global machines list is **no longer sorted** for performance reasons.  As far as I know, the only module that actually ever cared was cameras.   Our camera system already handles its own sorting in the cameranets anyway, so it should no longer be needed.
This commit is contained in:
Leshana
2017-12-28 15:20:16 -05:00
parent 66e9d9cfdf
commit a97a574278
16 changed files with 237 additions and 35 deletions

View File

@@ -180,7 +180,6 @@
/obj/machinery/atmospherics/tvalve/process() /obj/machinery/atmospherics/tvalve/process()
..() ..()
. = PROCESS_KILL . = PROCESS_KILL
//machines.Remove(src)
return return

View File

@@ -1,6 +1,6 @@
var/global/list/datum/pipe_network/pipe_networks = list() var/global/list/datum/pipe_network/pipe_networks = list() // TODO - Move into SSmachines
datum/pipe_network /datum/pipe_network
var/list/datum/gas_mixture/gases = list() //All of the gas_mixtures continuously connected in this network var/list/datum/gas_mixture/gases = list() //All of the gas_mixtures continuously connected in this network
var/volume = 0 //caches the total volume for atmos machines to use in gas calculations var/volume = 0 //caches the total volume for atmos machines to use in gas calculations
@@ -11,13 +11,8 @@ datum/pipe_network
var/update = 1 var/update = 1
//var/datum/gas_mixture/air_transient = null //var/datum/gas_mixture/air_transient = null
New()
//air_transient = new()
..()
Destroy() Destroy()
pipe_networks -= src STOP_PROCESSING_PIPENET(src)
for(var/datum/pipeline/line_member in line_members) for(var/datum/pipeline/line_member in line_members)
line_member.network = null line_member.network = null
for(var/obj/machinery/atmospherics/normal_member in normal_members) for(var/obj/machinery/atmospherics/normal_member in normal_members)
@@ -41,13 +36,14 @@ datum/pipe_network
if(!start_normal) if(!start_normal)
qdel(src) qdel(src)
return
start_normal.network_expand(src, reference) start_normal.network_expand(src, reference)
update_network_gases() update_network_gases()
if((normal_members.len>0)||(line_members.len>0)) if((normal_members.len>0)||(line_members.len>0))
pipe_networks += src START_PROCESSING_PIPENET(src)
else else
qdel(src) qdel(src)

View File

@@ -10,6 +10,19 @@
Master.current_ticklimit = original_tick_limit;\ Master.current_ticklimit = original_tick_limit;\
} }
// Boilerplate code for multi-step processors. See machines.dm for example use.
#define INTERNAL_PROCESS_STEP(this_step, initial_step, proc_to_call, cost_var, next_step)\
if(current_step == this_step || (initial_step && !resumed)) /* So we start at step 1 if not resumed.*/ {\
timer = TICK_USAGE;\
proc_to_call(resumed);\
cost_var = MC_AVERAGE(cost_var, TICK_DELTA_TO_MS(TICK_USAGE - timer));\
if(state != SS_RUNNING){\
return;\
}\
resumed = 0;\
current_step = next_step;\
}
// Used to smooth out costs to try and avoid oscillation. // Used to smooth out costs to try and avoid oscillation.
#define MC_AVERAGE_FAST(average, current) (0.7 * (average) + 0.3 * (current)) #define MC_AVERAGE_FAST(average, current) (0.7 * (average) + 0.3 * (current))
#define MC_AVERAGE(average, current) (0.8 * (average) + 0.2 * (current)) #define MC_AVERAGE(average, current) (0.8 * (average) + 0.2 * (current))

View File

@@ -105,3 +105,37 @@ var/list/restricted_camera_networks = list(NETWORK_ERT,NETWORK_MERCENARY,"Secret
#define ATMOS_DEFAULT_VOLUME_FILTER 200 // L. #define ATMOS_DEFAULT_VOLUME_FILTER 200 // L.
#define ATMOS_DEFAULT_VOLUME_MIXER 200 // L. #define ATMOS_DEFAULT_VOLUME_MIXER 200 // L.
#define ATMOS_DEFAULT_VOLUME_PIPE 70 // L. #define ATMOS_DEFAULT_VOLUME_PIPE 70 // L.
// Fancy-pants START/STOP_PROCESSING() macros that lets us custom define what the list is.
#define START_PROCESSING_IN_LIST(DATUM, LIST) \
if (DATUM.is_processing) {\
if(DATUM.is_processing != #LIST)\
{\
crash_with("Failed to start processing. [log_info_line(DATUM)] is already being processed by [DATUM.is_processing] but queue attempt occured on [#LIST]."); \
}\
} else {\
DATUM.is_processing = #LIST;\
LIST += DATUM;\
}
#define STOP_PROCESSING_IN_LIST(DATUM, LIST) \
if(DATUM.is_processing) {\
if(LIST.Remove(DATUM)) {\
DATUM.is_processing = null;\
} else {\
crash_with("Failed to stop processing. [log_info_line(DATUM)] is being processed by [is_processing] and not found in SSmachines.[#LIST]"); \
}\
}
// Note - I would prefer these be defined machines.dm, but some are used prior in file order. ~Leshana
#define START_MACHINE_PROCESSING(Datum) START_PROCESSING_IN_LIST(Datum, global.machines)
#define STOP_MACHINE_PROCESSING(Datum) STOP_PROCESSING_IN_LIST(Datum, global.machines)
#define START_PROCESSING_PIPENET(Datum) START_PROCESSING_IN_LIST(Datum, global.pipe_networks)
#define STOP_PROCESSING_PIPENET(Datum) STOP_PROCESSING_IN_LIST(Datum, global.pipe_networks)
#define START_PROCESSING_POWERNET(Datum) START_PROCESSING_IN_LIST(Datum, global.powernets)
#define STOP_PROCESSING_POWERNET(Datum) STOP_PROCESSING_IN_LIST(Datum, global.powernets)
#define START_PROCESSING_POWER_OBJECT(Datum) START_PROCESSING_IN_LIST(Datum, global.processing_power_items)
#define STOP_PROCESSING_POWER_OBJECT(Datum) STOP_PROCESSING_IN_LIST(Datum, global.processing_power_items)

View File

@@ -12,4 +12,8 @@
var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_GAME, RUNLEVEL_POSTGAME) var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_GAME, RUNLEVEL_POSTGAME)
#define RUNLEVEL_FLAG_TO_INDEX(flag) (log(2, flag) + 1) // Convert from the runlevel bitfield constants to index in runlevel_flags list #define RUNLEVEL_FLAG_TO_INDEX(flag) (log(2, flag) + 1) // Convert from the runlevel bitfield constants to index in runlevel_flags list
#define INIT_ORDER_LIGHTING 0 // Subsystem init_order, from highest priority to lowest priority
// Subsystems shutdown in the reverse of the order they initialize in
// The numbers just define the ordering, they are meaningless otherwise.
#define INIT_ORDER_MACHINES 10
#define INIT_ORDER_LIGHTING 0

View File

@@ -0,0 +1,160 @@
#define SSMACHINES_PIPENETS 1
#define SSMACHINES_MACHINERY 2
#define SSMACHINES_POWERNETS 3
#define SSMACHINES_POWER_OBJECTS 4
//
// SSmachines subsystem - Processing machines, pipenets, and powernets!
//
// Implementation Plan:
// PHASE 1 - Add subsystem using the existing global list vars
// PHASE 2 - Move the global list vars into the subsystem.
SUBSYSTEM_DEF(machines)
name = "Machines"
priority = 100
init_order = INIT_ORDER_MACHINES
flags = SS_KEEP_TIMING
runlevels = RUNLEVEL_GAME|RUNLEVEL_POSTGAME
var/current_step = SSMACHINES_PIPENETS
var/cost_pipenets = 0
var/cost_machinery = 0
var/cost_powernets = 0
var/cost_power_objects = 0
// TODO - PHASE 2 - Switch these from globals to instance vars
// var/list/pipenets = list()
// var/list/machinery = list()
// var/list/powernets = list()
// var/list/power_objects = list()
var/list/current_run = list()
/datum/controller/subsystem/machines/Initialize(timeofday)
SSmachines.makepowernets()
// TODO - Move world-creation time setup of atmos machinery and pipenets to here
fire()
..()
/datum/controller/subsystem/machines/fire(resumed = 0)
var/timer = TICK_USAGE
INTERNAL_PROCESS_STEP(SSMACHINES_PIPENETS,TRUE,process_pipenets,cost_pipenets,SSMACHINES_MACHINERY)
INTERNAL_PROCESS_STEP(SSMACHINES_MACHINERY,FALSE,process_machinery,cost_machinery,SSMACHINES_POWERNETS)
INTERNAL_PROCESS_STEP(SSMACHINES_POWERNETS,FALSE,process_powernets,cost_powernets,SSMACHINES_POWER_OBJECTS)
INTERNAL_PROCESS_STEP(SSMACHINES_POWER_OBJECTS,FALSE,process_power_objects,cost_power_objects,SSMACHINES_PIPENETS)
// rebuild all power networks from scratch - only called at world creation or by the admin verb
// The above is a lie. Turbolifts also call this proc.
/datum/controller/subsystem/machines/proc/makepowernets()
// TODO - check to not run while in the middle of a tick!
for(var/datum/powernet/PN in powernets)
qdel(PN)
powernets.Cut()
for(var/obj/structure/cable/PC in cable_list)
if(!PC.powernet)
var/datum/powernet/NewPN = new()
NewPN.add_cable(PC)
propagate_network(PC,PC.powernet)
/datum/controller/subsystem/machines/stat_entry()
var/msg = list()
msg += "C:{"
msg += "PI:[round(cost_pipenets,1)]|"
msg += "MC:[round(cost_machinery,1)]|"
msg += "PN:[round(cost_powernets,1)]|"
msg += "PO:[round(cost_power_objects,1)]"
msg += "} "
msg += "PI:[global.pipe_networks.len]|"
msg += "MC:[global.machines.len]|"
msg += "PN:[global.powernets.len]|"
msg += "PO:[global.processing_power_items.len]|"
msg += "MC/MS:[round((cost ? global.machines.len/cost_machinery : 0),0.1)]"
..(jointext(msg, null))
/datum/controller/subsystem/machines/proc/process_pipenets(resumed = 0)
if (!resumed)
src.current_run = global.pipe_networks.Copy()
//cache for sanic speed (lists are references anyways)
var/list/current_run = src.current_run
while(current_run.len)
var/datum/pipe_network/PN = current_run[current_run.len]
current_run.len--
if(istype(PN) && !QDELETED(PN))
PN.process(wait)
else
global.pipe_networks.Remove(PN)
if(!QDELETED(PN))
PN.is_processing = null
if(MC_TICK_CHECK)
return
/datum/controller/subsystem/machines/proc/process_machinery(resumed = 0)
if (!resumed)
src.current_run = global.machines.Copy()
var/list/current_run = src.current_run
while(current_run.len)
var/obj/machinery/M = current_run[current_run.len]
current_run.len--
if(istype(M) && !QDELETED(M) && !(M.process(wait) == PROCESS_KILL))
if(M.use_power)
M.auto_use_power()
else
global.machines.Remove(M)
if(!QDELETED(M))
M.is_processing = null
if(MC_TICK_CHECK)
return
/datum/controller/subsystem/machines/proc/process_powernets(resumed = 0)
if (!resumed)
src.current_run = global.powernets.Copy()
var/list/current_run = src.current_run
while(current_run.len)
var/datum/powernet/PN = current_run[current_run.len]
current_run.len--
if(istype(PN) && !QDELETED(PN))
PN.reset(wait)
else
global.powernets.Remove(PN)
if(!QDELETED(PN))
PN.is_processing = null
if(MC_TICK_CHECK)
return
// Actually only processes power DRAIN objects.
// Currently only used by powersinks. These items get priority processed before machinery
/datum/controller/subsystem/machines/proc/process_power_objects(resumed = 0)
if (!resumed)
src.current_run = global.processing_power_items.Copy()
var/list/current_run = src.current_run
while(current_run.len)
var/obj/item/I = current_run[current_run.len]
current_run.len--
if(!I.pwr_drain(wait)) // 0 = Process Kill, remove from processing list.
global.processing_power_items.Remove(I)
I.is_processing = null
if(MC_TICK_CHECK)
return
/datum/controller/subsystem/machines/Recover()
// TODO - PHASE 2
// if (istype(SSmachines.pipenets))
// pipenets = SSmachines.pipenets
// if (istype(SSmachines.machinery))
// machinery = SSmachines.machinery
// if (istype(SSmachines.powernets))
// powernets = SSmachines.powernets
// if (istype(SSmachines.power_objects))
// power_objects = SSmachines.power_objects
#undef SSMACHINES_PIPENETS
#undef SSMACHINES_MACHINERY
#undef SSMACHINES_POWER
#undef SSMACHINES_POWER_OBJECTS

View File

@@ -6,6 +6,7 @@
/datum /datum
var/gc_destroyed //Time when this object was destroyed. var/gc_destroyed //Time when this object was destroyed.
var/weakref/weakref // Holder of weakref instance pointing to this datum var/weakref/weakref // Holder of weakref instance pointing to this datum
var/is_processing = FALSE // If this datum is in an MC processing list, this will be set to its name.
#ifdef TESTING #ifdef TESTING
var/tmp/running_find_references var/tmp/running_find_references

View File

@@ -203,12 +203,7 @@ var/global/list/engineering_networks = list(
/obj/machinery/camera/proc/upgradeMotion() /obj/machinery/camera/proc/upgradeMotion()
assembly.upgrades.Add(new /obj/item/device/assembly/prox_sensor(assembly)) assembly.upgrades.Add(new /obj/item/device/assembly/prox_sensor(assembly))
setPowerUsage() setPowerUsage()
if(!(src in machines)) START_MACHINE_PROCESSING(src)
if(!machinery_sort_required && ticker)
dd_insertObjectList(machines, src)
else
machines += src
machinery_sort_required = 1
update_coverage() update_coverage()
/obj/machinery/camera/proc/setPowerUsage() /obj/machinery/camera/proc/setPowerUsage()

View File

@@ -118,16 +118,12 @@ Class Procs:
..(l) ..(l)
if(d) if(d)
set_dir(d) set_dir(d)
if(!machinery_sort_required && ticker) START_MACHINE_PROCESSING(src)
dd_insertObjectList(machines, src)
else
machines += src
machinery_sort_required = 1
if(circuit) if(circuit)
circuit = new circuit(src) circuit = new circuit(src)
/obj/machinery/Destroy() /obj/machinery/Destroy()
machines -= src STOP_MACHINE_PROCESSING(src)
if(component_parts) if(component_parts)
for(var/atom/A in component_parts) for(var/atom/A in component_parts)
if(A.loc == src) // If the components are inside the machine, delete them. if(A.loc == src) // If the components are inside the machine, delete them.

View File

@@ -94,7 +94,7 @@
singulo.target = src singulo.target = src
icon_state = "[icontype]1" icon_state = "[icontype]1"
active = 1 active = 1
machines |= src START_MACHINE_PROCESSING(src)
if(user) if(user)
user << "<span class='notice'>You activate the beacon.</span>" user << "<span class='notice'>You activate the beacon.</span>"

View File

@@ -26,7 +26,7 @@
/obj/item/device/powersink/Destroy() /obj/item/device/powersink/Destroy()
processing_objects.Remove(src) processing_objects.Remove(src)
processing_power_items.Remove(src) STOP_PROCESSING_POWER_OBJECT(src)
..() ..()
/obj/item/device/powersink/attackby(var/obj/item/I, var/mob/user) /obj/item/device/powersink/attackby(var/obj/item/I, var/mob/user)
@@ -50,7 +50,7 @@
else else
if (mode == 2) if (mode == 2)
processing_objects.Remove(src) // Now the power sink actually stops draining the station's power if you unhook it. --NeoFite processing_objects.Remove(src) // Now the power sink actually stops draining the station's power if you unhook it. --NeoFite
processing_power_items.Remove(src) STOP_PROCESSING_POWER_OBJECT(src)
anchored = 0 anchored = 0
mode = 0 mode = 0
src.visible_message("<span class='notice'>[user] detaches [src] from the cable!</span>") src.visible_message("<span class='notice'>[user] detaches [src] from the cable!</span>")
@@ -74,14 +74,14 @@
mode = 2 mode = 2
icon_state = "powersink1" icon_state = "powersink1"
processing_objects.Add(src) processing_objects.Add(src)
processing_power_items.Add(src) START_PROCESSING_POWER_OBJECT(src)
if(2) //This switch option wasn't originally included. It exists now. --NeoFite if(2) //This switch option wasn't originally included. It exists now. --NeoFite
src.visible_message("<span class='notice'>[user] deactivates [src]!</span>") src.visible_message("<span class='notice'>[user] deactivates [src]!</span>")
mode = 1 mode = 1
set_light(0) set_light(0)
icon_state = "powersink0" icon_state = "powersink0"
processing_objects.Remove(src) processing_objects.Remove(src)
processing_power_items.Remove(src) STOP_PROCESSING_POWER_OBJECT(src)
/obj/item/device/powersink/pwr_drain() /obj/item/device/powersink/pwr_drain()
if(!attached) if(!attached)

View File

@@ -6,9 +6,9 @@
// Items that ask to be called every cycle. // Items that ask to be called every cycle.
var/global/datum/datacore/data_core = null var/global/datum/datacore/data_core = null
var/global/list/all_areas = list() var/global/list/all_areas = list()
var/global/list/machines = list() var/global/list/machines = list() // TODO - Move into SSmachines
var/global/list/processing_objects = list() var/global/list/processing_objects = list()
var/global/list/processing_power_items = list() var/global/list/processing_power_items = list() // TODO - Move into SSmachines
var/global/list/active_diseases = list() var/global/list/active_diseases = list()
var/global/list/med_hud_users = list() // List of all entities using a medical HUD. var/global/list/med_hud_users = list() // List of all entities using a medical HUD.
var/global/list/sec_hud_users = list() // List of all entities using a security HUD. var/global/list/sec_hud_users = list() // List of all entities using a security HUD.
@@ -107,7 +107,7 @@ var/list/IClog = list()
var/list/OOClog = list() var/list/OOClog = list()
var/list/adminlog = list() var/list/adminlog = list()
var/list/powernets = list() var/list/powernets = list() // TODO - Move into SSmachines
var/Debug2 = 0 var/Debug2 = 0
var/datum/debug/debugobj var/datum/debug/debugobj

View File

@@ -151,7 +151,7 @@ proc/cardinalrange(var/center)
/obj/machinery/am_shielding/proc/setup_core() /obj/machinery/am_shielding/proc/setup_core()
processing = 1 processing = 1
machines.Add(src) START_MACHINE_PROCESSING(src)
if(!control_unit) return if(!control_unit) return
control_unit.linked_cores.Add(src) control_unit.linked_cores.Add(src)
control_unit.reported_core_efficiency += efficiency control_unit.reported_core_efficiency += efficiency

View File

@@ -15,7 +15,7 @@
var/problem = 0 // If this is not 0 there is some sort of issue in the powernet. Monitors will display warnings. var/problem = 0 // If this is not 0 there is some sort of issue in the powernet. Monitors will display warnings.
/datum/powernet/New() /datum/powernet/New()
powernets += src START_PROCESSING_POWERNET(src)
..() ..()
/datum/powernet/Destroy() /datum/powernet/Destroy()
@@ -25,7 +25,7 @@
for(var/obj/machinery/power/M in nodes) for(var/obj/machinery/power/M in nodes)
nodes -= M nodes -= M
M.powernet = null M.powernet = null
powernets -= src STOP_PROCESSING_POWERNET(src)
return ..() return ..()
//Returns the amount of excess power (before refunding to SMESs) from last tick. //Returns the amount of excess power (before refunding to SMESs) from last tick.

View File

@@ -0,0 +1,4 @@
author: Leshana
delete-after: True
changes:
- tweak: "Convert the machinery controller to a StonedMC subsystem"

View File

@@ -158,7 +158,6 @@
#include "code\controllers\Processes\event.dm" #include "code\controllers\Processes\event.dm"
#include "code\controllers\Processes\game_master.dm" #include "code\controllers\Processes\game_master.dm"
#include "code\controllers\Processes\inactivity.dm" #include "code\controllers\Processes\inactivity.dm"
#include "code\controllers\Processes\machinery.dm"
#include "code\controllers\Processes\mob.dm" #include "code\controllers\Processes\mob.dm"
#include "code\controllers\Processes\nanoui.dm" #include "code\controllers\Processes\nanoui.dm"
#include "code\controllers\Processes\obj.dm" #include "code\controllers\Processes\obj.dm"
@@ -176,6 +175,7 @@
#include "code\controllers\subsystems\creation.dm" #include "code\controllers\subsystems\creation.dm"
#include "code\controllers\subsystems\garbage.dm" #include "code\controllers\subsystems\garbage.dm"
#include "code\controllers\subsystems\lighting.dm" #include "code\controllers\subsystems\lighting.dm"
#include "code\controllers\subsystems\machines.dm"
#include "code\datums\ai_law_sets.dm" #include "code\datums\ai_law_sets.dm"
#include "code\datums\ai_laws.dm" #include "code\datums\ai_laws.dm"
#include "code\datums\browser.dm" #include "code\datums\browser.dm"