From 796fd350bc0fb14c4b090480fbc12aad3330fc49 Mon Sep 17 00:00:00 2001 From: jjgarcia Date: Thu, 27 Oct 2005 18:12:38 +0000 Subject: [PATCH] New example on how to import threads to ECL. It's fragile, but hopefully we will add better examples in a near future --- examples/threads/import/Makefile | 6 ++ examples/threads/import/import.c | 109 +++++++++++++++++++++++ examples/threads/import_win32/Makefile | 2 + examples/threads/import_win32/import.c | 114 +++++++++++++++++++++++++ 4 files changed, 231 insertions(+) create mode 100644 examples/threads/import/Makefile create mode 100644 examples/threads/import/import.c create mode 100644 examples/threads/import_win32/Makefile create mode 100644 examples/threads/import_win32/import.c diff --git a/examples/threads/import/Makefile b/examples/threads/import/Makefile new file mode 100644 index 000000000..c131b6e07 --- /dev/null +++ b/examples/threads/import/Makefile @@ -0,0 +1,6 @@ +# +# Read the comments in import.c +# + +import.exe: import.c + gcc -g `ecl-config --cflags` import.c -o $@ `ecl-config --ldflags` diff --git a/examples/threads/import/import.c b/examples/threads/import/import.c new file mode 100644 index 000000000..8d5565014 --- /dev/null +++ b/examples/threads/import/import.c @@ -0,0 +1,109 @@ +/* + import.c -- Execute Lisp code from C-generated threads +*/ +/* + Copyright (c) 2005, Juan Jose Garcia Ripoll. + + ECL is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + See file '../Copyright' for full details. +*/ + +#include +#include +#include +#include + +/* + * GOAL: To execute lisp code from threads which have not + * been generated by our lisp environment. + * + * ASSUMES: ECL has been configured with threads (--enable-threads) + * and installed somewhere on the path. + * + * COMPILE: Run "make" from the command line. + * + * + * When this example is compiled and run, it generates a number of + * threads, each one executing some interpreted code -- in this case + * a bunch of PRINT statements. + * + * Importing other threads into lisp is possible if these threads have + * been intercepted by the garbage collector. The way to do it is to + * include the on the source code that generates the threads, + * as we do here. This takes care of replacing calls to phtread_create + * or CreateThread (in unix and Windows respectively) with the + * GC_pthread_create and GC_CreateThread functions. + */ + +#include + + +static void * +thread_entry_point(void *data) +{ + cl_object form; + + /* + * This is the entry point of the threads we have created. + * These threads have no valid lisp environment. The following + * routine initializes the lisp and makes it ready for working + * in this thread. + */ + + ecl_import_current_thread(Cnil, Cnil); + + /* + * Here we execute some lisp code code. + */ + cl_eval(form); + + /* + * Finally, when we exit the thread we have to release the + * resources allocated by the lisp environment. + */ + ecl_release_current_thread(); + + return NULL; +} + + +int main(int narg, char **argv) +{ + pthread_t child_thread; + int i, code; + + /* + * First of all, we have to initialize the ECL environment. + * This should be done from the main thread. + */ + cl_boot(narg, argv); + + /* + * Here we spawn 10 threads using the OS functions. The + * current version is for Unix and uses pthread_create. + * Since we have included , pthread_create will be + * replaced with the appropiate routine from the garbage + * collector. + */ + cl_object sym_print = c_string_to_object("PRINT"); + for (i = 0; i < 10; i++) { + cl_object form = cl_list(2, sym_print, MAKE_FIXNUM(i)); + code = pthread_create(&child_thread, NULL, thread_entry_point, + (void*)form); + if (code) { + printf("Unable to create thread\n"); + exit(1); + } + } + + /* + * Here we wait for the last thread to finish. + */ + pthread_join(child_thread, NULL); + + return 0; +} diff --git a/examples/threads/import_win32/Makefile b/examples/threads/import_win32/Makefile new file mode 100644 index 000000000..9b1c38b00 --- /dev/null +++ b/examples/threads/import_win32/Makefile @@ -0,0 +1,2 @@ +import.exe: import.c + gcc -g `ecl-config --cflags` import.c -o $@ `ecl-config --ldflags` diff --git a/examples/threads/import_win32/import.c b/examples/threads/import_win32/import.c new file mode 100644 index 000000000..e08289652 --- /dev/null +++ b/examples/threads/import_win32/import.c @@ -0,0 +1,114 @@ +/* + import.c -- Execute Lisp code from C-generated threads +*/ +/* + Copyright (c) 2005, Juan Jose Garcia Ripoll. + + ECL is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + See file '../Copyright' for full details. +*/ + +#include +#include +#include +#include + +/* + * GOAL: To execute lisp code from threads which have not + * been generated by our lisp environment. + * + * ASSUMES: ECL has been configured with threads (--enable-threads) + * and installed somewhere on the path. + * + * COMPILE: Run "make" from the command line. + * + * + * When this example is compiled and run, it generates a number of + * threads, each one executing some interpreted code -- in this case + * a bunch of PRINT statements. + * + * Importing other threads into lisp is possible if these threads have + * been intercepted by the garbage collector. The way to do it is to + * include the on the source code that generates the threads, + * as we do here. This takes care of replacing calls to phtread_create + * or CreateThread (in unix and Windows respectively) with the + * GC_pthread_create and GC_CreateThread functions. + */ + +#include + +#ifdef _MSC_VER +#define sleep(x) Sleep((x)*1000) +#endif + +static DWORD WINAPI +thread_entry_point(void *data) +{ + cl_object form = (cl_object)data; + + /* + * This is the entry point of the threads we have created. + * These threads have no valid lisp environment. The following + * routine initializes the lisp and makes it ready for working + * in this thread. + */ + + ecl_import_current_thread(Cnil, Cnil); + + /* + * Here we execute some lisp code code. + */ + cl_eval(form); + + /* + * Finally, when we exit the thread we have to release the + * resources allocated by the lisp environment. + */ + ecl_release_current_thread(); + + return 1; +} + + +int main(int narg, char **argv) +{ + HANDLE code; + DWORD child_thread; + int i; + cl_object sym_print; + + /* + * First of all, we have to initialize the ECL environment. + * This should be done from the main thread. + */ + cl_boot(narg, argv); + + /* + * Here we spawn 10 threads using the OS functions. The + * current version is for Unix and uses pthread_create. + * Since we have included , pthread_create will be + * replaced with the appropiate routine from the garbage + * collector. + */ + sym_print = c_string_to_object("PRINT"); + for (i = 0; i < 10; i++) { + cl_object form = cl_list(2, sym_print, MAKE_FIXNUM(i)); + code = (HANDLE)CreateThread(NULL, 0, thread_entry_point, form, 0, + &child_thread); + if (code) { + printf("Unable to create thread. Code: %d\n", code); + exit(1); + } + } + + /* + * Here we wait for the last thread to finish. + */ + sleep(10); + + return 0; +}