Maid.lua 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. -- https://github.com/Quenty/NevermoreEngine/blob/version2/Modules/Events/Maid.lua
  2. --- Manages the cleaning of events and other things.
  3. -- Useful for encapsulating state and make deconstructors easy
  4. -- @classmod Maid
  5. -- @see Signal
  6. local Maid = {}
  7. Maid.ClassName = "Maid"
  8. --- Returns a new Maid object
  9. -- @constructor Maid.new()
  10. -- @treturn Maid
  11. function Maid.new()
  12. local self = {}
  13. self._tasks = {}
  14. return setmetatable(self, Maid)
  15. end
  16. --- Returns Maid[key] if not part of Maid metatable
  17. -- @return Maid[key] value
  18. function Maid:__index(index)
  19. if Maid[index] then
  20. return Maid[index]
  21. else
  22. return self._tasks[index]
  23. end
  24. end
  25. --- Add a task to clean up
  26. -- @usage
  27. -- Maid[key] = (function) Adds a task to perform
  28. -- Maid[key] = (event connection) Manages an event connection
  29. -- Maid[key] = (Maid) Maids can act as an event connection, allowing a Maid to have other maids to clean up.
  30. -- Maid[key] = (Object) Maids can cleanup objects with a `Destroy` method
  31. -- Maid[key] = nil Removes a named task. If the task is an event, it is disconnected. If it is an object, it is destroyed.
  32. function Maid:__newindex(index, newTask)
  33. if Maid[index] ~= nil then
  34. error(("'%s' is reserved"):format(tostring(index)), 2)
  35. end
  36. local tasks = self._tasks
  37. local oldTask = tasks[index]
  38. tasks[index] = newTask
  39. if oldTask then
  40. if type(oldTask) == "function" then
  41. oldTask()
  42. elseif typeof(oldTask) == "RBXScriptConnection" then
  43. oldTask:Disconnect()
  44. elseif oldTask.Destroy then
  45. oldTask:Destroy()
  46. end
  47. end
  48. end
  49. --- Same as indexing, but uses an incremented number as a key.
  50. -- @param task An item to clean
  51. -- @treturn number taskId
  52. function Maid:GiveTask(task)
  53. assert(task)
  54. local taskId = #self._tasks+1
  55. self[taskId] = task
  56. return taskId
  57. end
  58. --- Cleans up all tasks.
  59. -- @alias Destroy
  60. function Maid:DoCleaning()
  61. local tasks = self._tasks
  62. -- Disconnect all events first as we know this is safe
  63. for index, task in pairs(tasks) do
  64. if typeof(task) == "RBXScriptConnection" then
  65. tasks[index] = nil
  66. task:Disconnect()
  67. end
  68. end
  69. -- Clear out tasks table completely, even if clean up tasks add more tasks to the maid
  70. local index, task = next(tasks)
  71. while task ~= nil do
  72. tasks[index] = nil
  73. if type(task) == "function" then
  74. task()
  75. elseif typeof(task) == "RBXScriptConnection" then
  76. task:Disconnect()
  77. elseif task.Destroy then
  78. task:Destroy()
  79. end
  80. index, task = next(tasks)
  81. end
  82. end
  83. --- Alias for DoCleaning()
  84. -- @function Destroy
  85. Maid.Destroy = Maid.DoCleaning
  86. return Maid