From: simon meiklejohn (simon_at_[hidden])
Date: 2005-12-09 15:22:21
This post suggests apply a Decorator like pattern to the
Defer/Asio::demuxer style libraries. Where previously
a component requests a deferred execution of a function f()
it would now be possible to get f() called at the end
of a chain of wrapping functions
a( b( c( d( e( f() ) ) ) ) );
the decorating functions would be of the form
void func( boost::function( void (void) ) )
i.e. they can be composed into a chain using boost::bind
Of itself that looks pretty trivial. Where it becomes more
interesting is when you consider
1. who injects the extra functions and when.
2. what can be done inside those function objects
looking at the second - why would we want to decorate
the eventual callback? Here are some possibilities
1. try to obtain some resource. If its not obtainable,
then return without calling the decorated function
2. wait on a lock before proceeding (i.e. similar
to the defer_mutex concept)
3. Create an object on the stack that helps the
decorated callback - e.g. add a logging context
string ("ACME callback" so when the eventual code
calls LOG( "hello" ) what gets logged is
Apply this repeatedly - so the defer object, the defer
requester and the callback target each insert a
logging prefix, so LOG("hello") becomes
"[DeferPool][Acme callback][My acme observer]hello"
The three components that might have interesting things
to insert into the chain are:
1. the owner of f() (i.e. the component registering for a callback)
when it registers the callback. Lets say it inserts d() and e().
2. the originator of the callback (e.g. the parser component
from a prevoius discussion) when it initiates the callback,
or when the client callback is registered
3. the provider of the defer object (e.g. main()), when
it constructs the defer object.
In addition to code to be executed in the chain of every callback
its desirable to insert code that be executed just
once by each thread in a pool (e.g. to get the pesky
CoInitializeEx() called before servicing requests).
Lets call these Base Thread Decorators.
It may help to illustrate if i show a pseudo stack trace
at the point where a callback has finally reached the
innermost callback (f() in the above example).
[top of stack]
...client supplied decorators
... callback originator decorators
... per defer object decorators (provided by main)
defer_point::service_deferrals() - the thread waits for work
.... base thread decorators (provided by main)
a() - e.g. call CoInitEx...
.... thread entry point
[bottom of stack]
So i guess the point is - defer_point could usefully provide
some methods for injecting decorators to be applied
to all callbacks, as well as some methods to help
callback recipients and callback originators
to decorate their callbacks.
Does this seem a useful addition? Just more crazy talk
from a thread-obsessed idiot?