From a2e487c86ed5b556d2655ccf7fad86aa0014ce3b Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Tue, 1 Aug 2017 16:59:50 -0500 Subject: [PATCH 1/4] Makes GetComponent() faster using typecache magic --- code/__HELPERS/type2type.dm | 15 +++++++++++++++ code/datums/components/component.dm.rej | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 code/datums/components/component.dm.rej diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index 36a81e90e2..7df96c3da2 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -537,3 +537,18 @@ if(!istype(the_matrix) || the_matrix.len != 20) return "#ffffffff" return rgb(the_matrix[1]*255, the_matrix[6]*255, the_matrix[11]*255, the_matrix[16]*255) + +/proc/type2parent(child) + var/string_type = "[child]" + var/last_slash = findlasttext(string_type, "/") + if(last_slash == 1) + switch(child) + if(/datum) + return null + if(/obj || /mob) + return /atom/movable + if(/area || /turf) + return /atom + else + return /datum + return text2path(copytext(string_type, 1, last_slash)) \ No newline at end of file diff --git a/code/datums/components/component.dm.rej b/code/datums/components/component.dm.rej new file mode 100644 index 0000000000..7d216a39c5 --- /dev/null +++ b/code/datums/components/component.dm.rej @@ -0,0 +1,18 @@ +diff a/code/datums/components/component.dm b/code/datums/components/component.dm (rejected hunks) +@@ -22,8 +22,7 @@ + //lazy init the parent's dc list + var/list/dc = P.datum_components + if(!dc) +- dc = list() +- P.datum_components = dc ++ P.datum_components = dc = list() + + //set up the typecache + var/our_type = type +@@ -179,4 +178,4 @@ + helicopter.SendSignal(COMSIG_COMPONENT_REMOVING, C) + C.OnTransfer(src) + C.parent = src +- SendSignal(COMSIG_COMPONENT_ADDED, C) +\ No newline at end of file ++ SendSignal(COMSIG_COMPONENT_ADDED, C) From 468b14a01139e397f6482e198c3935ad5c3c11d8 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Wed, 2 Aug 2017 06:04:43 -0500 Subject: [PATCH 2/4] Update component.dm --- code/datums/components/component.dm | 168 +++++++++++++++++++++------- 1 file changed, 126 insertions(+), 42 deletions(-) diff --git a/code/datums/components/component.dm b/code/datums/components/component.dm index b9212d2786..5e25a581f8 100644 --- a/code/datums/components/component.dm +++ b/code/datums/components/component.dm @@ -1,8 +1,8 @@ /datum/component - var/enabled = TRUE // Enables or disables the components - var/dupe_mode = COMPONENT_DUPE_HIGHLANDER // How components of the same type are handled in the same parent - var/list/signal_procs // list of signals -> callbacks - var/datum/parent // parent datum + var/enabled = TRUE + var/dupe_mode = COMPONENT_DUPE_HIGHLANDER + var/list/signal_procs + var/datum/parent /datum/component/New(datum/P, ...) var/dm = dupe_mode @@ -11,26 +11,78 @@ if(old) switch(dm) if(COMPONENT_DUPE_HIGHLANDER) - P.RemoveComponent(old) - old = null //in case SendSignal() blocks + InheritComponent(old, FALSE) + qdel(old) if(COMPONENT_DUPE_UNIQUE) + old.InheritComponent(src, TRUE) qdel(src) return - P.SendSignal(COMSIG_COMPONENT_ADDED, list(src), FALSE) - LAZYADD(P.datum_components, src) + P.SendSignal(COMSIG_COMPONENT_ADDED, src) + + //lazy init the parent's dc list + var/list/dc = P.datum_components + if(!dc) + P.datum_components = dc = list() + + //set up the typecache + var/our_type = type + for(var/I in _GetInverseTypeListExceptRoot(our_type)) + var/test = dc[I] + if(test) //already another component of this type here + var/list/components_of_type + if(!islist(test)) + components_of_type = list(test) + dc[I] = components_of_type + else + components_of_type = test + if(I == our_type) //exact match, take priority + var/inserted = FALSE + for(var/J in 1 to components_of_type.len) + var/datum/component/C = components_of_type[J] + if(C.type != our_type) //but not over other exact matches + components_of_type.Insert(J, I) + inserted = TRUE + break + if(!inserted) + components_of_type += src + else //indirect match, back of the line with ya + components_of_type += src + else //only component of this type, no list + dc[I] = src + parent = P /datum/component/Destroy() - RemoveNoSignal() - return ..() - -/datum/component/proc/RemoveNoSignal() + enabled = FALSE var/datum/P = parent if(P) - LAZYREMOVE(P.datum_components, src) + _RemoveNoSignal() + P.SendSignal(COMSIG_COMPONENT_REMOVING, src) + LAZYCLEARLIST(signal_procs) + return ..() + +/datum/component/proc/_RemoveNoSignal() + var/datum/P = parent + if(P) + var/list/dc = P.datum_components + var/our_type = type + for(var/I in _GetInverseTypeListExceptRoot(our_type)) + var/list/components_of_type = dc[I] + if(islist(components_of_type)) // + var/list/subtracted = components_of_type - src + if(subtracted.len == 1) //only 1 guy left + dc[I] = subtracted[1] //make him special + else + dc[I] = subtracted + else //just us + dc -= I + if(!dc.len) + P.datum_components = null parent = null /datum/component/proc/RegisterSignal(sig_type, proc_on_self, override = FALSE) + if(QDELETED(src)) + return var/list/procs = signal_procs if(!procs) procs = list() @@ -43,45 +95,71 @@ procs[sig_type] = CALLBACK(src, proc_on_self) -/datum/var/list/datum_components //list of /datum/component +/datum/component/proc/ReceiveSignal(sigtype, ...) + var/list/sps = signal_procs + var/datum/callback/CB = LAZYACCESS(sps, sigtype) + if(!CB) + return FALSE + var/list/arguments = args.Copy() + arguments.Cut(1, 2) + return CB.InvokeAsync(arglist(arguments)) -// Send a signal to all other components in the container. -/datum/proc/SendSignal(sigtype, list/sig_args, async = FALSE) +/datum/component/proc/InheritComponent(datum/component/C, i_am_original) + return + +/datum/component/proc/OnTransfer(datum/new_parent) + return + +/datum/component/proc/_GetInverseTypeListExceptRoot(our_type_cached) + var/datum/component/current_type = our_type_cached + . = list() + while (current_type != /datum/component) + . += current_type + current_type = type2parent(current_type) + +/datum/var/list/datum_components //special typecache of /datum/component + +/datum/proc/SendSignal(sigtype, ...) var/list/comps = datum_components . = FALSE for(var/I in comps) var/datum/component/C = I if(!C.enabled) continue - var/list/sps = C.signal_procs - var/datum/callback/CB = LAZYACCESS(sps, sigtype) - if(!CB) - continue - if(!async) - . |= CB.Invoke(sig_args) - else - . |= CB.InvokeAsync(sig_args) + if(C.ReceiveSignal(arglist(args))) + ComponentActivated(C) + . = TRUE + +/datum/proc/ComponentActivated(datum/component/C) + return /datum/proc/GetComponent(c_type) - for(var/I in datum_components) - if(istype(I, c_type)) - return I + var/list/dc = datum_components + if(!dc) + return null + . = dc[c_type] + if(islist(.)) + return .[1] /datum/proc/GetExactComponent(c_type) - for(var/I in datum_components) - var/datum/component/C = I + var/list/dc = datum_components + if(!dc) + return null + var/datum/component/C = dc[c_type] + if(C) + if(islist(C)) + C = C[1] if(C.type == c_type) - return I + return C + return null /datum/proc/GetComponents(c_type) - . = list() - for(var/I in datum_components) - if(istype(I, c_type)) - . += I - -/datum/proc/AddComponents(list/new_types) - for(var/new_type in new_types) - AddComponent(new_type) + var/list/dc = datum_components + if(!dc) + return null + . = dc[c_type] + if(!islist(.)) + return list(.) /datum/proc/AddComponent(new_type, ...) var/nt = new_type @@ -89,9 +167,15 @@ var/datum/component/C = new nt(arglist(args)) return QDELING(C) ? GetComponent(new_type) : C -/datum/proc/RemoveComponent(datum/component/C) +/datum/proc/TakeComponent(datum/component/C) if(!C) return - C.RemoveNoSignal() - SendSignal(COMSIG_COMPONENT_REMOVING, list(C), FALSE) - qdel(C) + var/datum/helicopter = C.parent + if(helicopter == src) + //wat + return + C._RemoveNoSignal() + helicopter.SendSignal(COMSIG_COMPONENT_REMOVING, C) + C.OnTransfer(src) + C.parent = src + SendSignal(COMSIG_COMPONENT_ADDED, C) From fa8ed2de17ed9065ce6587a60d675ba068c2dab0 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Mon, 14 Aug 2017 09:13:33 -0500 Subject: [PATCH 3/4] Update component.dm --- code/datums/components/component.dm | 229 ++-------------------------- 1 file changed, 14 insertions(+), 215 deletions(-) diff --git a/code/datums/components/component.dm b/code/datums/components/component.dm index bc65b1cabe..5e25a581f8 100644 --- a/code/datums/components/component.dm +++ b/code/datums/components/component.dm @@ -26,7 +26,7 @@ //set up the typecache var/our_type = type - for(var/I in _GetInverseTypeList(our_type)) + for(var/I in _GetInverseTypeListExceptRoot(our_type)) var/test = dc[I] if(test) //already another component of this type here var/list/components_of_type @@ -66,7 +66,7 @@ if(P) var/list/dc = P.datum_components var/our_type = type - for(var/I in _GetInverseTypeList(our_type)) + for(var/I in _GetInverseTypeListExceptRoot(our_type)) var/list/components_of_type = dc[I] if(islist(components_of_type)) // var/list/subtracted = components_of_type - src @@ -110,226 +110,25 @@ /datum/component/proc/OnTransfer(datum/new_parent) return -/datum/component/proc/AfterComponentActivated() - return - -/datum/component/proc/_GetInverseTypeList(current_type) - . = list(current_type) +/datum/component/proc/_GetInverseTypeListExceptRoot(our_type_cached) + var/datum/component/current_type = our_type_cached + . = list() while (current_type != /datum/component) - current_type = type2parent(current_type) . += current_type + current_type = type2parent(current_type) + +/datum/var/list/datum_components //special typecache of /datum/component /datum/proc/SendSignal(sigtype, ...) var/list/comps = datum_components . = FALSE - if(!comps) - return - var/target = comps[/datum/component] - if(!islist(target)) - var/datum/component/C = target - if(C.enabled && C.ReceiveSignal(arglist(args))) + for(var/I in comps) + var/datum/component/C = I + if(!C.enabled) + continue + if(C.ReceiveSignal(arglist(args))) ComponentActivated(C) - C.AfterComponentActivated() - return TRUE - else - for(var/I in target) - var/datum/component/C = I - if(!C.enabled) - continue - if(C.ReceiveSignal(arglist(args))) - ComponentActivated(C) - . = TRUE - -/datum/proc/ComponentActivated(datum/component/C) - return - -/datum/proc/GetComponent(c_type) - var/list/dc = datum_components - if(!dc) - return null - . = dc[c_type] - if(islist(.)) - return .[1] - -/datum/proc/GetExactComponent(c_type) - var/list/dc = datum_components - if(!dc) - return null - var/datum/component/C = dc[c_type] - if(C) - if(islist(C)) - C = C[1] - if(C.type == c_type) - return C - return null - -/datum/proc/GetComponents(c_type) - var/list/dc = datum_components - if(!dc) - return null - . = dc[c_type] - if(!islist(.)) - return list(.) - -/datum/proc/AddComponent(new_type, ...) - var/nt = new_type - args[1] = src - var/datum/component/C = new nt(arglist(args)) - return QDELING(C) ? GetComponent(new_type) : C - -/datum/proc/TakeComponent(datum/component/C) - if(!C) - return - var/datum/helicopter = C.parent - if(helicopter == src) - //wat - return - C._RemoveNoSignal() - helicopter.SendSignal(COMSIG_COMPONENT_REMOVING, C) - C.OnTransfer(src) - C.parent = src - SendSignal(COMSIG_COMPONENT_ADDED, C) -/datum/component - var/enabled = TRUE - var/dupe_mode = COMPONENT_DUPE_HIGHLANDER - var/list/signal_procs - var/datum/parent - -/datum/component/New(datum/P, ...) - var/dm = dupe_mode - if(dm != COMPONENT_DUPE_ALLOWED) - var/datum/component/old = P.GetExactComponent(type) - if(old) - switch(dm) - if(COMPONENT_DUPE_HIGHLANDER) - InheritComponent(old, FALSE) - qdel(old) - if(COMPONENT_DUPE_UNIQUE) - old.InheritComponent(src, TRUE) - qdel(src) - return - P.SendSignal(COMSIG_COMPONENT_ADDED, src) - - //lazy init the parent's dc list - var/list/dc = P.datum_components - if(!dc) - P.datum_components = dc = list() - - //set up the typecache - var/our_type = type - for(var/I in _GetInverseTypeList(our_type)) - var/test = dc[I] - if(test) //already another component of this type here - var/list/components_of_type - if(!islist(test)) - components_of_type = list(test) - dc[I] = components_of_type - else - components_of_type = test - if(I == our_type) //exact match, take priority - var/inserted = FALSE - for(var/J in 1 to components_of_type.len) - var/datum/component/C = components_of_type[J] - if(C.type != our_type) //but not over other exact matches - components_of_type.Insert(J, I) - inserted = TRUE - break - if(!inserted) - components_of_type += src - else //indirect match, back of the line with ya - components_of_type += src - else //only component of this type, no list - dc[I] = src - - parent = P - -/datum/component/Destroy() - enabled = FALSE - var/datum/P = parent - if(P) - _RemoveNoSignal() - P.SendSignal(COMSIG_COMPONENT_REMOVING, src) - LAZYCLEARLIST(signal_procs) - return ..() - -/datum/component/proc/_RemoveNoSignal() - var/datum/P = parent - if(P) - var/list/dc = P.datum_components - var/our_type = type - for(var/I in _GetInverseTypeList(our_type)) - var/list/components_of_type = dc[I] - if(islist(components_of_type)) // - var/list/subtracted = components_of_type - src - if(subtracted.len == 1) //only 1 guy left - dc[I] = subtracted[1] //make him special - else - dc[I] = subtracted - else //just us - dc -= I - if(!dc.len) - P.datum_components = null - parent = null - -/datum/component/proc/RegisterSignal(sig_type, proc_on_self, override = FALSE) - if(QDELETED(src)) - return - var/list/procs = signal_procs - if(!procs) - procs = list() - signal_procs = procs - - if(!override) - . = procs[sig_type] - if(.) - stack_trace("[sig_type] overridden. Use override = TRUE to suppress this warning") - - procs[sig_type] = CALLBACK(src, proc_on_self) - -/datum/component/proc/ReceiveSignal(sigtype, ...) - var/list/sps = signal_procs - var/datum/callback/CB = LAZYACCESS(sps, sigtype) - if(!CB) - return FALSE - var/list/arguments = args.Copy() - arguments.Cut(1, 2) - return CB.InvokeAsync(arglist(arguments)) - -/datum/component/proc/InheritComponent(datum/component/C, i_am_original) - return - -/datum/component/proc/OnTransfer(datum/new_parent) - return - -/datum/component/proc/AfterComponentActivated() - return - -/datum/component/proc/_GetInverseTypeList(current_type) - . = list(current_type) - while (current_type != /datum/component) - current_type = type2parent(current_type) - . += current_type - -/datum/proc/SendSignal(sigtype, ...) - var/list/comps = datum_components - . = FALSE - if(!comps) - return - var/target = comps[/datum/component] - if(!islist(target)) - var/datum/component/C = target - if(C.enabled && C.ReceiveSignal(arglist(args))) - ComponentActivated(C) - C.AfterComponentActivated() - return TRUE - else - for(var/I in target) - var/datum/component/C = I - if(!C.enabled) - continue - if(C.ReceiveSignal(arglist(args))) - ComponentActivated(C) - . = TRUE + . = TRUE /datum/proc/ComponentActivated(datum/component/C) return From 2c33ef3ab080a2f1381834c66acb9002632cdae0 Mon Sep 17 00:00:00 2001 From: LetterJay Date: Fri, 18 Aug 2017 13:56:47 -0500 Subject: [PATCH 4/4] Update component.dm --- code/datums/components/component.dm | 2 -- 1 file changed, 2 deletions(-) diff --git a/code/datums/components/component.dm b/code/datums/components/component.dm index 5e25a581f8..4d5fae2115 100644 --- a/code/datums/components/component.dm +++ b/code/datums/components/component.dm @@ -117,8 +117,6 @@ . += current_type current_type = type2parent(current_type) -/datum/var/list/datum_components //special typecache of /datum/component - /datum/proc/SendSignal(sigtype, ...) var/list/comps = datum_components . = FALSE