mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2025-12-05 18:30:24 -08:00
116 lines
3.3 KiB
C
116 lines
3.3 KiB
C
/*
|
|
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 <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(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 <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;
|
|
}
|