ecl/examples/threads/import_win32/import.c
Daniel Kochmanski 768eb27079 Remove "copyright" from examples/
Examples were relicensed (under permission from JJGR) to BSD-2-Clause a few
years back. We also remove Copyright from individual files to match the
convention that examples doesn't have that (whole codebase is under JJGR's
copyright too).
2018-08-10 07:36:02 +02:00

106 lines
3 KiB
C

/*
import.c -- Execute Lisp code from C-generated threads
*/
#include <stdlib.h>
#include <stdio.h>
#ifndef _MSC_VER
# include <unistd.h>
# include <pthread.h>
#endif
/*
* 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 <ecl.h> 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 <ecl.h>
#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(ECL_NIL, ECL_NIL);
/*
* 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 <gc.h>, 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 == NULL) {
printf("Unable to create thread. Code: %d\n", GetLastError());
exit(1);
}
}
/*
* Here we wait for the last thread to finish.
*/
sleep(10);
return 0;
}