commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Tom <t...@tbee.org>
Subject [POOL] a conceptual implementation error?
Date Mon, 20 Nov 2006 12:25:38 GMT
Bear with me on this one...

The pool implementation splits pools into two parts: a provider of new 
objects (PoolableObjectFactory) and a pooling behaviour (Pool). This is 
a good idea, since this allows separation of content and behaviour: the 
same source of poolable objects can be used in a round-robin or stacked 
behaviour.

Now, in the current implementation, when the pool runs dry, the active 
pooling behaviour can do one of three things: wait, create a new one, or 
fail. For example: GenericObjectPool has settings to specify what 
behaviour should be used: WHEN_EXHAUSTED_BLOCK, WHEN_EXHAUSTED_GROW, 
WHEN_EXHAUSTED_FAIL. Behaviour 1 and 3 are straight forward, but "GROW" 
is what I am having problems with.

If we consider GROW behaviour in the current implementation, we can look 
at this as two sets inside the pool: one set with actively pooled 
objects (those managed by the pool and on this pool the max active, etc 
applies) and a second set with so far unpooled objects. The unpooled 
objects may not even be instantiated, but theoretically they exists. 
When the pool runs dry in GROW behaviour and thus needs a new object, 
one object is moved from the unpooled set to the pooled set.

I consider this two-set setup an implementation detail: conceptually the 
pool consist of both the actively pooled and unpooled objects, the user 
of the pool just request a new object and the pool then must figure out 
how to get one and whether or not to juggle between the sets.

Now to my point: in the current implementation this GROW behaviour ONLY 
applies to the pooled objects set. An that is IMHO incorrect. What 
should happen is: if the pooled objects set has run dry must ALWAYS try 
to fetch from the unpooled set, only if the unpooled set also has run 
dry, then the pool must decided wheter to BLOCK or WAIT. So it does not 
matter if the pooled set ran dry, BOTH set must have run dry in order to 
BLOCK or WAIT. Currently the StackedObjectPool goes into a very CPU 
consuming busy-waiting loop, and the GenericObjectPool just acceps null 
as the value.

As state above, the behaviour should be applied on the combined set, not 
just the pooled set. Initially it seems that the behaviour should be 
extended to the unpooled set, however if you consider this for a moment 
longer, it turns out that the GROW behavour is actually not needed. 
Given that the implementation detail of the pooled and unpooled sets is 
of no concern to the user of the pool, he has no business in defining if 
a pool should GROW. Either the pool is infinite (the factory can endless 
continue creating new objects) or it is not. If the pool is infinite, 
BLOCK and WAIT are of no concern. If the pool is not infinite and runs 
dry, the pool can either WAIT for an object to be returned or FAIL. 
There is no GROW.

So, to summarize:
- Pools handle the pooled object set according to specs (max active, min 
active, etc).
- Pool always GROW, its is the factory that decides if there is a new 
object available or not.
- If the factory says there is no more object (the pool ran dry), then 
the pool decides if it will WAIT or FAIL.
- The pool may decide that certain pooled objects are returned to the 
unpool set (destroy), when for example the "max active" is overflow.

Now, tell me if I see this wrong or not. As said before: currently the 
StackedObjectPool goes CPU mongol on a dry pool and the 
GenericObjectPool just returns null. I currently consider both 
implementations seriously bugged.

Tom

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-user-help@jakarta.apache.org


Mime
View raw message