Deferred Procedure Call System
Contents
Overview
The DPCS is intended to queue up routine calls for execution at a later point in time. Such instances where this might be useful would be:
- Performing a task at a later time (preferrably at the unwinding of the call stack)
- “Throwing” errors across DLL boundaries
- Collecting various events for a set of windows (e.g., redraw or update events) then executing all the events for all the windows at a single time
Terminology
- verb
- A singleton procedure that is called at a later date.
- verb_queue
- A collection of verbs.
- behavior
- A collection of verbs, verb queues, and other behaviors (subbehaviors). As verbs, verb queues, and subbehaviors are inserted into a behavior, the order in which they were inserted is retained, and becomes the order in which the behavior executes inserted children.
API
The current proposed API is as follows:
typedef boost::function<void ()> verb_t;
- A
verb_t
is a self-contained callback proc that is executed at a specific time
typedef struct verb_queue_t* verb_q_token_t;
- A
verb_queue_t
is a collection of verbs
typedef struct behavior_t* behavior_token_t;
- A
behavior_token_t
is a collection of verbs, verb queues, and other behaviors (subbehaviors)
behavior_token_t make_behavior(); void destroy_behavior(behavior_token_t behavior);
make_behavior
allocates a new behavior and returns the token to the client. The client is responsible for destroying the behavior with:destroy_behavior
destroys memory allocated for the the behavior. If the behavior is a subbehavior within another behavior, it is detached from its parent behavior. Likewise if the behavior being destructed contains any subbehaviors, they are destroyed as well.
void insert(behavior_token_t behavior, verb_t verb, bool single_execution);
- This version of
insert
will add a single verb at this current point in the behavior. ifsingle_execution
is true then the verb will be destroyed after the first time it is executed.
behavior_token_t insert_behavior(behavior_token_t behavior);
insert_behavior
adds a subbehavior at this current point in the behavior. The function returns to the client thebehavior_token_t
of the newly created subbehavior. You are not responsible for destroying the subbehavior, though you may if you choose to do so (detaching it from the parent behavior).
verb_q_token_t insert_queue(behavior_token_t behavior, bool single_execution);
insert_queue
adds a verb queue at this current point in the behavior. The function returns to the client theverb_q_token_t
of the newly created verb queue. You are not allowed to destroy verb queues. Ifsingle_execution
is set to true, every verb in the queue will be destroyed after the first time it is. However, the verb queue itself will not be destroyed, allowing for further verb insertion at a later point into the same queue.
bool empty(behavior_token_t behavior); std::size_t size(behavior_token_t behavior);
empty
returns to the client whether or not the behavior is empty.size
returns the number of singleton verbs, verb queues, and subbehaviors that have been inserted into this behavior.
void execute(behavior_token_t behavior);
execute
will iterate through the children of this behavior and execute them in the order in which they were inserted. Note that this ordering is “one level deep” – inserting a verb into a verb_queue that was inserted first into this behavior will result in that verb executing before any of the other immediate children of this behavior. If any verbs are marked assingle_execution
, they will not exist before this call is complete. Likewise, any verb queues markedsingle_execution
will be empty before the completion of this function call.
void insert(verb_q_token_t verb_q, verb_t verb);
- This version of
insert
will append a verb to the end of this verb queue.
bool empty(verb_q_token_t verb_q); std::size_t size(verb_q_token_t verb_q);
empty
returns to the client whether or not the verb queue is empty.size
returns the number of singleton verbs that have been inserted into this verb queue.
void execute(verb_q_token_t verb_q);
execute
will iterate through the verbs of this verb queue and execute them in the order in which they were inserted into this queue. If this verb queue was markedsingle_execution
it will be empty before the completion of this function call.
template<>
struct delete_ptr<behavior_token_t>
{
typedef void result_type;
void operator()(behavior_token_t x) const
{ if (x) destroy_behavior(x); }
};
- This template specialization is intended for use with the
adobe::auto_resource
class.
verb_q_token_t general_deferred_proc_queue();
- The general deferred proc queue is a catchall verb queue for verbs that need to be executed at the end of this iteration through the application’s event loop. It is constructed as a
single_execution
verb queue. The application binary is required to execute this verb queue at the end of every iteration of its event loop.
Issues
- There is a need for better locality - these are all things that have to happen after something else - the problem is the “something else” should not be known locally to the code doing the queuing.
- The basic need is for an explicit set of connections made by whatever code is connecting things up