Branch: Tag:

2001-02-01

2001-02-01 19:58:56 by Henrik Grubbström (Grubba) <grubba@grubba.org>

Added some AutoDoc mk II markup.

Rev: src/threads.c:1.151

1:   #include "global.h" - RCSID("$Id: threads.c,v 1.150 2001/01/24 08:17:28 hubbe Exp $"); + RCSID("$Id: threads.c,v 1.151 2001/02/01 19:58:56 grubba Exp $");      PMOD_EXPORT int num_threads = 1;   PMOD_EXPORT int threads_disabled = 0;
289:    threads_disabled));   }    + /*! @decl object(_disable_threads) _disable_threads() +  *! +  *! This function first posts a notice to all threads that it is time to stop. +  *! It then waits until all threads actually *have* stopped, and then then +  *! returns an object. All other threads will be blocked from running until +  *! that object has been freed/destroyed. +  *! +  *! @note +  *! This function can completely block Pike if used incorrectly. +  *! Use with extreme caution. +  */   void init_threads_disable(struct object *o)   {    low_init_threads_disable();
510:    by incrementing refcount though. */   }    + /*! @module Thread +  */    -  + /*! @decl array(Thread.Thread) all_threads() +  *! +  *! This function returns an array with the thread ids of all threads. +  *! +  *! @seealso +  *! @[Thread.Thread()] +  */   PMOD_EXPORT void f_all_threads(INT32 args)   {    /* Return an unordered array containing all threads that was running
679:   int num_lwps = 1;   #endif    + /*! @class Thread +  */ +  + /* @decl void create(function(mixed...:void) f, mixed ... args) +  *! +  *! This function creates a new thread which will run simultaneously +  *! to the rest of the program. The new thread will call the function +  *! @[f] with the arguments @[args]. When @[f] returns the thread will cease +  *! to exist. +  *! +  *! All Pike functions are 'thread safe' meaning that running +  *! a function at the same time from different threads will not corrupt +  *! any internal data in the Pike process. +  *! +  *! @returns +  *! The returned value will be the same as the return value of +  *! @[Thread.this_thread()] for the new thread. +  *! +  *! @note +  *! This function is only available on systems with POSIX or UNIX or WIN32 +  *! threads support. +  *! +  *! @seealso +  *! @[Mutex], @[Condition], @[this_thread()] +  */   void f_thread_create(INT32 args)   {    THREAD_T dummy;
722:    }   }    + /*! @endclass +  */ +    #ifdef UNIX_THREADS -  + /*! @decl void thread_set_concurrency(int concurrency) +  */   void f_thread_set_concurrency(INT32 args)   {    int c=1;
734:   }   #endif    + /*! @decl Thread.Thread this_thread() +  *! +  *! This function returns the object that identifies this thread. +  *! +  *! @seealso +  *! @[Thread.Thread()] +  */   PMOD_EXPORT void f_this_thread(INT32 args)   {    pop_n_elems(args);
764:      #define OB2KEY(X) ((struct key_storage *)((X)->storage))    + /*! @class Mutex +  *! +  *! @[Thread.Mutex] is a class that implements mutual exclusion locks. +  *! Mutex locks are used to prevent multiple threads from simultaneously +  *! execute sections of code which access or change shared data. The basic +  *! operations for a mutex is locking and unlocking. If a thread attempts +  *! to lock an already locked mutex the thread will sleep until the mutex +  *! is unlocked. +  *! +  *! @note +  *! This class is simulated when Pike is compiled without thread support, +  *! so it's always available. +  *! +  *! In POSIX threads, mutex locks can only be unlocked by the same thread +  *! that locked them. In Pike any thread can unlock a locked mutex. +  */ +  + /*! @decl MutexKey lock() +  *! @decl MutexKey lock(int type) +  *! +  *! This function attempts to lock the mutex. If the mutex is already +  *! locked by a different thread the current thread will sleep until the +  *! mutex is unlocked. The value returned is the 'key' to the lock. When +  *! the key is destructed or has no more references the lock will +  *! automatically be unlocked. The key will also be destructed if the lock +  *! is destructed. +  *! +  *! The @[type] argument specifies what @[lock()] should do if the +  *! mutex is already locked by this thread: +  *! @int +  *! @value 0 (default) +  *! Throw an error. +  *! @value 1 +  *! Sleep until the mutex is unlocked. Useful if some +  *! other thread will unlock it. +  *! @value 2 +  *! Return zero. This allows recursion within a locked region of +  *! code, but in conjunction with other locks it easily leads +  *! to unspecified locking order and therefore a risk for deadlocks. +  *! @endint +  *! +  *! @seealso +  *! @[trylock()] +  */   void f_mutex_lock(INT32 args)   {    struct mutex_storage *m;
842:    push_object(o);   }    + /*! @decl MutexKey trylock() +  *! @decl MutexKey trylock(int type) +  *! +  *! This function performs the same operation as @[lock()], but if the mutex +  *! is already locked, it will return zero instead of sleeping until it's +  *! unlocked. +  *! +  *! @seealso +  *! @[lock()] +  */   void f_mutex_trylock(INT32 args)   {    struct mutex_storage *m;
912:    co_destroy(& THIS_MUTEX->condition);   }    + /*! @endclass +  */ +    #define THIS_KEY ((struct key_storage *)(CURRENT_STORAGE))   void init_mutex_key_obj(struct object *o)   {
949:   }      #define THIS_COND ((COND_T *)(CURRENT_STORAGE)) +  + /*! @class Condition +  *! +  *! Implementation of condition variables. +  *! +  *! Condition variables are used by threaded programs +  *! to wait for events happening in other threads. +  *! +  *! @note +  *! Condition variables are only available on systems with thread +  *! support. The Condition class is not simulated otherwise, since that +  *! can't be done accurately without continuations. +  *! +  *! @seealso +  *! @[Thread.Mutex] +  */ +  + /*! @decl void wait() +  *! @decl void wait(Thread.MutexKey mutex_key) +  *! +  *! Wait for contition. +  *! +  *! This function makes the current thread sleep until the condition +  *! variable is signalled. The optional argument should be the 'key' +  *! to a mutex lock. If present the mutex lock will be unlocked before +  *! waiting for the condition in one atomic operation. After waiting +  *! for the condition the mutex referenced by mutex_key will be re-locked. +  *! +  *! @seealso +  *! @[Thread.Mutex->lock()] +  */   void f_cond_wait(INT32 args)   {    COND_T *c;
1010:    pop_n_elems(args);   }    + /*! @decl void signal() +  *! +  *! @[signal()] wakes up one of the threads currently waiting for the +  *! condition. +  *! +  *! @bugs +  *! Sometimes more than one thread is woken up. +  *! +  *! @seealso +  *! @[broadcast()] +  */   void f_cond_signal(INT32 args) { pop_n_elems(args); co_signal(THIS_COND); } -  +  + /*! @decl void broadcast() +  *! +  *! @[broadcast()] wakes up all threads currently waiting for this condition. +  *! +  *! @seealso +  *! @[signal()] +  */   void f_cond_broadcast(INT32 args) { pop_n_elems(args); co_broadcast(THIS_COND); } -  +    void init_cond_obj(struct object *o) { co_init(THIS_COND); }   void exit_cond_obj(struct object *o) { co_destroy(THIS_COND); }    -  + /*! @endclass +  */ +  + /*! @class Thread +  */ +    /* FIXME: -Hubbe */ -  + /*! @decl array(mixed) backtrace() +  *! +  *! Returns the current call stack for the thread. +  *! +  *! @returns +  *! The result has the same format as for @[predef::backtrace()]. +  *! +  *! @seealso +  *! @[predef::backtrace()] +  */   void f_thread_backtrace(INT32 args)   {    struct thread_state *foo = THIS_THREAD;
1039:    }   }    + /*! @decl int status() +  */   void f_thread_id_status(INT32 args)   {    pop_n_elems(args);    push_int(THIS_THREAD->status);   }    -  + /*! @decl static string _sprintf(int c) +  *! +  *! Returns a string identifing the thread. +  */   void f_thread_id__sprintf (INT32 args)   {    pop_n_elems (args);
1054:    f_add (3);   }    + /*! @decl mixed result() +  *! +  *! Waits for the thread to complete, and then returns +  *! the value returned from the thread function. +  */   static void f_thread_id_result(INT32 args)   {    struct thread_state *th=THIS_THREAD;
1090:    th_destroy(& THIS_THREAD->id);   }    + /*! @end class +  */ +    static void thread_was_recursed(struct object *o)   {    struct thread_state *tmp=THIS_THREAD;
1124:   #endif   }    + /*! @class Local +  *! +  *! Thread local variable storage. +  *! +  *! This class allows you to have variables which are separate for each +  *! thread that uses it. It has two methods: @[get()] and @[set()]. A value +  *! stored in an instance of @[Thread.Local] can only be retrieved by that +  *! same thread. +  *! +  *! @note +  *! This class is simulated when Pike is compiled without thread support, +  *! so it's always available. +  */ +  + /* FIXME: Why not use an init-callback? */   PMOD_EXPORT void f_thread_local(INT32 args)   {    static INT32 thread_local_id = 0;
1134:    push_object(loc);   }    + /*! @decl mixed get() +  *! +  *! Get the thread local value. +  *! +  *! This returns the value prevoiusly stored in the @[Thread.Local] object by +  *! the @[set()] method by this thread. +  *! +  *! @seealso +  *! @[set()] +  */   void f_thread_local_get(INT32 args)   {    struct svalue key;
1151:    }   }    + /*! @decl mixed set(mixed value) +  *! +  *! Set the thread local value. +  *! +  *! This sets the value returned by the @[get] method. +  *! +  *! Calling this method does not affect the value returned by @[get()] when +  *! it's called by another thread (ie multiple values can be stored at the +  *! same time, but only one value per thread). +  *! +  *! @returns +  *! This function returns its argument. +  *! +  *! @note +  *! Note that the value set can only be retreived by the same thread. +  *! +  *! @seealso +  *! @[get()] +  */   void f_thread_local_set(INT32 args)   {    struct svalue key;
1173:    mapping_insert(m, &key, &Pike_sp[-1]);   }    + /*! @endclass +  */ +    /* Thread farm code by Per    *    */
1349:    START_NEW_PROGRAM_ID(THREAD_MUTEX_KEY);    mutex_key_offset = ADD_STORAGE(struct key_storage);    /* This is needed to allow the gc to find the possible circular reference. -  * It also allows a process to take over ownership of a key. +  * It also allows a thread to take over ownership of a key.    */    map_variable("_owner", "object", 0,    mutex_key_offset + OFFSETOF(key_storage, owner), T_OBJECT);