@@ -10,7 +10,7 @@ of allocating and freeing them individually.*
1010
1111We're working on the visual effects for our game. When the hero casts a spell,
1212we want a shimmer of sparkles to burst across the screen. This calls for a
13- * particle system* : an engine that spawns little sparkly graphics and animates
13+ * particle system* , an engine that spawns little sparkly graphics and animates
1414them until they wink out of existence.
1515
1616Since a single wave of the wand could cause hundreds of particles to be spawned,
@@ -20,19 +20,19 @@ need to make sure that creating and destroying these particles doesn't cause
2020
2121### The curse of fragmentation
2222
23- Programming for a game console like the XBox 360 is closer to embedded
23+ Programming for a game console like the Xbox 360 is closer to embedded
2424programming than conventional PC programming in many ways. Like embedded
2525programming, console games must run continuously for a very long time without
26- crashing or leaking memory and efficient compacting memory managers are rarely
27- available. In this environment memory fragmentation is deadly.
26+ crashing or leaking memory, and efficient compacting memory managers are rarely
27+ available. In this environment, memory fragmentation is deadly.
2828
2929Fragmentation means the free space in our heap is <span
3030name="park">broken</span > into smaller pieces of memory instead of one large
3131open block. The * total* memory available may be large, but the largest
3232* contiguous* region might be painfully small. Say we've got fourteen bytes free,
3333but it's fragmented into two seven-byte pieces with a chunk of in-use memory
3434between them. If we try to allocate a twelve-byte object, we'll fail. No more
35- sparklies onscreen .
35+ sparklies on screen .
3636
3737<aside name =" park " >
3838
@@ -48,7 +48,7 @@ free space is *fragmented* into bits of open curb between half a dozen cars.
4848
4949<aside name =" heap " >
5050
51- Here's how a heap becomes fragmented, and how it can cause an allocation to fail
51+ Here's how a heap becomes fragmented and how it can cause an allocation to fail
5252even where there's theoretically enough memory available.
5353
5454</aside >
@@ -61,41 +61,41 @@ and filled-in crevices, ultimately hosing the game completely.
6161
6262Most console makers require games to pass "soak tests" where they leave the game
6363running in demo mode for several days. If the game crashes, they don't allow it
64- to ship. While soak tests sometimes fail because of a rarely- occurring bug, it's
64+ to ship. While soak tests sometimes fail because of a rarely occurring bug, it's
6565usually creeping fragmentation or memory leakage that brings the game down.
6666
6767</aside >
6868
6969### The best of both worlds
7070
71- Because of fragmentation, and because allocation may be slow, games are very
72- careful about when and how they manage memory. A simple solution is often best:
73- grab a big chunk of memory when the game starts and don't free it until the game
71+ Because of fragmentation and because allocation may be slow, games are very
72+ careful about when and how they manage memory. A simple solution is often best --
73+ grab a big chunk of memory when the game starts, and don't free it until the game
7474ends. But this is a pain for systems where we need to create and destroy things
7575while the game is running.
7676
77- An object pool gives us the best of both worlds: to the memory manager, we're
77+ An object pool gives us the best of both worlds. To the memory manager, we're
7878just allocating one big hunk of memory up front and not freeing it while the
7979game is playing. To the users of the pool, we can freely allocate and deallocate
8080objects to our heart's content.
8181
8282## The Pattern
8383
8484Define a ** pool** class that maintains a collection of ** reusable objects** .
85- Each object supports an ** "in use" query** to tell if it is currently "alive."
85+ Each object supports an ** "in use" query** to tell if it is currently "alive".
8686When the pool is initialized, it creates the entire collection of objects up
8787front (usually in a single contiguous allocation) and initializes them all to
8888the "not in use" state.
8989
9090When you want a new object, ask the pool for one. It finds an available object,
91- initializes it to "in use" and returns it. When the object is no longer needed,
91+ initializes it to "in use", and returns it. When the object is no longer needed,
9292it is set back to the "not in use" state. This way, objects can be freely
9393created and destroyed without needing to allocate memory or other resources.
9494
9595## When to Use It
9696
9797This pattern is used widely in games for obvious things like game entities and
98- visual effects, but also for less visible data structures such as currently
98+ visual effects, but it is also used for less visible data structures such as currently
9999playing sounds. Use Object Pool when:
100100
101101 * You need to frequently create and destroy objects.
@@ -110,7 +110,7 @@ playing sounds. Use Object Pool when:
110110
111111## Keep in Mind
112112
113- You normally rely on a garbage collector or just ` new ` and ` delete ` to handle
113+ You normally rely on a garbage collector or ` new ` and ` delete ` to handle
114114memory management for you. By using an object pool, you're saying, "I know
115115better how these bytes should be handled." That means the onus is on you to deal
116116with this pattern's limitations.
@@ -124,14 +124,14 @@ smaller pool frees up memory that could be used for other fun stuff.
124124
125125### Only a fixed number of objects can be active at any one time
126126
127- In some ways this is a good thing. Partitioning memory into separate pools for
127+ In some ways, this is a good thing. Partitioning memory into separate pools for
128128different types of objects ensures that, for example, a huge sequence of
129129explosions won't cause your particle system to eat * all* of the available
130130memory, preventing something more critical like a new enemy from being created.
131131
132132Nonetheless, this also means being prepared for the possibility that your
133133attempt to reuse an object from the pool will fail because they are all in use.
134- There are a few common strategies to handle this.
134+ There are a few common strategies to handle this:
135135
136136 * * Prevent it outright.* This is the most common "fix": tune the pool sizes so
137137 that they never overflow regardless of what the user does. For pools of
@@ -154,7 +154,7 @@ There are a few common strategies to handle this.
154154
155155 * * Forcibly kill an existing object.* Consider a pool for currently playing
156156 sounds, and assume you want to start a new sound but the pool is full. You
157- do * not* want to simply ignore the new sound: the user will notice if their
157+ do * not* want to simply ignore the new sound -- the user will notice if their
158158 magical wand swishes dramatically * sometimes* and stay stubbornly silent
159159 other times. A better solution is to find the quietest sound already playing
160160 and replace that with our new sound. The new sound will mask the audible
@@ -165,7 +165,7 @@ There are a few common strategies to handle this.
165165
166166 * * Increase the size of the pool.* If your game lets you be a bit more
167167 flexible with memory, you may be able to increase the size of the pool at
168- runtime, or create a second overflow pool. If you do grab more memory in
168+ runtime or create a second overflow pool. If you do grab more memory in
169169 either of these ways, consider whether or not the pool should contract to
170170 its previous size when the additional capacity is no longer needed.
171171
@@ -228,7 +228,7 @@ the memory manager will usually deal with fragmentation for you. But pools are
228228still useful there to avoid the cost of allocation and deallocation, especially
229229on mobile devices with slower CPUs and simpler garbage collectors.
230230
231- If you do use an object pool there , beware of a potential conflict. Since the
231+ If you do use an object pool in concert with a garbage collector , beware of a potential conflict. Since the
232232pool doesn't actually deallocate objects when they're no longer in use, they
233233remain in memory. If they contain references to * other* objects, it will prevent
234234the collector from reclaiming those too. To avoid this, when a pooled object is
@@ -237,7 +237,7 @@ no longer in use, clear any references it has to other objects.
237237## Sample Code
238238
239239Real-world particle systems will often apply gravity, wind, friction, and other
240- physical effects. Our much simpler sample will just move particles in a straight
240+ physical effects. Our much simpler sample will only move particles in a straight
241241line for a certain number of frames and then kill the particle. Not exactly film
242242caliber, but it should illustrate how to use an object pool.
243243
@@ -246,15 +246,15 @@ particle class:
246246
247247^code 1
248248
249- The default constructor initializes the particle to "not in use." A later call
249+ The default constructor initializes the particle to "not in use". A later call
250250to ` init() ` initializes the particle to a live state.
251251
252252Particles are animated over time using the unsurprisingly named ` animate() `
253253function, which should be called once per frame.
254254
255255The pool needs to know which particles are available for reuse. It gets this
256- from the particle's ` inUse() ` function. It takes advantage of the fact that
257- particles have a limited lifetime, and uses the ` _framesLeft ` variable to
256+ from the particle's ` inUse() ` function. This function takes advantage of the fact that
257+ particles have a limited lifetime and uses the ` _framesLeft ` variable to
258258discover which particles are in use without having to store a separate flag.
259259
260260The pool class is also simple:
@@ -275,7 +275,7 @@ class="pattern">Update Method</a> pattern.
275275The particles themselves are simply stored in a fixed-size array in the class.
276276In this sample implementation, the pool size is hardcoded in the class
277277declaration, but this could be defined externally by using a dynamic array of a
278- given size, or using a value template parameter.
278+ given size or by using a value template parameter.
279279
280280Creating a new particle is straightforward:
281281
@@ -286,7 +286,7 @@ find it, we initialize it and we're done. Note that in this implementation, if
286286there aren't any available particles, we simply don't create a new one.
287287
288288That's all there is to a simple particle system, aside from rendering the
289- particles, of course. We can now create a pool, and create some particles using
289+ particles, of course. We can now create a pool and create some particles using
290290it. The particles will automatically deactivate themselves when their lifetime
291291has expired.
292292
@@ -307,7 +307,7 @@ algorithms class.
307307
308308If we don't want to waste time * finding* free particles, the obvious answer is
309309to not lose track of them. We could store a separate list of pointers to each
310- unused particle. Then, when we need to create a particle, we just remove the
310+ unused particle. Then, when we need to create a particle, we remove the
311311first pointer from the list and reuse the particle it points to.
312312
313313Unfortunately, this would require us to maintain an entire separate array with
@@ -316,7 +316,7 @@ create the pool, *all* particles are unused, so the list would initially have a
316316pointer to every object in the pool.
317317
318318It would be nice to fix our performance problems * without* sacrificing any
319- memory. Conveniently, there is some memory already lying around we can borrow:
319+ memory. Conveniently, there is some memory already lying around that we can borrow --
320320the data for the unused particles themselves.
321321
322322When a particle isn't in use, most of its state is irrelevant. Its position and
@@ -326,7 +326,7 @@ other bits can be reused. Here's a revised particle:
326326
327327^code 4
328328
329- We've gotten all of the member variables except for ` framesLeft_ ` and moved them
329+ We've moved all of the member variables except for ` framesLeft_ `
330330into a ` live ` struct inside a ` state_ ` <span name =" union " >union</span >. This
331331struct holds the particle's state when it's being animated. When the particle is
332332unused, the other case of the union, the ` next ` member, is used. It holds a
@@ -336,15 +336,15 @@ pointer to the next available particle after this one.
336336
337337Unions don't seem to be used that often these days, so the syntax may be
338338unfamiliar to you. If you're on a game team, you've probably got a "memory
339- guru," that beleaguered compatriot whose job it is to come up with a solution
339+ guru", that beleaguered compatriot whose job it is to come up with a solution
340340when the game has inevitably blown its memory budget. Ask them about unions.
341341They'll know all about them and other fun bit-packing tricks.
342342
343343</aside >
344344
345345We can use these pointers to build a linked list that chains together every
346346unused particle in the pool. We have the list of available particles we need,
347- but didn't need to use any additional memory. Instead, we cannibalize the memory
347+ but we didn't need to use any additional memory. Instead, we cannibalize the memory
348348of the dead particles themselves to store the list.
349349
350350This clever technique is called a [ * free
@@ -360,7 +360,7 @@ list should thread through the entire pool. The pool constructor sets that up:
360360
361361^code 6
362362
363- Now to create a new particle, we just jump directly to the <span
363+ Now to create a new particle, we jump directly to the <span
364364name="first">first</span > available one:
365365
366366<aside name =" first " >
@@ -377,7 +377,7 @@ up the ghost in that frame:
377377
378378^code particle-animate
379379
380- When that happens, we just thread it back onto the list:
380+ When that happens, we simply thread it back onto the list:
381381
382382^code 8
383383
@@ -406,7 +406,7 @@ objects.
406406
407407 * * You can ensure that the objects can only be created by the pool.* In
408408 C++, a simple way to do this is to make the pool class a friend of the
409- object class, and then make the object's constructor private.
409+ object class and then make the object's constructor private.
410410
411411 ^code 10
412412
@@ -428,7 +428,7 @@ objects.
428428 reusable pool class.
429429
430430 * * The "in use" state must be tracked outside the objects.* The simplest
431- way to do this is by creating a separate bit field.
431+ way to do this is by creating a separate bit field:
432432
433433 ^code 11
434434
@@ -456,20 +456,20 @@ outside.
456456
457457 * * The pool's interface can be simpler.* Instead of offering multiple
458458 functions to cover each way an object can be initialized, the pool can
459- simply return a reference to the new object.
459+ simply return a reference to the new object:
460460
461461 ^code 13
462462
463463 The caller can then initialize the object by calling any method the
464- object exposes.
464+ object exposes:
465465
466466 ^code 14
467467
468468 * * Outside code may need to handle the failure to create a new object.*
469469 The previous example assumes that ` create() ` will always successfully
470470 return a pointer to an object. If the pool is full, though, it may
471471 return ` NULL ` instead. To be safe, you'll need to check for that before
472- you try to initialize the object.
472+ you try to initialize the object:
473473
474474 ^code 15
475475
@@ -478,7 +478,7 @@ outside.
478478 * This looks a lot like the <a class =" gof-pattern " href =" flyweight.html " >
479479 Flyweight</a > pattern. Both maintain a collection of reusable objects. The
480480 difference is what "reuse" means. Flyweight objects are reused by sharing
481- the same instance between multiple owners * simultaneously* . It avoids
481+ the same instance between multiple owners * simultaneously* . The Flyweight pattern avoids
482482 * duplicate* memory usage by using the same object in multiple contexts.
483483
484484 The objects in a pool get reused too, but only over time. "Reuse" in the
0 commit comments