ESOUI

ESOUI (https://www.esoui.com/forums/index.php)
-   General Authoring Discussion (https://www.esoui.com/forums/forumdisplay.php?f=174)
-   -   ZO_ObjectPool (https://www.esoui.com/forums/showthread.php?t=143)

zork 03/01/14 05:59 PM

ZO_ObjectPool
 
I have not wrapped my head around the ZO_ObjectPool yet.

Here is a snippet of code from zo_objectpool.lua. Not sure if that has been updated yet. (aug 2013)

Lua Code:
  1. --[[
  2.  
  3.     A generic pool to contain "active" and "free" objects.  Active objects
  4.     are typically objects which:
  5.         1. Have a relatively high construction cost
  6.         2. Are not lightweight enough to create many of them at once
  7.         3. Tend to be reused as dynamic elements of a larger container.
  8.        
  9.     The pool should "rapidly" reach a high-water mark of contained objects
  10.     which should flow between active and free states on a regular basis.
  11.    
  12.     Ideal uses of the ZO_ObjectPool would be to contain objects such as:
  13.         1. Scrolling combat text
  14.         2. Tracked quests
  15.         3. Buff icons
  16.        
  17.     The pools are not intended to be used to track a dynamic set of
  18.     contained objects whose membership grows to a predetermined size.
  19.     As such, do NOT use the pool to track:
  20.         1. Chat filters
  21.         2. Inventory slots
  22.         3. Action buttons (unless creating something like AutoBar)
  23.        
  24.     A common usage pattern is instantiating templated controls.  To facilitate this
  25.     without bloating your own code you should use ZO_ObjectPool_CreateControl which has
  26.     been written here as a convenience.  It creates a control named "template"..id where
  27.     id is an arbitrary value that will not conflict with other generated id's.
  28.    
  29.     If your system depends on having well-known names for controls, you should not use the
  30.     convenience function.    
  31. --]]
  32.  
  33. ZO_ObjectPool = ZO_Object:Subclass()
  34.  
  35. function ZO_ObjectPool:New(factoryFunction, resetFunction)
  36.     local pool = ZO_Object.New(self)
  37.        
  38.     if(factoryFunction)
  39.     then
  40.         resetFunction = resetFunction or ZO_ObjectPool_DefaultResetControl
  41.  
  42.         pool.m_Active   = {}
  43.         pool.m_Free     = {}
  44.         pool.m_Factory  = factoryFunction   -- Signature: function(ZO_ObjectPool)
  45.         pool.m_Reset    = resetFunction     -- Signature: function(objectBeingReset)
  46.         pool.m_NextFree = 1                 -- Just in case the user would like the pool to generate object keys.
  47.         pool.m_NextControlId = 0            -- Just in case the user would like the pool to generate id-based control suffixes
  48.     end
  49.    
  50.     return pool
  51. end
  52.  
  53. function ZO_ObjectPool:GetNextFree()
  54.     local nextPotentialFree = self.m_NextFree
  55.     self.m_NextFree = self.m_NextFree + 1
  56.  
  57.     local freeKey, object = next(self.m_Free)
  58.     if(freeKey == nil or object == nil)
  59.     then
  60.         return nextPotentialFree, nil
  61.     end
  62.  
  63.     return freeKey, object
  64. end
  65.  
  66. function ZO_ObjectPool:GetNextControlId()
  67.     self.m_NextControlId = self.m_NextControlId + 1
  68.     return self.m_NextControlId
  69. end
  70.  
  71. function ZO_ObjectPool:GetTotalObjectCount()
  72.     return self:GetActiveObjectCount() + self:GetFreeObjectCount()
  73. end
  74.  
  75. function ZO_ObjectPool:GetActiveObjectCount()
  76.     return NonContiguousCount(self.m_Active)
  77. end
  78.  
  79. function ZO_ObjectPool:GetActiveObjects()
  80.     return self.m_Active
  81. end
  82.  
  83. function ZO_ObjectPool:GetFreeObjectCount()
  84.     return NonContiguousCount(self.m_Free)
  85. end
  86.  
  87. function ZO_ObjectPool:AcquireObject(objectKey)
  88.     -- If the object referred to by this key is already
  89.     -- active there is very little work to do...just return it.    
  90.     if((objectKey ~= nil) and (self.m_Active[objectKey] ~= nil))
  91.     then
  92.         return self.m_Active[objectKey], objectKey
  93.     end
  94.    
  95.     local object = nil
  96.    
  97.     -- If we know the key that we want, use that object first, otherwise just return the first object from the free pool
  98.     -- A nil objectKey means that the caller doesn't care about tracking unique keys for these objects, or that the keys
  99.     -- the system uses can't directly be used to look up the data.  Just manage them with pool-generated id's
  100.     if(objectKey == nil)
  101.     then
  102.         objectKey, object = self:GetNextFree()
  103.     else
  104.         object = self.m_Free[objectKey]
  105.     end
  106.  
  107.     --
  108.     -- If the object is valid it was reclaimed from the free list, otherwise it needs to be created.
  109.     -- Creation uses the m_Factory member which receives this pool as its only argument.
  110.     -- Either way, after this, object must be non-nil
  111.     --
  112.     if(object)
  113.     then
  114.         self.m_Free[objectKey] = nil
  115.     else        
  116.         object = self:m_Factory()
  117.     end
  118.            
  119.     self.m_Active[objectKey] = object
  120.        
  121.     return object, objectKey
  122. end
  123.  
  124. function ZO_ObjectPool:GetExistingObject(objectKey)
  125.     return self.m_Active[objectKey]
  126. end
  127.  
  128. function ZO_ObjectPool:ReleaseObject(objectKey)
  129.     local object = self.m_Active[objectKey]
  130.    
  131.     if(object)
  132.     then
  133.         if(self.m_Reset)
  134.         then
  135.             self.m_Reset(object, self)
  136.         end
  137.        
  138.         self.m_Active[objectKey] = nil
  139.         self.m_Free[objectKey] = object
  140.     end
  141. end
  142.  
  143. function ZO_ObjectPool:ReleaseAllObjects()
  144.     for k, v in pairs(self.m_Active)
  145.     do
  146.         if(self.m_Reset)
  147.         then
  148.             self.m_Reset(v, self)
  149.         end
  150.        
  151.         self.m_Free[k] = v
  152.     end
  153.    
  154.     self.m_Active = {}
  155. end
  156.  
  157. function ZO_ObjectPool_CreateControl(templateName, objectPool, parentControl)
  158.     return CreateControlFromVirtual(templateName, parentControl, templateName, objectPool:GetNextControlId())
  159. end
  160.  
  161. function ZO_ObjectPool_CreateNamedControl(name, templateName, objectPool, parentControl)
  162.     return CreateControlFromVirtual(name, parentControl, templateName, objectPool:GetNextControlId())
  163. end
  164.  
  165. function ZO_ObjectPool_DefaultResetControl(control)
  166.     control:SetHidden(true)
  167. end

Pawkette used it in LootDrop. Maybe he/she knows and can enlighten us. :)

Pawkette 03/01/14 06:02 PM

What would you like to know about it?

zork 03/01/14 06:26 PM

Well I'm currently trying to understand the concept behind it.

As far as I can tell...the pool has functions to create and reset objects. On a certain event you accuire a new object and on a second event you release objects that you don't need anymore.

Maybe you could just describe the concept of LootDrop in general.

An item drops, you create a new object in the pool. After a certain time you release that object. That is how I understand it atm.

Pawkette 03/01/14 06:34 PM

Precisely that, the real concept behind ZO_ObjectPool is that you have a number of generic objects that you don't want to instantiate any time they're needed. So, ZO_ObjectPool will create an object, and when you release that object it goes back into a pool - never garbage collected. The next time you need an object, it asks that pool if any are sitting around unused and gives you that unused object instead of instantiating a new one.

It's a lot of fancy code to basically represent:

Lua Code:
  1. local in_use = {}
  2. local unused = {}
  3.  
  4. function GetNew()
  5.   if ( #unused ) then
  6.     return unused[ 1 ]
  7.   else
  8.      -- create new object
  9.   end
  10. end
  11.  
  12. function Release( object )
  13.   --remove from in_use
  14.   table.insert( unused, object )
  15. end
  16.  
  17. local obj = GetNew()
  18. table.insert( in_use, obj )
  19. obj:DoStuff()
  20. Release( obj )

Seerah 03/01/14 10:30 PM

I'm using it in a buff addon I'm currently working on. Here's a (very) trimmed down version.

Lua Code:
  1. local pool
  2.  
  3. local function CreateBuff(pool)
  4.      --create a new control frame
  5.      local buff = ZO_ObjectPool_CreateControl("MyBuffTemplate", pool, parentFrame)
  6.      --do other stuff with buff object
  7.  
  8.      --return it for use
  9.      return buff
  10. end
  11.  
  12. local function RemoveBuff(control)
  13.      --do stuff when you don't need a frame anymore
  14.      control:SetHidden(true)
  15. end
  16.  
  17. local function UpdateBuffs()
  18.      local myBuff
  19.      for i = 1, GetNumBuffs("player") do
  20.           --if a control with this id # doesn't exist yet, create it, otherwise just return the one we have
  21.           myBuff = pool:AcquireObject(i)
  22.           --do more stuff with myBuff
  23.      end
  24. end
  25.  
  26. local function Initialize()
  27.      --create a new pool to get my controls from
  28.      pool = ZO_ObjectPool:New(CreateBuff, RemoveBuff)
  29.      EVENT_MANAGER:RegisterForEvent("MyAddon", EVENT_EFFECT_CHANGED, UpdateBuffs)
  30. end
  31.  
  32. EVENT_MANAGER:RegisterForEvent("MyAddon", EVENT_ADD_ON_LOADED, function(event, addon)
  33.      if addon == "MyAddon" then
  34.           Initialize()
  35.      end
  36. end)

zork 03/02/14 05:26 AM

Thank you both. :)


All times are GMT -6. The time now is 03:09 AM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2014 - 2022 MMOUI