1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-04-30 03:40:34 +02:00

* coop-threads.c, threads.h (scm_spawn_thread): New function.

Can spawn a thread from application C code.
This commit is contained in:
Mikael Djurfeldt 1998-01-23 20:51:47 +00:00
parent 171422a94a
commit df366c2615
4 changed files with 105 additions and 9 deletions

9
NEWS
View file

@ -410,6 +410,15 @@ the stack to be saved automatically into the variable `the-last-stack'
use advanced error reporting, such as calling scm_display_error and use advanced error reporting, such as calling scm_display_error and
scm_display_backtrace. (They both take a stack object as argument.) scm_display_backtrace. (They both take a stack object as argument.)
** Function: SCM scm_spawn_thread (scm_catch_body_t body,
void *body_data,
scm_catch_handler_t handler,
void *handler_data)
Spawns a new thread. It does a job similar to
scm_call_with_new_thread but takes arguments more suitable when
spawning threads from application C code.
** The hook scm_error_callback has been removed. It was originally ** The hook scm_error_callback has been removed. It was originally
intended as a way for the user to install his own error handler. But intended as a way for the user to install his own error handler. But
that method works badly since it intervenes between throw and catch, that method works badly since it intervenes between throw and catch,

View file

@ -1,3 +1,8 @@
1998-01-23 Mikael Djurfeldt <mdj@mdj.nada.kth.se>
* coop-threads.c, threads.h (scm_spawn_thread): New function.
Can spawn a thread from application C code.
1998-01-20 Mikael Djurfeldt <mdj@mdj.nada.kth.se> 1998-01-20 Mikael Djurfeldt <mdj@mdj.nada.kth.se>
* gh.h, gh_data.c (gh_doubles2scm, gh_doubles2dvect, * gh.h, gh_data.c (gh_doubles2scm, gh_doubles2dvect,

View file

@ -204,14 +204,20 @@ scm_threads_mark_stacks ()
} }
} }
#ifdef __STDC__ /* NOTE: There are TWO mechanisms for starting a thread: The first one
void is used when spawning a thread from Scheme, while the second one is
launch_thread (void *p) used from C.
#else
void It might be argued that the first should be implemented in terms of
launch_thread (p) the second. The reason it isn't is that that would require an
void *p; extra unnecessary malloc (the thread_args structure). By providing
#endif one pair of extra functions (c_launch_thread, scm_spawn_thread) the
Scheme threads are started more efficiently. */
/* This is the first thread spawning mechanism: threads from Scheme */
static void
scheme_launch_thread (void *p)
{ {
/* The thread object will be GC protected by being a member of the /* The thread object will be GC protected by being a member of the
list given as argument to launch_thread. It will be marked list given as argument to launch_thread. It will be marked
@ -274,7 +280,7 @@ scm_call_with_new_thread (argl)
SCM_DEFER_INTS; SCM_DEFER_INTS;
SCM_SETCAR (thread, scm_tc16_thread); SCM_SETCAR (thread, scm_tc16_thread);
argl = scm_cons (thread, argl); argl = scm_cons (thread, argl);
t = coop_create (launch_thread, (void *) argl); t = coop_create (scheme_launch_thread, (void *) argl);
t->data = SCM_ROOT_STATE (root); t->data = SCM_ROOT_STATE (root);
SCM_SETCDR (thread, t); SCM_SETCDR (thread, t);
scm_thread_count++; scm_thread_count++;
@ -291,6 +297,79 @@ scm_call_with_new_thread (argl)
return thread; return thread;
} }
/* This is the second thread spawning mechanism: threads from C */
struct thread_args {
SCM thread;
scm_catch_body_t body;
void *body_data;
scm_catch_handler_t handler;
void *handler_data;
};
static void
c_launch_thread (void *p)
{
struct thread_args *args = (struct thread_args *) p;
/* The thread object will be GC protected by being on this stack */
SCM thread = args->thread;
/* We must use the address of `thread', otherwise the compiler will
optimize it away. This is OK since the longest SCM_STACKITEM
also is a long. */
scm_internal_cwdr (args->body,
args->body_data,
args->handler,
args->handler_data,
&thread);
scm_thread_count--;
scm_must_free ((char *) args);
}
SCM
scm_spawn_thread (scm_catch_body_t body, void *body_data,
scm_catch_handler_t handler, void *handler_data)
{
SCM thread;
coop_t *t;
SCM root, old_winds;
struct thread_args *args =
(struct thread_args *) scm_must_malloc (sizeof (*args),
"scm_spawn_thread");
/* Unwind wind chain. */
old_winds = scm_dynwinds;
scm_dowinds (SCM_EOL, scm_ilength (scm_root->dynwinds));
/* Allocate thread locals. */
root = scm_make_root (scm_root->handle);
/* Make thread. */
SCM_NEWCELL (thread);
SCM_DEFER_INTS;
SCM_SETCAR (thread, scm_tc16_thread);
args->thread = thread;
args->body = body;
args->body_data = body_data;
args->handler = handler;
args->handler_data = handler_data;
t = coop_create (c_launch_thread, (void *) args);
t->data = SCM_ROOT_STATE (root);
SCM_SETCDR (thread, t);
scm_thread_count++;
/* Note that the following statement also could cause coop_yield.*/
SCM_ALLOW_INTS;
/* We're now ready for the thread to begin. */
coop_yield();
/* Return to old dynamic context. */
scm_dowinds (old_winds, - scm_ilength (old_winds));
return thread;
}
#ifdef __STDC__ #ifdef __STDC__
SCM SCM
scm_join_thread (SCM t) scm_join_thread (SCM t)

View file

@ -73,6 +73,9 @@ SCM scm_threads_lock_mutex SCM_P ((SCM));
SCM scm_threads_unlock_mutex SCM_P ((SCM)); SCM scm_threads_unlock_mutex SCM_P ((SCM));
SCM scm_threads_monitor SCM_P ((void)); SCM scm_threads_monitor SCM_P ((void));
SCM scm_spawn_thread (scm_catch_body_t body, void *body_data,
scm_catch_handler_t handler, void *handler_data);
#if 0 #if 0
/* These don't work any more. */ /* These don't work any more. */
#ifdef USE_MIT_PTHREADS #ifdef USE_MIT_PTHREADS