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_tis a self-contained callback proc that is executed at a specific time
typedef struct verb_queue_t* verb_q_token_t;
- A
verb_queue_tis a collection of verbs
typedef struct behavior_t* behavior_token_t;
- A
behavior_token_tis a collection of verbs, verb queues, and other behaviors (subbehaviors)
behavior_token_t make_behavior(); void destroy_behavior(behavior_token_t behavior);
make_behaviorallocates a new behavior and returns the token to the client. The client is responsible for destroying the behavior with:destroy_behaviordestroys 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
insertwill add a single verb at this current point in the behavior. ifsingle_executionis true then the verb will be destroyed after the first time it is executed.
behavior_token_t insert_behavior(behavior_token_t behavior);
insert_behavioradds a subbehavior at this current point in the behavior. The function returns to the client thebehavior_token_tof 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_queueadds a verb queue at this current point in the behavior. The function returns to the client theverb_q_token_tof the newly created verb queue. You are not allowed to destroy verb queues. Ifsingle_executionis 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);
emptyreturns to the client whether or not the behavior is empty.sizereturns the number of singleton verbs, verb queues, and subbehaviors that have been inserted into this behavior.
void execute(behavior_token_t behavior);
executewill 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_executionwill be empty before the completion of this function call.
void insert(verb_q_token_t verb_q, verb_t verb);
- This version of
insertwill 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);
emptyreturns to the client whether or not the verb queue is empty.sizereturns the number of singleton verbs that have been inserted into this verb queue.
void execute(verb_q_token_t verb_q);
executewill 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_executionit 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_resourceclass.
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_executionverb 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