c# - Implementing a pool with a time limit -


continuing question:

correct way implement resource pool

i'm thinking implementing maximum amount of time user of pool allowed continue hold on object pool, i'm not sure of right way implement such thing. so, have this:

ifoo getfoofrompool() {     if (_sem.wait(waittimeout))     {         return pop();     }     throw new waittimeoutexception("timed out waiting foo instance"); } 

so _sem semaphore , pop pop off instance stack (initializing if needed), far good.

when caller done ifoo, return stack so:

void releasefoo(ifoo p) {     if (p == null)     {         throw new argumentnullexception("foo parameter null");     }     push(p);     _sem.release(); } 

and wrap wrapper class using idisposable ensure foo gets returned pool. client side, looks this:

using (var f = mypool.getdisposablefoo()) {     // stuff... } 

what i'd have such if // stuff takes long (or hangs), ifoo recycled , calling code throw exception.

so thought of doing this:

private ifoo pop() {     ifoo p;     _stack.trypop(out p);     if (p == null)     {         p = runfactory();   // lazy initialization of stack     }     if (maximumloantime > 0)     {         p.currenttoken = new cancellationtokensource();         task.delay(maximumloantime, p.currenttoken.token).continuewith(() =>         {             // timeout, return stack             // inform current owner???             push(p);         });     }     return p; } 

the problem how make sure current holder gets signaled doesn't continue try , use instance of ifoo might in use else.

so ended adding loanexpired event , onloanexpired method ifoo. works this:

private ifoo pop() {     ifoo p;     _stack.trypop(out p);     if (p == null)     {         p = runfactory();   // lazy initialization of stack     }     if (maximumloantime > 0)     {         p.currenttoken = new cancellationtokensource();         task.delay(maximumloantime, p.currenttoken.token).continuewith(() =>         {                 p.currenttoken.dispose();                 p.onloanexpired();         }, taskcontinuationoptions.notoncanceled);     }     return p; } 

returning expired loan object deferred foowrapper subscribes loanexpired event of foo instance it's wrapping:

private void foo_loanexpired(object sender, eventargs e) {     isdisposed = true;    // checked on attempt use object     foo.loanexpired -= foo_loanexpired;          _pool.returnexpiredloan(foo);     onloanexpired();                                // pass event client handlers } 

and in pool, returnexpiredloan looks this:

void returnexpiredloan(ifoo p) {     // since it's expired, there risk broken or hung     // push null on stack force fresh instance next time around     _stack.push(null);     _sem.release();      p.dispose(); } 

now made decision dump expired foo , create new 1 in particular case, wouldn't right approach different resource.

and couple of other changes, when foowrapper disposed, have unsubscribe event handler:

public void dispose() {     foo.loanexpired -= foo_loanexpired;     if (!isdisposed)        // don't try , return instance if killed     {         _pool.releasefoo(foo);     } } 

and when push foo on stack, need cancel expiration , dispose token source:

private void push(ifoo p) {     if (p.currenttoken != null)     {         p.currenttoken.cancel();         p.currenttoken.dispose();         p.currenttoken = null;     }     _stack.push(p); } 

Comments

Popular posts from this blog

javascript - Using jquery append to add option values into a select element not working -

Android soft keyboard reverts to default keyboard on orientation change -

Rendering JButton to get the JCheckBox behavior in a JTable by using images does not update my table -