From dff522fbaa8775ed983f6a2b83409addef7d112d Mon Sep 17 00:00:00 2001 From: Insality Date: Tue, 5 Apr 2022 18:57:40 +0300 Subject: [PATCH] Solve #182 add table pool for events --- druid/base/back_handler.lua | 6 +++ druid/base/button.lua | 11 +++++ druid/base/drag.lua | 10 +++++ druid/base/hover.lua | 7 +++ druid/base/scroll.lua | 8 ++++ druid/base/static_grid.lua | 10 +++++ druid/base/swipe.lua | 6 +++ druid/base/text.lua | 8 ++++ druid/component.lua | 6 +++ druid/const.lua | 2 + druid/event.lua | 22 ++++++--- druid/extended/checkbox.lua | 6 +++ druid/extended/checkbox_group.lua | 7 +++ druid/extended/data_list.lua | 6 +++ druid/extended/dynamic_grid.lua | 10 +++++ druid/extended/input.lua | 11 +++++ druid/extended/lang_text.lua | 6 +++ druid/extended/layout.lua | 6 +++ druid/extended/progress.lua | 6 +++ druid/extended/radio_group.lua | 6 +++ druid/extended/slider.lua | 6 +++ druid/extended/timer.lua | 8 ++++ druid/system/druid_instance.lua | 1 + druid/system/tablepool.lua | 75 +++++++++++++++++++++++++++++++ 24 files changed, 244 insertions(+), 6 deletions(-) create mode 100644 druid/system/tablepool.lua diff --git a/druid/base/back_handler.lua b/druid/base/back_handler.lua index a97c7d8..e3e19c8 100644 --- a/druid/base/back_handler.lua +++ b/druid/base/back_handler.lua @@ -30,6 +30,12 @@ function BackHandler.init(self, callback, params) end +function BackHandler.on_internal_remove(self) + component.on_internal_remove(self) + self.on_back:clear() +end + + --- Input handler for component -- @tparam BackHandler self @{BackHandler} -- @tparam string action_id on_input action id diff --git a/druid/base/button.lua b/druid/base/button.lua index 61c4db2..fe41c4d 100755 --- a/druid/base/button.lua +++ b/druid/base/button.lua @@ -239,6 +239,17 @@ function Button.on_late_init(self) end +function Button.on_internal_remove(self) + component.on_internal_remove(self) + self.on_click:clear() + self.on_repeated_click:clear() + self.on_long_click:clear() + self.on_double_click:clear() + self.on_hold_callback:clear() + self.on_click_outside:clear() +end + + function Button.on_input(self, action_id, action) if not is_input_match(self, action_id) then return false diff --git a/druid/base/drag.lua b/druid/base/drag.lua index b51c1af..c9c2e98 100644 --- a/druid/base/drag.lua +++ b/druid/base/drag.lua @@ -189,6 +189,16 @@ function Drag.init(self, node, on_drag_callback) end +function Drag.on_internal_remove(self) + component.on_internal_remove(self) + self.on_touch_start:clear() + self.on_touch_end:clear() + self.on_drag_start:clear() + self.on_drag:clear() + self.on_drag_end:clear() +end + + function Drag.on_late_init(self) if not self.click_zone and const.IS_STENCIL_CHECK then local stencil_node = helper.get_closest_stencil_node(self.node) diff --git a/druid/base/hover.lua b/druid/base/hover.lua index 05aa0ac..9c71b18 100644 --- a/druid/base/hover.lua +++ b/druid/base/hover.lua @@ -38,6 +38,13 @@ function Hover.init(self, node, on_hover_callback) end +function Hover.on_internal_remove(self) + component.on_internal_remove(self) + self.on_hover:clear() + self.on_mouse_hover:clear() +end + + function Hover.on_late_init(self) if not self.click_zone and const.IS_STENCIL_CHECK then local stencil_node = helper.get_closest_stencil_node(self.node) diff --git a/druid/base/scroll.lua b/druid/base/scroll.lua index 01fbdd4..796335f 100755 --- a/druid/base/scroll.lua +++ b/druid/base/scroll.lua @@ -174,6 +174,14 @@ function Scroll.init(self, view_node, content_node) end +function Scroll.on_internal_remove(self) + component.on_internal_remove(self) + self.on_scroll:clear() + self.on_scroll_to:clear() + self.on_point_scroll:clear() +end + + function Scroll.on_late_init(self) if not self.click_zone and const.IS_STENCIL_CHECK then local stencil_node = helper.get_closest_stencil_node(self.node) diff --git a/druid/base/static_grid.lua b/druid/base/static_grid.lua index c32d4c0..30f47ce 100644 --- a/druid/base/static_grid.lua +++ b/druid/base/static_grid.lua @@ -115,6 +115,16 @@ function StaticGrid.init(self, parent, element, in_row) end +function StaticGrid.on_internal_remove(self) + component.on_internal_remove(self) + self.on_add_item:clear() + self.on_remove_item:clear() + self.on_change_items:clear() + self.on_clear:clear() + self.on_update_positions:clear() +end + + local _temp_pos = vmath.vector3(0) --- Return pos for grid node index -- @tparam StaticGrid self @{StaticGrid} diff --git a/druid/base/swipe.lua b/druid/base/swipe.lua index d4ecc27..69e9b3a 100644 --- a/druid/base/swipe.lua +++ b/druid/base/swipe.lua @@ -99,6 +99,12 @@ function Swipe.init(self, node, on_swipe_callback) end +function Swipe.on_internal_remove(self) + component.on_internal_remove(self) + self.on_swipe:clear() +end + + function Swipe.on_late_init(self) if not self.click_zone and const.IS_STENCIL_CHECK then local stencil_node = helper.get_closest_stencil_node(self.node) diff --git a/druid/base/text.lua b/druid/base/text.lua index 8981ccc..13ce80d 100755 --- a/druid/base/text.lua +++ b/druid/base/text.lua @@ -217,6 +217,14 @@ function Text.init(self, node, value, adjust_type) end +function Text.on_internal_remove(self) + component.on_internal_remove(self) + self.on_set_text:clear() + self.on_set_pivot:clear() + self.on_update_text_scale:clear() +end + + function Text.on_layout_change(self) self:set_to(self.last_value) end diff --git a/druid/component.lua b/druid/component.lua index 02d351a..6374344 100644 --- a/druid/component.lua +++ b/druid/component.lua @@ -8,6 +8,7 @@ local const = require("druid.const") local class = require("druid.system.middleclass") local helper = require("druid.helper") +local tablepool = require("druid.system.tablepool") local BaseComponent = class("druid.component") @@ -348,6 +349,11 @@ function BaseComponent.set_debug(self, is_debug) end +--- On remove method on druid:remove or druid:final (protected) +function BaseComponent:on_internal_remove() +end + + --- Return true, if input priority was changed -- @tparam BaseComponent self @{BaseComponent} -- @local diff --git a/druid/const.lua b/druid/const.lua index 3e8c0d9..2d23a60 100755 --- a/druid/const.lua +++ b/druid/const.lua @@ -7,6 +7,8 @@ local M = {} +M.POOL_ID = "druid_table_pool" + M.ACTION_TEXT = hash(sys.get_config("druid.input_text", "text")) M.ACTION_TOUCH = hash(sys.get_config("druid.input_touch", "touch")) M.ACTION_MARKED_TEXT = hash(sys.get_config("druid.input_marked_text", "marked_text")) diff --git a/druid/event.lua b/druid/event.lua index e540de8..11bc2f3 100644 --- a/druid/event.lua +++ b/druid/event.lua @@ -5,6 +5,8 @@ -- @alias druid.event local class = require("druid.system.middleclass") +local const = require("druid.const") +local tablepool = require("druid.system.tablepool") local DruidEvent = class("druid.event") @@ -29,11 +31,12 @@ function DruidEvent.subscribe(self, callback, context) assert(type(self) == "table", "You should subscribe to event with : syntax") assert(type(callback) == "function", "Callback should be function") - self._callbacks = self._callbacks or {} - table.insert(self._callbacks, { - callback = callback, - context = context - }) + self._callbacks = self._callbacks or tablepool.fetch(const.POOL_ID) + local callback_table = tablepool.fetch(const.POOL_ID, 0, 2) + callback_table.callback = callback + callback_table.context = context + + table.insert(self._callbacks, callback_table) return callback end @@ -50,6 +53,7 @@ function DruidEvent.unsubscribe(self, callback, context) for index, callback_info in ipairs(self._callbacks) do if callback_info.callback == callback and callback_info.context == context then + tablepool.release(self._callbacks[index]) table.remove(self._callbacks, index) return end @@ -71,6 +75,12 @@ end --- Clear the all event handlers -- @tparam DruidEvent self @{DruidEvent} function DruidEvent.clear(self) + if self._callbacks then + for index = #self._callbacks, 1, -1 do + tablepool.release(self._callbacks[index]) + end + end + tablepool.release(self._callbacks) self._callbacks = nil end @@ -83,7 +93,7 @@ function DruidEvent.trigger(self, ...) return false end - for index, callback_info in ipairs(self._callbacks) do + for _, callback_info in ipairs(self._callbacks) do if callback_info.context then callback_info.callback(callback_info.context, ...) else diff --git a/druid/extended/checkbox.lua b/druid/extended/checkbox.lua index ef1b295..f7d4c82 100755 --- a/druid/extended/checkbox.lua +++ b/druid/extended/checkbox.lua @@ -67,6 +67,12 @@ function Checkbox.on_layout_change(self) end +function Checkbox.on_internal_remove(self) + component.on_internal_remove(self) + self.on_change_state:clear() +end + + --- Set checkbox state -- @tparam Checkbox self @{Checkbox} -- @tparam bool state Checkbox state diff --git a/druid/extended/checkbox_group.lua b/druid/extended/checkbox_group.lua index 2ca9561..493e5ab 100644 --- a/druid/extended/checkbox_group.lua +++ b/druid/extended/checkbox_group.lua @@ -41,6 +41,13 @@ function CheckboxGroup.init(self, nodes, callback, click_nodes) end +function CheckboxGroup.on_internal_remove(self) + component.on_internal_remove(self) + self.on_checkbox_click:clear() +end + + + --- Set checkbox group state -- @tparam CheckboxGroup self @{CheckboxGroup} -- @tparam bool[] indexes Array of checkbox state diff --git a/druid/extended/data_list.lua b/druid/extended/data_list.lua index e8e95c6..05f21e6 100644 --- a/druid/extended/data_list.lua +++ b/druid/extended/data_list.lua @@ -76,6 +76,12 @@ function DataList.on_remove(self) end +function DataList.on_internal_remove(self) + component.on_internal_remove(self) + self.on_scroll_progress_change:clear() +end + + --- Set new data set for DataList component -- @tparam DataList self @{DataList} -- @tparam table data The new data array diff --git a/druid/extended/dynamic_grid.lua b/druid/extended/dynamic_grid.lua index 0593715..a9da0ae 100644 --- a/druid/extended/dynamic_grid.lua +++ b/druid/extended/dynamic_grid.lua @@ -89,6 +89,16 @@ function DynamicGrid.init(self, parent) end +function DynamicGrid.on_internal_remove(self) + component.on_internal_remove(self) + self.on_add_item:clear() + self.on_remove_item:clear() + self.on_change_items:clear() + self.on_clear:clear() + self.on_update_positions:clear() +end + + function DynamicGrid.on_layout_change(self) self:_update(true) end diff --git a/druid/extended/input.lua b/druid/extended/input.lua index d463871..d8f43b3 100755 --- a/druid/extended/input.lua +++ b/druid/extended/input.lua @@ -154,6 +154,17 @@ function Input.init(self, click_node, text_node, keyboard_type) end +function Input.on_internal_remove(self) + component.on_internal_remove(self) + self.on_input_select:clear() + self.on_input_unselect:clear() + self.on_input_text:clear() + self.on_input_empty:clear() + self.on_input_full:clear() + self.on_input_wrong:clear() +end + + function Input.on_input(self, action_id, action) if self.is_selected then local input_text = nil diff --git a/druid/extended/lang_text.lua b/druid/extended/lang_text.lua index f78b70b..fec0c7d 100755 --- a/druid/extended/lang_text.lua +++ b/druid/extended/lang_text.lua @@ -41,6 +41,12 @@ function LangText.init(self, node, locale_id, no_adjust) end +function LangText.on_internal_remove(self) + component.on_internal_remove(self) + self.on_change:clear() +end + + function LangText.on_language_change(self) if self.last_locale then self:translate(self.last_locale, unpack(self.last_locale_args)) diff --git a/druid/extended/layout.lua b/druid/extended/layout.lua index 37963f0..719e2ae 100644 --- a/druid/extended/layout.lua +++ b/druid/extended/layout.lua @@ -39,6 +39,12 @@ function Layout:init(node, mode, on_size_changed_callback) end +function Layout.on_internal_remove(self) + component.on_internal_remove(self) + self.on_size_changed:clear() +end + + function Layout:on_window_resized() local window_x, window_y = window.get_size() local stretch_x = window_x / self.window_size.x diff --git a/druid/extended/progress.lua b/druid/extended/progress.lua index 509e57b..99ef6b2 100644 --- a/druid/extended/progress.lua +++ b/druid/extended/progress.lua @@ -121,6 +121,12 @@ function Progress.init(self, node, key, init_value) end +function Progress.on_internal_remove(self) + component.on_internal_remove(self) + self.on_change:clear() +end + + -- @tparam Progress self @{Progress} function Progress.on_late_init(self) self:set_to(self._init_value) diff --git a/druid/extended/radio_group.lua b/druid/extended/radio_group.lua index fef1d00..768959d 100644 --- a/druid/extended/radio_group.lua +++ b/druid/extended/radio_group.lua @@ -50,6 +50,12 @@ function RadioGroup.init(self, nodes, callback, click_nodes) end +function RadioGroup.on_internal_remove(self) + component.on_internal_remove(self) + self.on_radio_click:clear() +end + + --- Set radio group state -- @tparam RadioGroup self @{RadioGroup} -- @tparam number index Index in radio group diff --git a/druid/extended/slider.lua b/druid/extended/slider.lua index 4a8c90c..ea5470b 100644 --- a/druid/extended/slider.lua +++ b/druid/extended/slider.lua @@ -77,6 +77,12 @@ function Slider.init(self, node, end_pos, callback) end +function Slider.on_internal_remove(self) + component.on_internal_remove(self) + self.on_change_value:clear() +end + + function Slider.on_layout_change(self) self:set(self.value) end diff --git a/druid/extended/timer.lua b/druid/extended/timer.lua index 21ac56b..e31bdb7 100644 --- a/druid/extended/timer.lua +++ b/druid/extended/timer.lua @@ -65,6 +65,14 @@ function Timer.init(self, node, seconds_from, seconds_to, callback) end +function Timer.on_internal_remove(self) + component.on_internal_remove(self) + self.on_tick:clear() + self.on_set_enabled:clear() + self.on_timer_end:clear() +end + + function Timer.update(self, dt) if not self.is_on then return diff --git a/druid/system/druid_instance.lua b/druid/system/druid_instance.lua index e286e78..d2f2c99 100755 --- a/druid/system/druid_instance.lua +++ b/druid/system/druid_instance.lua @@ -289,6 +289,7 @@ function DruidInstance.remove(self, component) local all_components = self.components_all for i = #all_components, 1, -1 do if all_components[i] == component then + component:on_internal_remove() if component.on_remove then component:on_remove() end diff --git a/druid/system/tablepool.lua b/druid/system/tablepool.lua new file mode 100644 index 0000000..2c8a803 --- /dev/null +++ b/druid/system/tablepool.lua @@ -0,0 +1,75 @@ +-- Source: https://github.com/openresty/lua-tablepool/blob/master/lib/tablepool.lua + +local setmetatable = setmetatable + +local _M = {} +local max_pool_size = 500 +local pools = {} + + +function _M.fetch(tag) + local pool = pools[tag] + if not pool then + pool = {} + pools[tag] = pool + pool.c = 0 + pool[0] = 0 + + else + local len = pool[0] + if len > 0 then + local obj = pool[len] + pool[len] = nil + pool[0] = len - 1 + return obj + end + end + + return {} +end + + +function _M.release(tag, obj, noclear) + if not obj then + error("object empty", 2) + end + + local pool = pools[tag] + if not pool then + pool = {} + pools[tag] = pool + pool.c = 0 + pool[0] = 0 + end + + if not noclear then + setmetatable(obj, nil) + for k in pairs(obj) do + obj[k] = nil + end + end + + do + local cnt = pool.c + 1 + if cnt >= 20000 then + pool = {} + pools[tag] = pool + pool.c = 0 + pool[0] = 0 + return + end + pool.c = cnt + end + + local len = pool[0] + 1 + if len > max_pool_size then + -- discard it simply + return + end + + pool[len] = obj + pool[0] = len +end + + +return _M