Lightweight Context Switching

Lightweight Context Switching — Support for asychronous execution

Synopsis


#include <monitor/monitor.h>


            mon_ctx;
enum        mon_ctx_flags;
mon_ctx*    mon_ctx_new                     (void);
void        mon_ctx_free                    (mon_ctx *ctx);
int         mon_ctx_step                    (mon_ctx *ctx);
void        mon_ctx_enter                   (mon_ctx *ctx);
void        mon_ctx_leave                   (mon_ctx *ctx);
int         mon_ctx_add_data                (mon_ctx *ctx,
                                             const char *key,
                                             void *value,
                                             GDestroyNotify free);
int         mon_ctx_set_data                (mon_ctx *ctx,
                                             const char *key,
                                             void *value,
                                             GDestroyNotify free);
void        mon_ctx_del_data                (mon_ctx *ctx,
                                             const char *key);
void*       mon_ctx_get_data                (mon_ctx *ctx,
                                             const char *key);
void        mon_ctx_abort                   (mon_ctx *ctx);
            mon_ctx_frame;
mon_ctx_frame* mon_ctx_frame_new            (mon_ctx *ctx,
                                             void *priv,
                                             int (*do_step) (mon_ctx_frame *frame),
                                             void (*done) (mon_ctx_frame *frame));
void        mon_ctx_frame_del               (mon_ctx_frame *frame);
void        mon_ctx_frame_simple_done       (mon_ctx_frame *frame);

            mon_ctx_grp;
            mon_ctx_grp_ctx;
void        mon_ctx_grp_done                (mon_ctx_grp *grp);
enum        mon_ctx_grp_flags;
mon_ctx_grp* mon_ctx_grp_new                (mon_ctx *parent,
                                             mon_ctx_grp_flags flags);
mon_ctx*    mon_ctx_grp_new_ctx             (mon_ctx_grp *grp,
                                             void *owner,
                                             void *user_data,
                                             GDestroyNotify user_data_done,
                                             int (*frame_step) (mon_ctx_frame *frame),
                                             void (*frame_done) (mon_ctx_frame *frame));
void        mon_ctx_grp_ref                 (mon_ctx_grp *grp);
int         mon_ctx_grp_finish              (mon_ctx_grp *gctx);

Description

Details

mon_ctx

typedef struct {
	int			result;
	time_t			timeout;
	int			rundepth: 16;
	mon_ctx_flags		flags : 16;
	GList			*frames;
	GList			*data;
} mon_ctx;

The mon_ctx structure contains an execution context.

int result;the result of the last function call inside this context.
time_t timeout;timeout of this context (currently unused).
int rundepth : 16;counter used for reentrancy protection.
mon_ctx_flags flags : 16;one or more of mon_ctx_flags.
GList *frames;the stack of functions that are waiting for execution.
GList *data;the list of context-global data elements.

enum mon_ctx_flags

typedef enum {
	MON_CTX_AUTOFREE	= (1 << 0),
	MON_CTX_ABORTED		= (1 << 1),
	MON_CTX_RUNNING		= (1 << 2)
} mon_ctx_flags;

Flags for a mon_ctx structure.

MON_CTX_AUTOFREEthe mon_ctx shold be freed when the last frame terminates or when the context is aborted.
MON_CTX_ABORTEDthis flag is set by mon_ctx_abort() to indicate that the context is being aborted.
MON_CTX_RUNNINGthis flag is used internally to prevent recursive calls to mon_ctx_step().

mon_ctx_new ()

mon_ctx*    mon_ctx_new                     (void);

Allocates a new empty mon_ctx.

Returns :a mon_ctx.

mon_ctx_free ()

void        mon_ctx_free                    (mon_ctx *ctx);

Deallocates a mon_ctx.

ctx :a mon_ctx.

mon_ctx_step ()

int         mon_ctx_step                    (mon_ctx *ctx);

Calls the topmost frame in the context's frame stack. If that frame returns MON_CONTINUE, mon_ctx_step() also returns MON_CONTINUE and the next call will start the same function again. If the frame returns any other value, ctx->result is set to this value, the frame is removed from the stack, and the new topmost frame is tried. This continues until one frame returns MON_CONTINUE or there are no more frames left.

ctx :a mon_ctx.
Returns :the result of the last executed frame.

Note

If the MON_CTX_AUTOFREE flag was set for the context, the ctx pointer might not be valid anymore after this function returns

mon_ctx_enter ()

void        mon_ctx_enter                   (mon_ctx *ctx);

Marks a mon_ctx as being under execution and thus prevents it from being deallocated by calls like mon_ctx_step() or mon_ctx_abort().

ctx :a mon_ctx.

mon_ctx_leave ()

void        mon_ctx_leave                   (mon_ctx *ctx);

Undoes the effect of the last mon_ctx_enter(). Must be called exactly as many times as mon_ctx_enter() was called. If the context is empty (all frames have exited) or has been aborted and MON_CTX_AUTOFREE is set, the context is deallocated.

ctx :a mon_ctx.

mon_ctx_add_data ()

int         mon_ctx_add_data                (mon_ctx *ctx,
                                             const char *key,
                                             void *value,
                                             GDestroyNotify free);

Adds some context-global data to a mon_ctx. If context-global data with the same key exists already, the function fails.

ctx :a mon_ctx.
key :the key of the data. It must be a static string constant.
value :the value of the key.
free :function to be called to deallocate the value when the context finishes.
Returns :0 if successful or an error code.

mon_ctx_set_data ()

int         mon_ctx_set_data                (mon_ctx *ctx,
                                             const char *key,
                                             void *value,
                                             GDestroyNotify free);

Adds some context-global data to a mon_ctx. If context-global data with the same key exists already, it is overwritten with the new value.

ctx :a mon_ctx.
key :the key of the data. It must be a static string constant.
value :the value of the key.
free :function to be called to deallocate the value when the context finishes.
Returns :0 if successful or an error code.

mon_ctx_del_data ()

void        mon_ctx_del_data                (mon_ctx *ctx,
                                             const char *key);

Removes context-global data from a mon_ctx.

ctx :a mon_ctx.
key :the key of the data to remove.

mon_ctx_get_data ()

void*       mon_ctx_get_data                (mon_ctx *ctx,
                                             const char *key);

Returns context-global data for a given key.

ctx :a mon_ctx.
key :the key of the data.
Returns :

mon_ctx_abort ()

void        mon_ctx_abort                   (mon_ctx *ctx);

Aborts the execution of a mon_ctx. The context's result value is set to MON_ERR_CTX_ABORTED and all frames are removed from the stack. If the MON_CTX_AUTOFREE flag was set for ctx, mon_ctx_free() is also called.

ctx :a mon_ctx to abort.

mon_ctx_frame

typedef struct {
	mon_ctx			*ctx;
	void			*priv;
	int			(*do_step)(mon_ctx_frame *frame);
	void			(*done)(mon_ctx_frame *frame);
} mon_ctx_frame;

Defines an executing frame in a mon_ctx (somewhat similar to a stack frame).

mon_ctx *ctx;the owner mon_ctx.
void *priv;frame-private data.
do_step ()function to call when this frame is to be executed.
done ()function to call when this frame is removed from the stack.

mon_ctx_frame_new ()

mon_ctx_frame* mon_ctx_frame_new            (mon_ctx *ctx,
                                             void *priv,
                                             int (*do_step) (mon_ctx_frame *frame),
                                             void (*done) (mon_ctx_frame *frame));

Allocates a new mon_ctx_frame.

ctx :the mon_ctx where this frame belongs.
priv :frame-private data.
do_step :the function to call when this frame is to be executed.
done :the function to call when this frame is removed from the stack. It should de-allocate resources held by priv.
Returns :a new mon_ctx_frame or NULL if out of memory.

mon_ctx_frame_del ()

void        mon_ctx_frame_del               (mon_ctx_frame *frame);

Removes a frame from its owner's stack.

frame :a mon_ctx_frame to remove.

mon_ctx_frame_simple_done ()

void        mon_ctx_frame_simple_done       (mon_ctx_frame *frame);

Simple helper routine that deallocates the frame private data.

frame :a mon_ctx_frame.

mon_ctx_grp

typedef struct {
	mon_ctx			*parent;
	mon_ctx_frame		*parent_frame;
	mon_ctx_grp_flags	flags;

	unsigned int		total;
	unsigned int		failed;
	unsigned int		completed;

	int			last_error;
	int			refcnt;
} mon_ctx_grp;

The mon_ctx_grp structure binds several child contexts to a parent context.

mon_ctx *parent;the parent context.
mon_ctx_frame *parent_frame;the mon_ctx_frame created by mon_ctx_grp_new().
mon_ctx_grp_flags flags;one or more of mon_ctx_grp_flags.
unsigned int total;total number of child contexts belonging to this group.
unsigned int failed;number of child contexts that exited with a non-0 result.
unsigned int completed;number of child contexts that exited with a 0 result.
int last_error;error code from the last failed child context.
int refcnt;reference count.

mon_ctx_grp_ctx

typedef struct {
	mon_ctx_grp		*container;
	void			*owner;
	void			*user_data;
	GDestroyNotify		user_data_done;
} mon_ctx_grp_ctx;

Structure used to bind a child context to the mon_ctx_grp it belongs to.

mon_ctx_grp *container;the mon_ctx_grp this child belongs to.
void *owner;owner of this mon_ctx_grp_ctx structure. This field is freely available for users.
void *user_data;arbitrary user data. This field is freely available for users.
GDestroyNotify user_data_done;destructor for user_data. If not NULL, it is called with user_data being its argument when the mon_ctx_grp_ctx structure is destroyed.

mon_ctx_grp_done ()

void        mon_ctx_grp_done                (mon_ctx_grp *grp);

Decrements the reference count of a mon_ctx_grp structure. If the reference count reaches zero, the object is deallocated.

grp :a mon_ctx_grp.

enum mon_ctx_grp_flags

typedef enum {
	MON_CTX_GRP_STRICT	= (1 << 0)
} mon_ctx_grp_flags;

Flags for controlling the use of a mon_ctx_grp structure.

MON_CTX_GRP_STRICTif this flag is not set, the parent context is waken up as soon as the first child successfully exits. If this flag is set, all child contexts must exit before the parent can continue.

mon_ctx_grp_new ()

mon_ctx_grp* mon_ctx_grp_new                (mon_ctx *parent,
                                             mon_ctx_grp_flags flags);

Allocates a new mon_ctx_grp structure.

parent :the parent mon_ctx that will be notified when the child contexts exit.
flags :one or more of the values of mon_ctx_grp_flags.
Returns :a new mon_ctx_grp structure.

mon_ctx_grp_new_ctx ()

mon_ctx*    mon_ctx_grp_new_ctx             (mon_ctx_grp *grp,
                                             void *owner,
                                             void *user_data,
                                             GDestroyNotify user_data_done,
                                             int (*frame_step) (mon_ctx_frame *frame),
                                             void (*frame_done) (mon_ctx_frame *frame));

Allocates a new child context bound to a mon_ctx_grp container.

grp :the mon_ctx_grp the child context will belong to.
owner :value to be stored in the owner field of the mon_ctx_grp_ctx structure that is passed to frame_step frame_done.
user_data :value to be stored in the user_data field of the mon_ctx_grp_ctx structure that is passed to frame_step and frame_done.
user_data_done :destructor for user_data.
frame_step :function to call when the last frame of the child context terminates. The priv field of the frame argument will point to a mon_ctx_grp_ctx structure that is initialized with values grp, owner, user_data and user_data_done.
frame_done :frame destructor to call for the frame passed to frame_step. The priv field of the frame points to the same mon_ctx_grp_ctx structure described with frame_step.
Returns :the child mon_ctx context.

mon_ctx_grp_ref ()

void        mon_ctx_grp_ref                 (mon_ctx_grp *grp);

Increments the reference count of a mon_ctx_grp structure.

grp :a mon_ctx_grp.

mon_ctx_grp_finish ()

int         mon_ctx_grp_finish              (mon_ctx_grp *gctx);

Performs checks on a mon_ctx_grp after all child contexts belonging to it have been created. If there were no child contexts or they all have already completed, the extra frame added to the parent context by mon_ctx_grp_new() is removed. If there are child contexts pending, MON_CONTINUE is returned. Otherwise, the return status of the last failing child context is returned (or 0 if all child contexts have finished successfully).

gctx :a mon_ctx_grp.
Returns :0 if all child contexts finished successfully, MON_CONTINUE if there are pending child contexts or an error code. The returned value is suitable as the return code of the parent context.