diff --git a/moo/kernel/Class.moo b/moo/kernel/Class.moo index 6ca7426..af7ed93 100644 --- a/moo/kernel/Class.moo +++ b/moo/kernel/Class.moo @@ -4,7 +4,7 @@ ## class(#pointer) Class(Apex) { - dcl spec selfspec superclass subclasses name instvars classvars classinstvars pooldics instmthdic classmthdic. + dcl spec selfspec superclass subclasses name instvars classvars classinstvars pooldics instmthdic classmthdic nsdic. method(#class) basicNew { diff --git a/moo/kernel/Process.moo b/moo/kernel/Process.moo index 3224139..6776009 100644 --- a/moo/kernel/Process.moo +++ b/moo/kernel/Process.moo @@ -99,7 +99,7 @@ class(#pointer) Process(Object) class Semaphore(Object) { - dcl count waiting_head waiting_tail heapIndex fireTimeSec fireTimeNsec. + dcl count waiting_head waiting_tail heapIndex fireTimeSec fireTimeNsec ioIndex ioData ioMask. method(#class) forMutualExclusion { @@ -112,9 +112,14 @@ class Semaphore(Object) method initialize { self.count := 0. + self.heapIndex := -1. self.fireTimeSec := 0. self.fireTimeNsec := 0. + + self.ioIndex := -1. + self.ioData := nil. + self.ioMask := 0. } ## ================================================================== diff --git a/moo/lib/Makefile.am b/moo/lib/Makefile.am index bb3d63b..8ec00fb 100644 --- a/moo/lib/Makefile.am +++ b/moo/lib/Makefile.am @@ -79,7 +79,7 @@ bin_PROGRAMS = moo moo_SOURCES = main.c moo_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) moo_LDFLAGS = $(LDFLAGS_LIB_COMMON) -moo_LDADD = $(LIBADD_LIB_COMMON) -lmoo +moo_LDADD = $(LIBADD_LIB_COMMON) -lmoo -lxcb install-data-hook: diff --git a/moo/lib/Makefile.in b/moo/lib/Makefile.in index f0bd061..a9f7940 100644 --- a/moo/lib/Makefile.in +++ b/moo/lib/Makefile.in @@ -453,7 +453,7 @@ libmoo_la_LIBADD = $(LIBADD_LIB_COMMON) $(am__append_5) moo_SOURCES = main.c moo_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) moo_LDFLAGS = $(LDFLAGS_LIB_COMMON) -moo_LDADD = $(LIBADD_LIB_COMMON) -lmoo +moo_LDADD = $(LIBADD_LIB_COMMON) -lmoo -lxcb all: moo-cfg.h $(MAKE) $(AM_MAKEFLAGS) all-am diff --git a/moo/lib/comp.c b/moo/lib/comp.c index 44100de..390ec2e 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -287,7 +287,13 @@ static int is_reserved_word (const moo_oocs_t* ucs) VOCA_ERROR, VOCA_THIS_CONTEXT, VOCA_THIS_PROCESS, - VOCA_IF + VOCA_IF, + VOCA_ELSE, + VOCA_ELSIF, + VOCA_WHILE, + VOCA_DO, + VOCA_BREAK, + VOCA_CONTINUE }; int i; @@ -2737,6 +2743,34 @@ oops: return MOO_NULL; } +static moo_oop_set_t add_nsdic_to_class (moo_t* moo, moo_oop_class_t c, const moo_oocs_t* name) +{ + moo_oow_t tmp_count = 0; + moo_oop_t sym; + moo_oop_set_t ns; + + moo_pushtmp (moo, (moo_oop_t*)&c); tmp_count++; + + sym = moo_makesymbol (moo, name->ptr, name->len); + if (!sym) goto oops; + + moo_pushtmp (moo, &sym); tmp_count++; + + ns = moo_makedic (moo, moo->_namespace, NAMESPACE_SIZE); + if (!ns) goto oops; + + /*moo_pushtmp (moo, &ns); tmp_count++;*/ + + c->nsdic = ns; + + moo_poptmps (moo, tmp_count); + return ns; + +oops: + moo_poptmps (moo, tmp_count); + return MOO_NULL; +} + static int preprocess_dotted_name (moo_t* moo, int dont_add_ns, int accept_pooldic_as_ns, const moo_oocs_t* fqn, const moo_ioloc_t* fqn_loc, moo_oocs_t* name, moo_oop_set_t* ns_oop) { const moo_ooch_t* ptr, * dot; @@ -2769,9 +2803,33 @@ static int preprocess_dotted_name (moo_t* moo, int dont_add_ns, int accept_poold if (MOO_CLASSOF(moo, ass->value) == moo->_namespace || (seg.ptr == fqn->ptr && ass->value == (moo_oop_t)moo->sysdic)) { - /* ok */ + /* ok - the current segment is a namespace name or + * it is the first segment and is System */ dic = (moo_oop_set_t)ass->value; } + else if (MOO_CLASSOF(moo, ass->value) == moo->_class) + { + /* the segment is a class name. use the nsdic field. + * class X {} + * class X.Y {} + * when processing X in X.Y, this part is reached. */ + dic = ((moo_oop_class_t)ass->value)->nsdic; + if ((moo_oop_t)dic == moo->_nil) + { + /* the nsdic field is still nil. no namespace dictionary + * has been attached to the class */ + moo_oop_set_t t; + + if (dont_add_ns) goto wrong_name; + + /* attach a new namespace dictionary to the nsdic field + * of the class */ + t = add_nsdic_to_class (moo, (moo_oop_class_t)ass->value, &seg); + if (!t) return -1; + + dic = t; + } + } else { if (accept_pooldic_as_ns && MOO_CLASSOF(moo, ass->value) == moo->_pool_dictionary) diff --git a/moo/lib/exec.c b/moo/lib/exec.c index 90143c9..f250126 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -32,10 +32,14 @@ #define PROC_STATE_SUSPENDED 0 #define PROC_STATE_TERMINATED -1 +/* TODO: adjust these max semaphore pointer buffer capacity, + * proably depending on the object memory size? */ #define SEM_LIST_INC 256 #define SEM_HEAP_INC 256 +#define SEM_IO_INC 256 #define SEM_LIST_MAX (SEM_LIST_INC * 1000) #define SEM_HEAP_MAX (SEM_HEAP_INC * 1000) +#define SEM_IO_MAX (SEM_IO_INC * 1000) #define SEM_HEAP_PARENT(x) (((x) - 1) / 2) #define SEM_HEAP_LEFT(x) ((x) * 2 + 1) @@ -59,8 +63,7 @@ #define STORE_ACTIVE_SP(moo) STORE_SP(moo, (moo)->processor->active) #define SWITCH_ACTIVE_CONTEXT(moo,v_ctx) \ - do \ - { \ + do { \ STORE_ACTIVE_IP (moo); \ (moo)->active_context = (v_ctx); \ (moo)->active_method = (moo_oop_method_t)(moo)->active_context->origin->method_or_nargs; \ @@ -105,12 +108,27 @@ #endif /* ------------------------------------------------------------------------- */ +static MOO_INLINE int vm_startup (moo_t* moo) +{ + if (moo->vmprim.vm_startup (moo) <= -1) return -1; + moo->vmprim.vm_gettime (moo, &moo->exec_start_time); /* raw time. no adjustment */ + return 0; +} + +static MOO_INLINE void vm_cleanup (moo_t* moo) +{ + moo->vmprim.vm_gettime (moo, &moo->exec_end_time); /* raw time. no adjustment */ + moo->vmprim.vm_cleanup (moo); +} + static MOO_INLINE void vm_gettime (moo_t* moo, moo_ntime_t* now) { moo->vmprim.vm_gettime (moo, now); /* in vm_startup(), moo->exec_start_time has been set to the time of - * that moment. time returned here becomes relative to moo->exec_start_time - * and is kept small such that it can get reprensed in a small integer */ + * that moment. time returned here get offset by moo->exec_start_time and + * thus becomes relative to it. this way, it is kept small such that it + * can be represented in a small integer with leaving almost zero chance + * of overflow. */ MOO_SUBNTIME (now, now, &moo->exec_start_time); /* now = now - exec_start_time */ } @@ -119,16 +137,9 @@ static MOO_INLINE void vm_sleep (moo_t* moo, const moo_ntime_t* dur) moo->vmprim.vm_sleep (moo, dur); } -static MOO_INLINE void vm_startup (moo_t* moo) +static MOO_INLINE void vm_mux_wait (moo_t* moo, const moo_ntime_t* dur) { - moo->vmprim.vm_startup (moo); - moo->vmprim.vm_gettime (moo, &moo->exec_start_time); -} - -static MOO_INLINE void vm_cleanup (moo_t* moo) -{ - vm_gettime (moo, &moo->exec_end_time); - moo->vmprim.vm_cleanup (moo); + moo->vmprim.mux_wait (moo, dur); } /* ------------------------------------------------------------------------- */ @@ -539,10 +550,12 @@ static moo_oop_process_t signal_semaphore (moo_t* moo, moo_oop_semaphore_t sem) /* [NOTE] no GC must occur as 'proc' isn't protected with moo_pushtmp(). */ + /* detach a process from a semaphore waiting list and + * make it runnable */ unchain_from_semaphore (moo, proc); resume_process (moo, proc); /* TODO: error check */ - /* return the resumed process */ + /* return the resumed(runnable) process */ return proc; } } @@ -706,6 +719,8 @@ static void delete_from_sem_heap (moo_t* moo, moo_ooi_t index) } } +#if 0 +/* unused */ static void update_sem_heap (moo_t* moo, moo_ooi_t index, moo_oop_semaphore_t newsem) { moo_oop_semaphore_t sem; @@ -721,6 +736,67 @@ static void update_sem_heap (moo_t* moo, moo_ooi_t index, moo_oop_semaphore_t ne else sift_down_sem_heap (moo, index); } +#endif + +static int add_to_sem_io (moo_t* moo, moo_oop_semaphore_t sem) +{ + moo_ooi_t index; + + if (moo->sem_io_count >= SEM_IO_MAX) + { + moo->errnum = MOO_ESHFULL; + return -1; + } + + if (moo->sem_io_count >= moo->sem_io_capa) + { + moo_oow_t new_capa; + moo_oop_semaphore_t* tmp; + + /* no overflow check when calculating the new capacity + * owing to SEM_IO_MAX check above */ + new_capa = moo->sem_io_capa + SEM_IO_INC; + tmp = moo_reallocmem (moo, moo->sem_io, MOO_SIZEOF(moo_oop_semaphore_t) * new_capa); + if (!tmp) return -1; + + moo->sem_io = tmp; + moo->sem_io_capa = new_capa; + } + + MOO_ASSERT (moo, moo->sem_io_count <= MOO_SMOOI_MAX); + + if (moo->vmprim.mux_add (moo) <= -1) /*TODO: pass data */ + { + return -1; + } + + index = moo->sem_io_count; + moo->sem_io[index] = sem; + sem->heap_index = MOO_SMOOI_TO_OOP(index); + moo->sem_io_count++; + + return 0; +} + +static void delete_from_sem_io (moo_t* moo, moo_ooi_t index) +{ + + moo_oop_semaphore_t sem, lastsem; + + sem = moo->sem_io[index]; + sem->io_index = MOO_SMOOI_TO_OOP(-1); + + moo->vmprim.mux_del (moo); /* TODO: pass data... */ + + moo->sem_io_count--; + if (moo->sem_io_count > 0 && index != moo->sem_io_count) + { + /* move the last item to the deletion position */ + lastsem = moo->sem_io[moo->sem_io_count]; + lastsem->io_index = MOO_SMOOI_TO_OOP(index); + moo->sem_io[index] = lastsem; + } +} static moo_oop_process_t start_initial_process (moo_t* moo, moo_oop_context_t c) { @@ -1984,13 +2060,15 @@ static moo_pfrc_t pf_processor_add_timed_semaphore (moo_t* moo, moo_ooi_t nargs) sem = (moo_oop_semaphore_t)MOO_STACK_GETARG(moo, nargs, 0); rcv = MOO_STACK_GETRCV(moo, nargs); - if (rcv != (moo_oop_t)moo->processor) return MOO_PF_FAILURE; - if (MOO_CLASSOF(moo,sem) != moo->_semaphore) return MOO_PF_FAILURE; - if (!MOO_OOP_IS_SMOOI(sec)) return MOO_PF_FAILURE; + /* ProcessScheduler>>signal:after: calls this primitive function. */ + if (rcv != (moo_oop_t)moo->processor || + MOO_CLASSOF(moo,sem) != moo->_semaphore || + !MOO_OOP_IS_SMOOI(sec)) return MOO_PF_FAILURE; if (MOO_OOP_IS_SMOOI(sem->heap_index) && sem->heap_index != MOO_SMOOI_TO_OOP(-1)) { + /* if the semaphore is already been added. remove it first */ delete_from_sem_heap (moo, MOO_OOP_TO_SMOOI(sem->heap_index)); MOO_ASSERT (moo, sem->heap_index == MOO_SMOOI_TO_OOP(-1)); @@ -2002,7 +2080,7 @@ static moo_pfrc_t pf_processor_add_timed_semaphore (moo_t* moo, moo_ooi_t nargs) } /* this code assumes that the monotonic clock returns a small value - * that can fit into a SmallInteger, even after some additions... */ + * that can fit into a SmallInteger, even after some additions. */ vm_gettime (moo, &now); MOO_ADDNTIMESNS (&ft, &now, MOO_OOP_TO_SMOOI(sec), MOO_OOP_TO_SMOOI(nsec)); if (ft.sec < 0 || ft.sec > MOO_SMOOI_MAX) @@ -2024,6 +2102,42 @@ static moo_pfrc_t pf_processor_add_timed_semaphore (moo_t* moo, moo_ooi_t nargs) return MOO_PF_SUCCESS; } +static moo_pfrc_t pf_processor_add_io_semaphore (moo_t* moo, moo_ooi_t nargs) +{ + moo_oop_t rcv, sec, nsec; + moo_oop_semaphore_t sem; + + MOO_ASSERT (moo, nargs == 3); + + nsec = MOO_STACK_GETARG (moo, nargs, 2); + if (!MOO_OOP_IS_SMOOI(nsec)) return MOO_PF_FAILURE; + + sec = MOO_STACK_GETARG(moo, nargs, 1); + sem = (moo_oop_semaphore_t)MOO_STACK_GETARG(moo, nargs, 0); + rcv = MOO_STACK_GETRCV(moo, nargs); + + /* ProcessScheduler>>signal:after: calls this primitive function. */ + if (rcv != (moo_oop_t)moo->processor || + MOO_CLASSOF(moo,sem) != moo->_semaphore || + !MOO_OOP_IS_SMOOI(sec)) return MOO_PF_FAILURE; + + if (MOO_OOP_IS_SMOOI(sem->io_index) && + sem->io_index != MOO_SMOOI_TO_OOP(-1)) + { + /* remove it if it's already added for IO */ + delete_from_sem_io (moo, MOO_OOP_TO_SMOOI(sem->io_index)); + MOO_ASSERT (moo, sem->io_index == MOO_SMOOI_TO_OOP(-1)); + } + +/* TOOD: sanity check on argument 2 and 3 */ + sem->io_data = MOO_STACK_GETARG(moo, nargs, 1); + sem->io_mask = MOO_STACK_GETARG(moo, nargs, 2); + if (add_to_sem_io (moo, sem) <= -1) return MOO_PF_HARD_FAILURE; + + MOO_STACK_SETRETTORCV (moo, nargs); /* ^self */ + return MOO_PF_SUCCESS; +} + static moo_pfrc_t pf_processor_remove_semaphore (moo_t* moo, moo_ooi_t nargs) { /* remove a semaphore from processor's signal scheduling */ @@ -2050,6 +2164,13 @@ static moo_pfrc_t pf_processor_remove_semaphore (moo_t* moo, moo_ooi_t nargs) MOO_ASSERT (moo, sem->heap_index == MOO_SMOOI_TO_OOP(-1)); } + if (MOO_OOP_IS_SMOOI(sem->io_index) && + sem->io_index != MOO_SMOOI_TO_OOP(-1)) + { + delete_from_sem_io (moo, MOO_OOP_TO_SMOOI(sem->heap_index)); + MOO_ASSERT (moo, sem->io_index == MOO_SMOOI_TO_OOP(-1)); + } + MOO_STACK_SETRETTORCV (moo, nargs); /* ^self */ return MOO_PF_SUCCESS; } @@ -2564,6 +2685,7 @@ static pf_t pftab[] = { 1, 1, pf_processor_schedule, "_processor_schedule" }, { 2, 3, pf_processor_add_timed_semaphore, "_processor_add_timed_semaphore" }, + { 3, 3, pf_processor_add_io_semaphore, "_processor_add_io_semaphore" }, { 1, 1, pf_processor_remove_semaphore, "_processor_remove_semaphore" }, { 2, 2, pf_processor_return_to, "_processor_return_to" }, @@ -2918,7 +3040,9 @@ static MOO_INLINE int switch_process_if_needed (moo_t* moo) { if (moo->sem_heap_count > 0) { + /* handle timed semaphores */ moo_ntime_t ft, now; + vm_gettime (moo, &now); do @@ -2956,24 +3080,32 @@ static MOO_INLINE int switch_process_if_needed (moo_t* moo) MOO_ASSERT (moo, proc->state == MOO_SMOOI_TO_OOP(PROC_STATE_RUNNABLE)); MOO_ASSERT (moo, proc == moo->processor->runnable_head); - wake_new_process (moo, proc); + wake_new_process (moo, proc); /* switch to running */ moo->proc_switched = 1; } } else if (moo->processor->active == moo->nil_process) { + /* no running process */ MOO_SUBNTIME (&ft, &ft, (moo_ntime_t*)&now); - vm_sleep (moo, &ft); /* TODO: change this to i/o multiplexer??? */ + + if (moo->sem_io_count > 0) + vm_mux_wait (moo, &ft); + else + vm_sleep (moo, &ft); /* TODO: change this to i/o multiplexer??? */ vm_gettime (moo, &now); } else { + /* there is a running process. go on */ break; } } - while (moo->sem_heap_count > 0); + while (moo->sem_heap_count > 0 && !moo->abort_req); } + if (moo->sem_io_count > 0) vm_mux_wait (moo, MOO_NULL); + if (moo->processor->active == moo->nil_process) { /* no more waiting semaphore and no more process */ @@ -3034,11 +3166,13 @@ int moo_execute (moo_t* moo) MOO_ASSERT (moo, moo->active_context != MOO_NULL); - vm_startup (moo); + if (vm_startup(moo) <= -1) goto oops; vm_startup_called = 1; - moo->proc_switched = 0; - while (1) + moo->proc_switched = 0; + moo->abort_req = 0; + + while (!moo->abort_req) { if (switch_process_if_needed(moo) == 0) break; /* no more runnable process */ @@ -4157,7 +4291,6 @@ int moo_execute (moo_t* moo) } done: - vm_cleanup (moo); #if defined(MOO_PROFILE_VM) MOO_LOG1 (moo, MOO_LOG_IC | MOO_LOG_INFO, "TOTAL_INST_COUTNER = %zu\n", inst_counter); @@ -4169,6 +4302,11 @@ oops: return -1; } +int moo_abort (moo_t* moo) +{ + moo->abort_req = 1; +} + int moo_invoke (moo_t* moo, const moo_oocs_t* objname, const moo_oocs_t* mthname) { int n; diff --git a/moo/lib/gc.c b/moo/lib/gc.c index 5243e18..95ae67f 100644 --- a/moo/lib/gc.c +++ b/moo/lib/gc.c @@ -626,6 +626,11 @@ void moo_gc (moo_t* moo) moo->sem_heap[i] = (moo_oop_semaphore_t)moo_moveoop (moo, (moo_oop_t)moo->sem_heap[i]); } + for (i = 0; i < moo->sem_io_count; i++) + { + moo->sem_io[i] = (moo_oop_semaphore_t)moo_moveoop (moo, (moo_oop_t)moo->sem_io[i]); + } + for (i = 0; i < moo->tmp_count; i++) { *moo->tmp_stack[i] = moo_moveoop (moo, *moo->tmp_stack[i]); diff --git a/moo/lib/main.c b/moo/lib/main.c index a3b6187..a6bbbe3 100644 --- a/moo/lib/main.c +++ b/moo/lib/main.c @@ -75,6 +75,8 @@ # if defined(HAVE_SIGNAL_H) # include # endif + +# include #endif #if !defined(MOO_DEFAULT_PFMODPREFIX) @@ -118,6 +120,8 @@ struct xtn_t const char* source_path; /* main source file */ #if defined(_WIN32) HANDLE waitable_timer; +#else + int ep; /* epoll */ #endif }; @@ -616,6 +620,56 @@ if (mask & MOO_LOG_GC) return; /* don't show gc logs */ /* ========================================================================= */ +static int vm_startup (moo_t* moo) +{ +#if defined(_WIN32) + xtn_t* xtn = (xtn_t*)moo_getxtn(moo); + xtn->waitable_timer = CreateWaitableTimer(MOO_NULL, TRUE, MOO_NULL); + +#else + xtn_t* xtn = (xtn_t*)moo_getxtn(moo); + + xtn->ep = epoll_create1 (EPOLL_CLOEXEC); + if (xtn->ep == -1) + { + MOO_DEBUG0 (moo, "Cannot create epoll\n"); + moo_syserrtoerrnum (errno); + goto oops; + } + + return 0; + +oops: + if (xtn->ep >= 0) + { + close (xtn->ep); + xtn->ep = -1; + } + + return -1; +#endif +} + +static void vm_cleanup (moo_t* moo) +{ +#if defined(_WIN32) + xtn_t* xtn = (xtn_t*)moo_getxtn(moo); + if (xtn->waitable_timer) + { + CloseHandle (xtn->waitable_timer); + xtn->waitable_timer = MOO_NULL; + } +#else + xtn_t* xtn = (xtn_t*)moo_getxtn(moo); + + if (xtn->ep) + { + close (xtn->ep); + xtn->ep = -1; + } +#endif +} + static void vm_gettime (moo_t* moo, moo_ntime_t* now) { #if defined(_WIN32) @@ -729,6 +783,7 @@ static void vm_sleep (moo_t* moo, const moo_ntime_t* dur) } #else + struct timespec ts; ts.tv_sec = dur->sec; ts.tv_nsec = dur->nsec; @@ -736,26 +791,43 @@ static void vm_sleep (moo_t* moo, const moo_ntime_t* dur) #endif } -static void vm_startup (moo_t* moo) +static int mux_add (moo_t* moo) { -#if defined(_WIN32) xtn_t* xtn = (xtn_t*)moo_getxtn(moo); - xtn->waitable_timer = CreateWaitableTimer(MOO_NULL, TRUE, MOO_NULL); -#endif -} + struct epoll_event ev; -static void vm_cleanup (moo_t* moo) -{ -#if defined(_WIN32) - xtn_t* xtn = (xtn_t*)moo_getxtn(moo); - if (xtn->waitable_timer) + ev.events = EPOLLIN | EPOLLOUT; + ev.data.u64 = 10; + +/* + if (epoll_ctl (xtn->ep, EPOLL_CTL_DEL, 000, &ev) == -1) { - CloseHandle (xtn->waitable_timer); - xtn->waitable_timer = MOO_NULL; + moo_syserrtoerrnum (errno); + return -1; } -#endif +*/ + return 0; } +static void mux_del (moo_t* moo) +{ + xtn_t* xtn = (xtn_t*)moo_getxtn(moo); + struct epoll_event ev; +/* epoll_ctl (xtn->ep, EPOLL_CTL_DEL, 00, &ev);*/ +} + +static void mux_wait (moo_t* moo, const moo_ntime_t* dur) +{ + xtn_t* xtn = (xtn_t*)moo_getxtn(moo); + int tmout = 0; + + if (dur) tmout = MOO_SECNSEC_TO_MSEC(dur->sec, dur->nsec); +/* + if (epoll_wait (xtn->ep, xtn->evt_ptr, xtn->evt_capa, tmout) > 0) + { + } +*/ +} /* ========================================================================= */ static moo_t* g_moo = MOO_NULL; @@ -902,10 +974,14 @@ int main (int argc, char* argv[]) vmprim.dl_close = dl_close; vmprim.dl_getsym = dl_getsym; vmprim.log_write = log_write; - vmprim.vm_gettime = vm_gettime; - vmprim.vm_sleep = vm_sleep; + vmprim.vm_startup = vm_startup; vmprim.vm_cleanup = vm_cleanup; + vmprim.vm_gettime = vm_gettime; + vmprim.vm_sleep = vm_sleep; + vmprim.mux_add = mux_add; + vmprim.mux_del = mux_del; + vmprim.mux_wait = mux_wait; #if defined(USE_LTDL) lt_dlinit (); diff --git a/moo/lib/moo.c b/moo/lib/moo.c index 4de6315..1ba1193 100644 --- a/moo/lib/moo.c +++ b/moo/lib/moo.c @@ -157,6 +157,13 @@ void moo_fini (moo_t* moo) moo->sem_heap_count = 0; } + if (moo->sem_io) + { + moo_freemem (moo, moo->sem_io); + moo->sem_io_capa = 0; + moo->sem_io_count = 0; + } + for (cb = moo->cblist; cb; cb = cb->next) { if (cb->fini) cb->fini (moo); diff --git a/moo/lib/moo.h b/moo/lib/moo.h index 8283edc..c989a46 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -442,7 +442,7 @@ struct moo_set_t moo_oop_oop_t bucket; /* Array */ }; -#define MOO_CLASS_NAMED_INSTVARS 11 +#define MOO_CLASS_NAMED_INSTVARS 12 typedef struct moo_class_t moo_class_t; typedef struct moo_class_t* moo_oop_class_t; struct moo_class_t @@ -469,6 +469,9 @@ struct moo_class_t * [1] - class methods, MethodDictionary */ moo_oop_set_t mthdic[MOO_METHOD_TYPE_COUNT]; + /* dictionary used for namespacing */ + moo_oop_set_t nsdic; + /* indexed part afterwards */ moo_oop_t slot[1]; /* class instance variables and class variables. */ }; @@ -648,7 +651,7 @@ struct moo_context_t typedef struct moo_process_t moo_process_t; typedef struct moo_process_t* moo_oop_process_t; -#define MOO_SEMAPHORE_NAMED_INSTVARS 6 +#define MOO_SEMAPHORE_NAMED_INSTVARS 9 typedef struct moo_semaphore_t moo_semaphore_t; typedef struct moo_semaphore_t* moo_oop_semaphore_t; @@ -673,12 +676,18 @@ struct moo_process_t struct moo_semaphore_t { MOO_OBJ_HEADER; + moo_oop_t count; /* SmallInteger */ moo_oop_process_t waiting_head; moo_oop_process_t waiting_tail; + moo_oop_t heap_index; /* index to the heap */ moo_oop_t heap_ftime_sec; /* firing time */ moo_oop_t heap_ftime_nsec; /* firing time */ + + moo_oop_t io_index; + moo_oop_t io_data; + moo_oop_t io_mask; /* SmallInteger */ }; #define MOO_PROCESS_SCHEDULER_NAMED_INSTVARS 5 @@ -733,28 +742,36 @@ enum moo_vmprim_opendl_flag_t }; typedef enum moo_vmprim_opendl_flag_t moo_vmprim_opendl_flag_t; -typedef void* (*moo_vmprim_opendl_t) (moo_t* moo, const moo_ooch_t* name, int flags); -typedef void (*moo_vmprim_closedl_t) (moo_t* moo, void* handle); -typedef void* (*moo_vmprim_getdlsym_t) (moo_t* moo, void* handle, const moo_ooch_t* name); +typedef void* (*moo_vmprim_dlopen_t) (moo_t* moo, const moo_ooch_t* name, int flags); +typedef void (*moo_vmprim_dlclose_t) (moo_t* moo, void* handle); +typedef void* (*moo_vmprim_dlsym_t) (moo_t* moo, void* handle, const moo_ooch_t* name); typedef void (*moo_log_write_t) (moo_t* moo, moo_oow_t mask, const moo_ooch_t* msg, moo_oow_t len); -typedef void (*moo_vmprim_sleep_t) (moo_t* moo, const moo_ntime_t* duration); -typedef void (*moo_vmprim_gettime_t) (moo_t* moo, moo_ntime_t* now); -typedef void (*moo_vmprim_startup_t) (moo_t* moo); +typedef int (*moo_vmprim_startup_t) (moo_t* moo); typedef void (*moo_vmprim_cleanup_t) (moo_t* moo); +typedef void (*moo_vmprim_gettime_t) (moo_t* moo, moo_ntime_t* now); +typedef void (*moo_vmprim_sleep_t) (moo_t* moo, const moo_ntime_t* duration); + +typedef int (*moo_vmprim_muxadd_t) (moo_t* moo); +typedef void (*moo_vmprim_muxdel_t) (moo_t* moo); +typedef void (*moo_vmprim_muxwait_t) (moo_t* moo, const moo_ntime_t* duration); struct moo_vmprim_t { - moo_vmprim_opendl_t dl_open; - moo_vmprim_closedl_t dl_close; - moo_vmprim_getdlsym_t dl_getsym; + moo_vmprim_dlopen_t dl_open; + moo_vmprim_dlclose_t dl_close; + moo_vmprim_dlsym_t dl_getsym; moo_log_write_t log_write; - moo_vmprim_gettime_t vm_gettime; - moo_vmprim_sleep_t vm_sleep; - moo_vmprim_startup_t vm_startup; - moo_vmprim_cleanup_t vm_cleanup; + moo_vmprim_startup_t vm_startup; + moo_vmprim_cleanup_t vm_cleanup; + moo_vmprim_gettime_t vm_gettime; + moo_vmprim_sleep_t vm_sleep; + + moo_vmprim_muxadd_t mux_add; + moo_vmprim_muxdel_t mux_del; + moo_vmprim_muxwait_t mux_wait; }; typedef struct moo_vmprim_t moo_vmprim_t; @@ -958,11 +975,18 @@ struct moo_t moo_oow_t sem_list_count; moo_oow_t sem_list_capa; - /* semaphores sorted according to time-out */ + /* semaphores sorted according to time-out. + * organize entries using heap as the earliest entry + * needs to be checked first */ moo_oop_semaphore_t* sem_heap; moo_oow_t sem_heap_count; moo_oow_t sem_heap_capa; + /* semaphores for I/O handling. plain array */ + moo_oop_semaphore_t* sem_io; + moo_oow_t sem_io_count; + moo_oow_t sem_io_capa; + moo_oop_t* tmp_stack[256]; /* stack for temporaries */ moo_oow_t tmp_count; @@ -977,6 +1001,7 @@ struct moo_t moo_ooi_t ip; int proc_switched; /* TODO: this is temporary. implement something else to skip immediate context switching */ int switch_proc; + int abort_req; moo_ntime_t exec_start_time; moo_ntime_t exec_end_time; /* ============================================================= diff --git a/moo/mod/Makefile.am b/moo/mod/Makefile.am index b47796c..4e405f9 100644 --- a/moo/mod/Makefile.am +++ b/moo/mod/Makefile.am @@ -34,7 +34,7 @@ LDFLAGS_COMMON = -L$(abs_builddir)/../lib -L$(libdir) -version-info 1:0:0 -no-un LIBADD_COMMON = -lmoo pkgmodexecdir = $(libdir) -pkgmodexec_LTLIBRARIES = libmoo-console.la libmoo-ffi.la libmoo-stdio.la +pkgmodexec_LTLIBRARIES = libmoo-console.la libmoo-ffi.la libmoo-stdio.la libmoo-x11.la endif @@ -53,3 +53,7 @@ libmoo_stdio_la_CPPFLAGS = $(CPPFLAGS_COMMON) libmoo_stdio_la_LDFLAGS = $(LDFLAGS_COMMON) libmoo_stdio_la_LIBADD = $(LIBADD_COMMON) +libmoo_x11_la_SOURCES = x11.c _x11.h +libmoo_x11_la_CPPFLAGS = $(CPPFLAGS_COMMON) +libmoo_x11_la_LDFLAGS = $(LDFLAGS_COMMON) +libmoo_x11_la_LIBADD = $(LIBADD_COMMON) -lxcb diff --git a/moo/mod/Makefile.in b/moo/mod/Makefile.in index 8dc4687..8f62e4e 100644 --- a/moo/mod/Makefile.in +++ b/moo/mod/Makefile.in @@ -172,6 +172,14 @@ libmoo_stdio_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ @ENABLE_STATIC_MODULE_FALSE@am_libmoo_stdio_la_rpath = -rpath \ @ENABLE_STATIC_MODULE_FALSE@ $(pkgmodexecdir) @ENABLE_STATIC_MODULE_TRUE@am_libmoo_stdio_la_rpath = +libmoo_x11_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_libmoo_x11_la_OBJECTS = libmoo_x11_la-x11.lo +libmoo_x11_la_OBJECTS = $(am_libmoo_x11_la_OBJECTS) +libmoo_x11_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libmoo_x11_la_LDFLAGS) $(LDFLAGS) -o $@ +@ENABLE_STATIC_MODULE_FALSE@am_libmoo_x11_la_rpath = -rpath \ +@ENABLE_STATIC_MODULE_FALSE@ $(pkgmodexecdir) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false @@ -207,9 +215,9 @@ am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libmoo_console_la_SOURCES) $(libmoo_ffi_la_SOURCES) \ - $(libmoo_stdio_la_SOURCES) + $(libmoo_stdio_la_SOURCES) $(libmoo_x11_la_SOURCES) DIST_SOURCES = $(libmoo_console_la_SOURCES) $(libmoo_ffi_la_SOURCES) \ - $(libmoo_stdio_la_SOURCES) + $(libmoo_stdio_la_SOURCES) $(libmoo_x11_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -415,7 +423,7 @@ CPPFLAGS_COMMON = -I$(abs_builddir) -I$(abs_builddir)/../lib \ @ENABLE_STATIC_MODULE_TRUE@LIBADD_COMMON = @ENABLE_STATIC_MODULE_TRUE@noinst_LTLIBRARIES = libmoo-console.la libmoo-ffi.la libmoo-stdio.la @ENABLE_STATIC_MODULE_FALSE@pkgmodexecdir = $(libdir) -@ENABLE_STATIC_MODULE_FALSE@pkgmodexec_LTLIBRARIES = libmoo-console.la libmoo-ffi.la libmoo-stdio.la +@ENABLE_STATIC_MODULE_FALSE@pkgmodexec_LTLIBRARIES = libmoo-console.la libmoo-ffi.la libmoo-stdio.la libmoo-x11.la libmoo_console_la_SOURCES = console.c console.h libmoo_console_la_CPPFLAGS = $(CPPFLAGS_COMMON) libmoo_console_la_LDFLAGS = $(LDFLAGS_COMMON) @@ -428,6 +436,10 @@ libmoo_stdio_la_SOURCES = stdio.c _stdio.h libmoo_stdio_la_CPPFLAGS = $(CPPFLAGS_COMMON) libmoo_stdio_la_LDFLAGS = $(LDFLAGS_COMMON) libmoo_stdio_la_LIBADD = $(LIBADD_COMMON) +libmoo_x11_la_SOURCES = x11.c _x11.h +libmoo_x11_la_CPPFLAGS = $(CPPFLAGS_COMMON) +libmoo_x11_la_LDFLAGS = $(LDFLAGS_COMMON) +libmoo_x11_la_LIBADD = $(LIBADD_COMMON) -lxcb all: all-am .SUFFIXES: @@ -517,6 +529,9 @@ libmoo-ffi.la: $(libmoo_ffi_la_OBJECTS) $(libmoo_ffi_la_DEPENDENCIES) $(EXTRA_li libmoo-stdio.la: $(libmoo_stdio_la_OBJECTS) $(libmoo_stdio_la_DEPENDENCIES) $(EXTRA_libmoo_stdio_la_DEPENDENCIES) $(AM_V_CCLD)$(libmoo_stdio_la_LINK) $(am_libmoo_stdio_la_rpath) $(libmoo_stdio_la_OBJECTS) $(libmoo_stdio_la_LIBADD) $(LIBS) +libmoo-x11.la: $(libmoo_x11_la_OBJECTS) $(libmoo_x11_la_DEPENDENCIES) $(EXTRA_libmoo_x11_la_DEPENDENCIES) + $(AM_V_CCLD)$(libmoo_x11_la_LINK) $(am_libmoo_x11_la_rpath) $(libmoo_x11_la_OBJECTS) $(libmoo_x11_la_LIBADD) $(LIBS) + mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -526,6 +541,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmoo_console_la-console.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmoo_ffi_la-ffi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmoo_stdio_la-stdio.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmoo_x11_la-x11.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @@ -572,6 +588,13 @@ libmoo_stdio_la-stdio.lo: stdio.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmoo_stdio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmoo_stdio_la-stdio.lo `test -f 'stdio.c' || echo '$(srcdir)/'`stdio.c +libmoo_x11_la-x11.lo: x11.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmoo_x11_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmoo_x11_la-x11.lo -MD -MP -MF $(DEPDIR)/libmoo_x11_la-x11.Tpo -c -o libmoo_x11_la-x11.lo `test -f 'x11.c' || echo '$(srcdir)/'`x11.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmoo_x11_la-x11.Tpo $(DEPDIR)/libmoo_x11_la-x11.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='x11.c' object='libmoo_x11_la-x11.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmoo_x11_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmoo_x11_la-x11.lo `test -f 'x11.c' || echo '$(srcdir)/'`x11.c + mostlyclean-libtool: -rm -f *.lo diff --git a/moo/mod/_ffi.h b/moo/mod/_ffi.h index 5a8964f..d213036 100644 --- a/moo/mod/_ffi.h +++ b/moo/mod/_ffi.h @@ -24,8 +24,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _MOO_LIB_MOD_FFI_H_ -#define _MOO_LIB_MOD_FFI_H_ +#ifndef _MOO_MOD_FFI_H_ +#define _MOO_MOD_FFI_H_ #include diff --git a/moo/mod/_stdio.h b/moo/mod/_stdio.h index a11b871..d0b604e 100644 --- a/moo/mod/_stdio.h +++ b/moo/mod/_stdio.h @@ -24,8 +24,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _MOO_LIB_MOD_STDIO_H_ -#define _MOO_LIB_MOD_STDIO_H_ +#ifndef _MOO_MOD_STDIO_H_ +#define _MOO_MOD_STDIO_H_ #include diff --git a/moo/mod/_x11.h b/moo/mod/_x11.h new file mode 100644 index 0000000..ac97a40 --- /dev/null +++ b/moo/mod/_x11.h @@ -0,0 +1,43 @@ +/* + * $Id$ + * + Copyright (c) 2014-2017 Chung, Hyung-Hwan. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MOO_MOD_X11_H_ +#define _MOO_MOD_X11_H_ + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +MOO_EXPORT int moo_mod_x11 (moo_t* moo, moo_mod_t* mod); + +#if defined(__cplusplus) +} +#endif + +#endif + diff --git a/moo/mod/console.h b/moo/mod/console.h index d735a9e..9a433d7 100644 --- a/moo/mod/console.h +++ b/moo/mod/console.h @@ -24,8 +24,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _MOO_LIB_MOD_CONSOLE_H_ -#define _MOO_LIB_MOD_CONSOLE_H_ +#ifndef _MOO_MOD_CONSOLE_H_ +#define _MOO_MOD_CONSOLE_H_ #include diff --git a/moo/mod/x11.c b/moo/mod/x11.c new file mode 100644 index 0000000..7e9384e --- /dev/null +++ b/moo/mod/x11.c @@ -0,0 +1,261 @@ +/* + * $Id$ + * + Copyright (c) 2014-2017 Chung, Hyung-Hwan. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "_x11.h" +#include + +#include +#include + +#include + +typedef struct x11_t x11_t; +struct x11_t +{ + MOO_OBJ_HEADER; + xcb_connection_t* c; +}; + +static moo_pfrc_t pf_newinstsize (moo_t* moo, moo_ooi_t nargs) +{ + moo_ooi_t newinstsize = MOO_SIZEOF(x11_t) - MOO_SIZEOF(moo_obj_t); + MOO_STACK_SETRET (moo, nargs, MOO_SMOOI_TO_OOP(newinstsize)); + return MOO_PF_SUCCESS; +} + +static moo_pfrc_t pf_connect (moo_t* moo, moo_ooi_t nargs) +{ + x11_t* x11; + xcb_connection_t* c; + +/* TODO: accept display target as a parameter */ + if (nargs != 0) + { + moo_seterrnum (moo, MOO_EINVAL); + goto softfail; + } + + x11 = (x11_t*)MOO_STACK_GETRCV(moo, nargs); + /* + name = MOO_STACK_GETARG(moo, nargs, 0); + + if (!MOO_ISTYPEOF(moo, name, MOO_OBJ_TYPE_CHAR)) + { + moo_seterrnum (moo, MOO_EINVAL); + goto softfail; + } + + MOO_DEBUG3 (moo, " %.*js => %p\n", MOO_OBJ_GET_SIZE(name), ((moo_oop_char_t)name)->slot, rcv->handle); + */ + c = xcb_connect (MOO_NULL, MOO_NULL); + if (!c) + { + MOO_DEBUG0 (moo, " Cannot connect to X11 server\n"); + goto softfail; + } + + x11->c = c; + MOO_STACK_SETRETTORCV (moo, nargs); + return MOO_PF_SUCCESS; + +softfail: + MOO_STACK_SETRETTOERROR (moo, nargs); + return MOO_PF_SUCCESS; +} + +static moo_pfrc_t pf_disconnect (moo_t* moo, moo_ooi_t nargs) +{ + x11_t* x11; + + if (nargs != 0) + { + moo_seterrnum (moo, MOO_EINVAL); + goto softfail; + } + + x11 = (x11_t*)MOO_STACK_GETRCV(moo, nargs); + + MOO_DEBUG1 (moo, " %p\n", x11->c); + + xcb_disconnect (x11->c); + x11->c = MOO_NULL; + + MOO_STACK_SETRETTORCV (moo, nargs); + return MOO_PF_SUCCESS; + +softfail: + MOO_STACK_SETRETTOERROR (moo, nargs); + return MOO_PF_SUCCESS; +} + +/* ------------------------------------------------------------------------ */ + +typedef struct fnctab_t fnctab_t; +struct fnctab_t +{ + moo_method_type_t type; + moo_ooch_t mthname[15]; + int variadic; + moo_pfimpl_t handler; +}; + + +static moo_pfimpl_t search_fnctab (moo_t* moo, const fnctab_t* fnctab, moo_oow_t fnclen, const moo_ooch_t* name) +{ + int left, right, mid, n; + + left = 0; right = fnclen - 1; + + while (left <= right) + { + mid = (left + right) / 2; + + n = moo_compoocstr (name, fnctab[mid].mthname); + if (n < 0) right = mid - 1; + else if (n > 0) left = mid + 1; + else + { + return fnctab[mid].handler; + } + } + + moo->errnum = MOO_ENOENT; + return MOO_NULL; +} + +static int import_fnctab (moo_t* moo, moo_mod_t* mod, moo_oop_t _class, const fnctab_t* fnctab, moo_oow_t fnclen) +{ + int ret = 0; + moo_oow_t i; + + moo_pushtmp (moo, &_class); + for (i = 0; i < fnclen; i++) + { + if (moo_genpfmethod (moo, mod, _class, fnctab[i].type, fnctab[i].mthname, fnctab[i].variadic, MOO_NULL) <= -1) + { + /* TODO: delete pfmethod generated??? */ + ret = -1; + break; + } + } + + moo_poptmp (moo); + return ret; +} + + +#define C MOO_METHOD_CLASS +#define I MOO_METHOD_INSTANCE + +/* ------------------------------------------------------------------------ */ + +static fnctab_t x11_fnctab[] = +{ + { C, { '_','n','e','w','I','n','s','t','S','i','z','e','\0' }, 0, pf_newinstsize }, + { I, { 'c','o','n','n','e','c','t','\0' }, 0, pf_connect }, + { I, { 'd','i','s','c','o','n','n','e','c','t','\0' }, 0, pf_disconnect } +}; + + +static int x11_import (moo_t* moo, moo_mod_t* mod, moo_oop_t _class) +{ + return import_fnctab (moo, mod, _class, x11_fnctab, MOO_COUNTOF(x11_fnctab)); +} + +static moo_pfimpl_t x11_query (moo_t* moo, moo_mod_t* mod, const moo_ooch_t* name) +{ + return search_fnctab (moo, x11_fnctab, MOO_COUNTOF(x11_fnctab), name); +} + +static void x11_unload (moo_t* moo, moo_mod_t* mod) +{ + /* TODO: anything? close open open dll handles? For that, pf_open must store the value it returns to mod->ctx or somewhere..*/ +} + +int moo_mod_x11 (moo_t* moo, moo_mod_t* mod) +{ + mod->import = x11_import; + mod->query = x11_query; + mod->unload = x11_unload; + mod->ctx = MOO_NULL; + return 0; +} + + +#if 0 + + screen = xcb_setup_roots_iterator(xcb_get_setup(x11->c)).data; + x11->mw = xcb_generate_id (xtn->c); + + xcb_create_window (x11->c, + XCB_COPY_FROM_PARENT, + xtn->mw, + screen->root, + 0, 0, 300, 300, 10, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + screen->root_visual, + 0, MOO_NULL); + + xcb_map_window (xtn->xcb, xtn->mw); + xcb_flush (xtn->xcb); + + xcb_generic_event_t* evt; + while ((evt = xcb_poll_for_event(xtn->xcb, 0)) + { + /* TODO: dispatch event read */ + } + +static fnctab_t x11_window_fnctab[] = +{ + { C, { '_','n','e','w','I','n','s','t','S','i','z','e','\0' }, 0, pf_newinstsize }, + { I, { 'c','o','n','n','e','c','t','\0' }, 0, pf_connect }, + { I, { 'd','i','s','c','o','n','n','e','c','t','\0' }, 0, pf_disconnect } +}; + +static int x11_window_import (moo_t* moo, moo_mod_t* mod, moo_oop_t _class) +{ + return import_fnctab (moo, mod, _class, x11_window_fnctab, MOO_COUNTOF(x11_window_fnctab)); +} + +static moo_pfimpl_t x11_window_query (moo_t* moo, moo_mod_t* mod, const moo_ooch_t* name) +{ + return search_fnctab (moo, x11_window_fnctab, MOO_COUNTOF(x11_window_fnctab), name); +} + +static void windowunload (moo_t* moo, moo_mod_t* mod) +{ + /* TODO: anything? */ +} + +int moo_mod_x11_window (moo_t* moo, moo_mod_t* mod) +{ + mod->import = x11_window_import; + mod->query = x11_window_query; + mod->unload = x11_window_unload; + mod->ctx = MOO_NULL; + return 0; +} +#endif