/traderous

To get this branch, use:
bzr branch /bzr/traderous

« back to all changes in this revision

Viewing changes to zoetrope/utils/factory.lua

  • Committer: Josh C
  • Date: 2013-05-04 20:45:17 UTC
  • Revision ID: josh@9ix.org-20130504204517-1rfp92svud12kg42
zoetrope 1.4

Show diffs side-by-side

added added

removed removed

 
1
-- Class: Factory
 
2
-- A factory allows for simple object pooling; that is,
 
3
-- reusing object instances instead of creating them and deleting
 
4
-- them as needed. This approach saves CPU and memory.
 
5
--
 
6
-- Be careful of accidentally adding an instance to a view twice.
 
7
-- This will manifest itself as the sprite moving twice as fast, for
 
8
-- example, each time it is recycled. The easiest way to avoid this
 
9
-- problem is for the object to add itself to the view in its onNew
 
10
-- handler, since that will only be called once.
 
11
--
 
12
-- If you only want a certain number of instances of a class ever
 
13
-- created, first call preload() to create as many instances as you want,
 
14
-- then freeze() to prevent any new instances from being created.
 
15
-- If a factory is ever asked to make a new instance of a frozen class
 
16
-- but none are available for recycling, it returns nil.
 
17
--
 
18
-- Event: onReset
 
19
-- Called not on the factory, but the object is creates whenever
 
20
-- it is either initially created or recycled via create(). 
 
21
--
 
22
-- Extends:
 
23
--              <Class>
 
24
 
 
25
Factory = Class:extend{
 
26
        -- private property: objects ready to be recycled, stored by prototype
 
27
        _recycled = {},
 
28
 
 
29
        -- private property: tracks which pools cannot be added to, stored by prototype.
 
30
        _frozen = {},
 
31
 
 
32
        -- Method: create
 
33
        -- Creates a fresh object, either by reusing a previously
 
34
        -- recycled one or creating a new instance. If the object has
 
35
        -- a revive method, it calls it.
 
36
        --
 
37
        -- Arguments:
 
38
        --              prototype - <Class> object
 
39
        --              props - table of properties to mix into the class
 
40
        --
 
41
        -- Returns:
 
42
        --              fresh object
 
43
 
 
44
        create = function (self, prototype, props)
 
45
                local newObj
 
46
 
 
47
                if STRICT then
 
48
                        assert(prototype.instanceOf and prototype:instanceOf(Class), 'asked to create something that isn\'t a class')
 
49
                end
 
50
                
 
51
                if self._recycled[prototype] and #self._recycled[prototype] > 0 then
 
52
                        newObj = table.remove(self._recycled[prototype])
 
53
                        if props then newObj:mixin(props) end
 
54
                else
 
55
                        -- create a new instance if we're allowed to
 
56
 
 
57
                        if not self._frozen[prototype] then
 
58
                                newObj = prototype:new(props)
 
59
                        else
 
60
                                return nil
 
61
                        end
 
62
                end
 
63
 
 
64
                if newObj.revive then newObj:revive() end
 
65
                if newObj.onReset then newObj:onReset() end
 
66
                return newObj
 
67
        end,
 
68
 
 
69
        -- Method: recycle
 
70
        -- Marks an object as ready to be recycled. If the object
 
71
        -- has a die method, then this function it.
 
72
        --
 
73
        -- Arguments:
 
74
        --              object - object to recycle
 
75
        --
 
76
        -- Returns:
 
77
        --              nothing
 
78
 
 
79
        recycle = function (self, object)
 
80
                if not self._recycled[object.prototype] then
 
81
                        self._recycled[object.prototype] = {}
 
82
                end
 
83
 
 
84
                table.insert(self._recycled[object.prototype], object)
 
85
 
 
86
                if object.die then object:die() end
 
87
        end,
 
88
 
 
89
        -- Method: preload
 
90
        -- Preloads the factory with a certain number of instances of a class.
 
91
        --
 
92
        -- Arguments:
 
93
        --              prototype - class object
 
94
        --              count - number of objects to create
 
95
        --
 
96
        -- Returns:
 
97
        --              nothing
 
98
 
 
99
        preload = function (self, prototype, count)
 
100
                if not self._recycled[prototype] then
 
101
                        self._recycled[prototype] = {}
 
102
                end
 
103
 
 
104
                local i
 
105
 
 
106
                for i = 1, count do
 
107
                        table.insert(self._recycled[prototype], prototype:new())
 
108
                end
 
109
        end,
 
110
 
 
111
        -- Method: freeze
 
112
        -- Prevents any new instances of a class from being created via create().
 
113
        --
 
114
        -- Arguments:
 
115
        --              prototype - class object
 
116
        --
 
117
        -- Returns:
 
118
        --              nothing
 
119
 
 
120
        freeze = function (self, prototype)
 
121
                self._frozen[prototype] = true
 
122
        end,
 
123
 
 
124
        -- Method: unfreeze
 
125
        -- Allows new instances of a class to be created via create().
 
126
        --
 
127
        -- Arguments:
 
128
        --              prototype - class object
 
129
        --
 
130
        -- Returns:
 
131
        --              nothing
 
132
 
 
133
        unfreeze = function (self, prototype)
 
134
                self._frozen[prototype] = false
 
135
        end
 
136
}