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:
parent
171422a94a
commit
df366c2615
4 changed files with 105 additions and 9 deletions
9
NEWS
9
NEWS
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue