Simple coroutine library / objects in plain C Snapshot
cthread.h
Go to the documentation of this file.
00001 #ifndef __CTHREAD_H__
00002 #define __CTHREAD_H__
00003 
00004 
00005 #include <ucontext.h>
00006 #include <stdint.h>
00007 #include <corothread/stacks.h>
00008 #include <corothread/val.h>
00009 
00010 /** 
00011  * @defgroup CTHREAD
00012  * @brief a coroutine thread.
00013  *
00014  * A very limited user mode threading package that allows constructions of co-routines.
00015  * Coroutine scheduling is done by mean of mkcontet/setcontext/getcontext functions (glibc)
00016  *
00017  * User mode threads are best when used in a very limited scenario, complex usage scenarios often
00018  * lead to intricate situations that are hard to debug.
00019  * Areas where user mode threading shines 
00020  *   - coroutines / continuations
00021  *   - generator funcions (like python/ruby/perl).
00022  *
00023  *
00024  * @{
00025  */
00026 
00027 typedef void  (*CTHREAD_PROC) (VALUES *);
00028 
00029 typedef enum {
00030   CTHREAD_STATE_INIT,
00031   CTHREAD_STATE_RUNNING,
00032   CTHREAD_STATE_SUSPENDED,
00033   CTHREAD_STATE_EXIT,
00034 } CTHREAD_STATE;
00035 
00036 
00037 
00038 typedef struct tagCTHREAD {
00039   ucontext_t context_coroutine;
00040   ucontext_t context_caller;
00041   CTHREAD_STATE state;
00042   uint32_t thread_id;
00043  
00044   int    thread_to_caller_value_set;
00045   VALUES thread_to_caller_value; 
00046   int    caller_to_thread_value_set;
00047   VALUES caller_to_thread_value;  
00048 
00049   CTHREAD_PROC proc;  
00050   struct tagCTHREAD *prev_thread;
00051   STACK_ENTRY *stack_entry;  
00052 } CTHREAD;
00053 
00054  
00055 
00056 /**
00057  * @brief library initialisation
00058  */
00059 int CTHREAD_libinit();
00060 
00061 /**
00062  * @brief initialises a new co-routine thread. 
00063  
00064  * Postcondition: The new thread is initialised and enters CTHREAD_STATE_INIT state.
00065 
00066  * @param stacks the thread is obtained from the pool of stacks (argument stack).
00067  * @param proc The thread procecdure is argument proc.
00068  */
00069 CTHREAD * CTHREAD_init( STACKS *stacks, CTHREAD_PROC proc );
00070 
00071 /**
00072  * deallocates a thread 
00073  *
00074  * Precondition: the thread must be in CTHREAD_STATE_EXIT state 
00075  */ 
00076 int CTHREAD_free( CTHREAD *thread );
00077 
00078 /**
00079  * @brief start a new thread - the thread procedure is invoked.
00080  *
00081  * The initialised thread is started; The function returns if the running thread either exited or entered suspended state (i.e. the thread called CTHREAD_yield)
00082  *
00083  * Values passed from the thread to the caller are stored in rvalue parameter.
00084  * If this parameter is 0 then the return values are ignored.
00085  * 
00086  * Values passed from the caller to the thread -
00087  *   
00088  * Precondition: the thread is in either CTHREAD_STATE_INIT or CTHREAD_STATE_EXIT state.
00089  * Postcondition: the thread is in CTHREAD_STATE_RUNNING state.
00090  *
00091  */
00092 int CTHREAD_start( CTHREAD *thread, VALUES **rvalue, const char *format , ... );
00093 
00094 
00095 /**
00096  * @brief resume a suspended thread
00097  *
00098  * Resumes a suspended thread, the function will return when the resumed thread calls CTHREAD_yield or when it exits.
00099  *
00100  * Passing parameters to the thread; a variable length set of arguments can be sent to the thread, and the thread will be able to read them.
00101  * Parameter format is the format specifier, subsequent variable length argument values are then sent to the thread.
00102  *  
00103  * Retrieving parameters from the thread:
00104  * We can access values returned by the thread, once CTHREAD_resume returns. The values passed by the thread are stored in rvalue parameter.
00105  *
00106  * Precondition: the thread is in CTHREAD_STATE_SUSPENDED state
00107  * Postcondition: the thread is in CTHREAD_STATE_RUNNING state
00108   */
00109 int CTHREAD_resume( CTHREAD *thread, VALUES **rvalue, const char *format, ... );
00110 
00111 
00112 
00113 
00114 /**
00115  * @brief a running thread temporarily suspends execution
00116  *
00117  * Precondition: the thread is in CTHREAD_STATE_RUNNING state
00118  * Postcondition: the thread is in CTHREAD_STATE_SUSPENDED state
00119  
00120  
00121  */
00122 int CTHREAD_yield(VALUES **rvalue, const char *format, ... );
00123 
00124 /**
00125  * @brief waits till the thread has finished 
00126  * Calls CTHREAD_resume repeatedly unntil the thread finishes.
00127  */
00128 int CTHREAD_join( CTHREAD *thread, VALUES **rvalue );
00129 
00130 
00131 /**
00132  * @brief a running thread sets it return values
00133  *
00134  */
00135 int CTHREAD_set_return_value( const char *format, ... );
00136 
00137 /**
00138  * @brief get thread id
00139  *
00140  * Precondition: the thread is in any state other than CTHREAD_STATE_INIT
00141  */
00142 uint32_t CTHREAD_get_tid();
00143 
00144 /**
00145  * @brief get thread state
00146  */
00147 M_INLINE CTHREAD_STATE CTHREAD_state(CTHREAD *thread) 
00148 {
00149   return thread->state;
00150 }
00151 
00152 /**
00153  * @}
00154  */
00155 
00156 #endif
00157 
00158