00001 #include <string.h>
00002 #ifdef _WIN32
00003 #include <windows.h>
00004 #else
00005 #include <pthread.h>
00006 #endif
00007
00008 #include "data.h"
00009 #include "code.h"
00010
00011 static void lockDestroy(void* lock) { naFreeLock(lock); }
00012 static naGhostType LockType = { lockDestroy };
00013
00014 static void semDestroy(void* sem) { naFreeSem(sem); }
00015 static naGhostType SemType = { semDestroy };
00016
00017 typedef struct {
00018 naContext ctx;
00019 naRef func;
00020 } ThreadData;
00021
00022 #ifdef _WIN32
00023 static DWORD WINAPI threadtop(LPVOID param)
00024 #else
00025 static void* threadtop(void* param)
00026 #endif
00027 {
00028 ThreadData* td = param;
00029 naCall(td->ctx, td->func, 0, 0, naNil(), naNil());
00030 naFreeContext(td->ctx);
00031 naFree(td);
00032 return 0;
00033 }
00034
00035 static naRef f_newthread(naContext c, naRef me, int argc, naRef* args)
00036 {
00037 ThreadData *td;
00038 if(argc < 1 || !naIsFunc(args[0]))
00039 naRuntimeError(c, "bad/missing argument to newthread");
00040 td = naAlloc(sizeof(*td));
00041 td->ctx = naNewContext();
00042 td->func = args[0];
00043 naTempSave(td->ctx, td->func);
00044 #ifdef _WIN32
00045 CreateThread(0, 0, threadtop, td, 0, 0);
00046 #else
00047 {
00048 pthread_t t; int err;
00049 if((err = pthread_create(&t, 0, threadtop, td)))
00050 naRuntimeError(c, "newthread failed: %s", strerror(err));
00051 pthread_detach(t);
00052 }
00053 #endif
00054 return naNil();
00055 }
00056
00057 static naRef f_newlock(naContext c, naRef me, int argc, naRef* args)
00058 {
00059 return naNewGhost(c, &LockType, naNewLock());
00060 }
00061
00062 static naRef f_lock(naContext c, naRef me, int argc, naRef* args)
00063 {
00064 if(argc > 0 && naGhost_type(args[0]) == &LockType) {
00065 naModUnlock();
00066 naLock(naGhost_ptr(args[0]));
00067 naModLock();
00068 }
00069 return naNil();
00070 }
00071
00072 static naRef f_unlock(naContext c, naRef me, int argc, naRef* args)
00073 {
00074 if(argc > 0 && naGhost_type(args[0]) == &LockType)
00075 naUnlock(naGhost_ptr(args[0]));
00076 return naNil();
00077 }
00078
00079 static naRef f_newsem(naContext c, naRef me, int argc, naRef* args)
00080 {
00081 return naNewGhost(c, &SemType, naNewSem());
00082 }
00083
00084 static naRef f_semdown(naContext c, naRef me, int argc, naRef* args)
00085 {
00086 if(argc > 0 && naGhost_type(args[0]) == &SemType) {
00087 naModUnlock();
00088 naSemDown(naGhost_ptr(args[0]));
00089 naModLock();
00090 }
00091 return naNil();
00092 }
00093
00094 static naRef f_semup(naContext c, naRef me, int argc, naRef* args)
00095 {
00096 if(argc > 0 && naGhost_type(args[0]) == &SemType)
00097 naSemUp(naGhost_ptr(args[0]), 1);
00098 return naNil();
00099 }
00100
00101 static naCFuncItem funcs[] = {
00102 { "newthread", f_newthread },
00103 { "newlock", f_newlock },
00104 { "lock", f_lock },
00105 { "unlock", f_unlock },
00106 { "newsem", f_newsem },
00107 { "semdown", f_semdown },
00108 { "semup", f_semup },
00109 { 0 }
00110 };
00111
00112 naRef naInit_thread(naContext c)
00113 {
00114 return naGenLib(c, funcs);
00115 }