|
From: <cli...@li...> - 2010-12-15 01:03:11
|
Send clisp-cvs mailing list submissions to cli...@li... To subscribe or unsubscribe via the World Wide Web, visit https://lists.sourceforge.net/lists/listinfo/clisp-cvs or, via email, send a message with subject or body 'help' to cli...@li... You can reach the person managing the list at cli...@li... When replying, please edit your Subject line so it is more specific than "Re: Contents of clisp-cvs digest..." CLISP CVS commits for today Today's Topics: 1. clisp/src ChangeLog, 1.7573, 1.7574 subr.d, 1.278, 1.279 subrkw.d, 1.71, 1.72 xthread.d, 1.33, 1.34 zthread.d, 1.92, 1.93 (Vladimir Tzankov) 2. clisp/tests ChangeLog,1.670,1.671 mt.tst,1.25,1.26 (Vladimir Tzankov) 3. clisp/doc impext.xml,1.658,1.659 (Vladimir Tzankov) 4. clisp/doc impext.xml,1.659,1.660 (Sam Steingold) ---------------------------------------------------------------------- Message: 1 Date: Sat, 30 Oct 2010 21:03:02 +0000 From: Vladimir Tzankov <vt...@us...> Subject: clisp/src ChangeLog, 1.7573, 1.7574 subr.d, 1.278, 1.279 subrkw.d, 1.71, 1.72 xthread.d, 1.33, 1.34 zthread.d, 1.92, 1.93 To: cli...@li... Message-ID: <E1P...@sf...> Update of /cvsroot/clisp/clisp/src In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv27775/src Modified Files: ChangeLog subr.d subrkw.d xthread.d zthread.d Log Message: [MULTITHREAD]: add optional :TEST predicate to MT:EXEMPTION-WAIT Index: subrkw.d =================================================================== RCS file: /cvsroot/clisp/clisp/src/subrkw.d,v retrieving revision 1.71 retrieving revision 1.72 diff -u -d -r1.71 -r1.72 --- subrkw.d 19 Feb 2010 20:36:06 -0000 1.71 +++ subrkw.d 30 Oct 2010 21:02:59 -0000 1.72 @@ -232,7 +232,7 @@ s(mutex_lock) v(1, (kw(name))) s(make_exemption) -v(1, (kw(timeout))) +v(2, (kw(test),kw(timeout))) s(exemption_wait) #endif v(7, (kw(name),kw(code),kw(constants),kw(seclass),kw(lambda_list),kw(documentation),kw(jitc_p)) ) Index: zthread.d =================================================================== RCS file: /cvsroot/clisp/clisp/src/zthread.d,v retrieving revision 1.92 retrieving revision 1.93 diff -u -d -r1.92 -r1.93 --- zthread.d 21 Oct 2010 18:42:17 -0000 1.92 +++ zthread.d 30 Oct 2010 21:02:59 -0000 1.93 @@ -839,59 +839,95 @@ VALUES1(TheExemption(obj)->xco_name); } -LISPFUN(exemption_wait,seclass_default,2,0,norest,key,1,(kw(timeout))) -{ /* (EXEMPTION-WAIT exemption mutex) */ +#if defined(POSIX_THREADS) +/* UP: fills timespec with millis milliseconds form "now" + <> r: timespec to be filled + > millis: milliseconds */ +local inline struct timespec *get_abs_timeout(struct timespec *r, + uintL millis) { + var struct timeval tv; + gettimeofday(&tv, NULL); + r->tv_sec = tv.tv_sec + (tv.tv_usec + millis * 1000) / 1000000; + r->tv_nsec = 1000 * ((tv.tv_usec + millis*1000) % 1000000); + return r; +} +#endif + +LISPFUN(exemption_wait,seclass_default,2,0,norest,key,1,(kw(test),kw(timeout))) +{ /* (EXEMPTION-WAIT exemption mutex :test predicate :timeout to) */ var struct timeval tv; var struct timeval *tvp = sec_usec(popSTACK(),unbound,&tv); - STACK_0 = check_mutex(STACK_0); - STACK_1 = check_exemption(STACK_1); - if (!eq(TheMutex(STACK_0)->xmu_owner, current_thread()->_lthread)) { + if (!missingp(STACK_0) && !functionp(STACK_0)) + STACK_0 = check_function_replacement(STACK_0); + STACK_1 = check_mutex(STACK_1); + STACK_2 = check_exemption(STACK_2); + if (!eq(TheMutex(STACK_1)->xmu_owner, current_thread()->_lthread)) { /* the mutex should be owned by the calling thread. */ - var object mx = STACK_0; + var object mx = STACK_1; pushSTACK(mx); /* CELL-ERROR Slot NAME */ pushSTACK(current_thread()->_lthread); pushSTACK(mx); pushSTACK(S(exemption_wait)); error(control_error,GETTEXT("~S: mutex ~S should be owned by ~S")); } - /* we are the owners - let's see how many times we we have locked it */ - if (TheMutex(STACK_0)->xmu_recurse_count != 1) { + /* we are the owners - let's see how many times it is locked */ + if (TheMutex(STACK_1)->xmu_recurse_count != 1) { /* using recursive mutex with condition variables may cause really weird errors that are almost impossible to debug. Let's check that we have locked it only once. */ - var object mx = STACK_0; + var object mx = STACK_1; pushSTACK(mx); /* CELL-ERROR Slot NAME */ pushSTACK(current_thread()->_lthread); pushSTACK(mx); pushSTACK(S(exemption_wait)); error(control_error,GETTEXT("~S: recursive mutex ~S is locked multiple times by ~S")); } - /* pthread_cond_wait() will release the OS mutex - so clear the owner. */ - TheMutex(STACK_0)->xmu_owner = NIL; TheMutex(STACK_0)->xmu_recurse_count = 0; /* get the pointer before we allow the GC to run */ - var xmutex_t *m = TheMutex(STACK_0)->xmu_system; - var xcondition_t *c = TheExemption(STACK_1)->xco_system; - var gcv_object_t *mxrec = &STACK_0; /*in case of interrupt STACK_0 != mutex*/ - clisp_thread_t *thr = current_thread(); - var int res; - - thr->_wait_condition = c; - thr->_wait_mutex = m; - begin_system_call(); GC_SAFE_REGION_BEGIN(); - if (tvp) - res = xcondition_timedwait(c,m,tvp->tv_sec*1000 + tvp->tv_usec/1000); - else - res = xcondition_wait(c,m); - thr->_wait_mutex = NULL; - thr->_wait_condition = NULL; - /* do not (possibly) handle pending interrupts here since on non-local exit - from interrupt we may leave the mutex object in inconsistent state*/ - GC_SAFE_REGION_END_WITHOUT_INTERRUPTS(); end_system_call(); - - /* set again the owner. even in case of error - this should be fine. */ - TheMutex(*mxrec)->xmu_owner = current_thread()->_lthread; - TheMutex(*mxrec)->xmu_recurse_count = 1; - /* handle (if any) interrupts */ - HANDLE_PENDING_INTERRUPTS(thr); - skipSTACK(2); + var xmutex_t *m = TheMutex(STACK_1)->xmu_system; + var xcondition_t *c = TheExemption(STACK_2)->xco_system; + /* in case of interrupt STACK is changed - save pointers to objects needed + before handling the interrupt */ + var gcv_object_t *mxrec = &STACK_1; + var gcv_object_t *predicate = &STACK_0; + var clisp_thread_t *thr = current_thread(); + var int res = 0; + var bool wait_more = true; +#ifdef POSIX_THREADS + /* absolute time is needed in order to handle properly possible + spurious wakeups */ + var struct timespec _timeout, *timeout = tvp ? + get_abs_timeout(&_timeout,tvp->tv_sec*1000 + tvp->tv_usec/1000) : NULL; +#else /* WIN32_THREADS */ + var uintL _timeout, *timeout = + tvp ? (_timeout = tvp->tv_sec*1000 + tvp->tv_usec/1000, &_timeout) : NULL; +#endif + while (wait_more) { + if (!missingp(*predicate)) { /* there is :test predicate */ + funcall(*predicate,0); + if (!nullp(value1)) break; + } else + wait_more = false; /* on next iteration we will exit */ + /* pthread_cond_wait() will release the OS mutex - so clear the owner. */ + TheMutex(*mxrec)->xmu_owner = NIL; TheMutex(*mxrec)->xmu_recurse_count = 0; + /* mark on what the thread is waiting */ + thr->_wait_condition = c; + thr->_wait_mutex = m; + begin_system_call(); GC_SAFE_REGION_BEGIN(); + res = xcondition_wait(c,m,timeout); +#ifdef POSIX_THREADS + /* handle possible spurious wakeups */ + wait_more = (res == 0 && !missingp(*predicate)); +#endif + thr->_wait_mutex = NULL; + thr->_wait_condition = NULL; + /* do not (possibly) handle pending interrupts here since on non-local exit + from interrupt we may leave the mutex object in inconsistent state*/ + GC_SAFE_REGION_END_WITHOUT_INTERRUPTS(); end_system_call(); + /* set again the owner. even in case of error - this should be fine. */ + TheMutex(*mxrec)->xmu_owner = current_thread()->_lthread; + TheMutex(*mxrec)->xmu_recurse_count = 1; + /* handle (if any) interrupts */ + HANDLE_PENDING_INTERRUPTS(thr); + } + skipSTACK(3); VALUES1(res ? NIL : T); } @@ -919,21 +955,7 @@ /* LOW-LEVEL THREADS STUFF */ /* TODO: not the right place to put these stuff. separate file is better ? */ -#if defined(POSIX_THREADS) - -/* UP: fills timespec with millis milliseconds form "now" - <> r: timespec to be filled - > millis: milliseconds */ -local inline void get_abs_timeout(struct timespec *r, uintL millis) { - var struct timeval tv; - gettimeofday(&tv, NULL); - r->tv_sec = tv.tv_sec + (tv.tv_usec + millis * 1000) / 1000000; - r->tv_nsec = 1000 * ((tv.tv_usec + millis*1000) % 1000000); -} - - -#else /* WIN32_THREADS */ - +#if defined(WIN32_THREADS) /* UP: helper function for waiting on a condition associated with "raw" mutex > c: condition object > m: xmutex_raw_t object @@ -946,12 +968,11 @@ (c)->waiting_count++; LeaveCriticalSection(&(c)->cs); LeaveCriticalSection(m); - var DWORD timeout = millis == THREAD_WAIT_INFINITE ? INFINITE : millis; + var DWORD timeout = (millis == THREAD_WAIT_INFINITE) ? INFINITE : millis; var DWORD r = WaitForSingleObject((c)->sem,timeout); EnterCriticalSection(m); return r == WAIT_OBJECT_0 ? 0 : 1; } - #endif /* UP: initializes xlock_t @@ -1092,24 +1113,22 @@ signals can be handled if arrive > c: the condition variable > m: the mutex /xlock_t/ - > timeout: timeout in milliseconds + > timeout: timeout (NULL for infinite). POSIX_THREADS - this is pointer + to struct timespec. WIN32_THREADS - ptr to uintL in ms < Returns 0 on success, otherwise the error code from pthreads */ -int xcondition_wait_helper(xcondition_t *c,xlock_t *m, uintL timeout) +int xcondition_wait(xcondition_t *c,xlock_t *m, void *timeout) { var int r=-1; /* mutex is owned by us and it is locked just once. our caller assures this */ xlock_unlock_helper(m,false); /* mark as unlocked */ #ifdef POSIX_THREADS - if (timeout != THREAD_WAIT_INFINITE) { - var struct timespec ww; - get_abs_timeout(&ww,timeout); - r = pthread_cond_timedwait(c,&m->xl_mutex,&ww); - } else { - r = pthread_cond_wait(c,&m->xl_mutex); - } + r = timeout ? + pthread_cond_timedwait(c,&m->xl_mutex,(struct timespec *)timeout) : + pthread_cond_wait(c,&m->xl_mutex); #else /* WIN32 */ - r = win32_xcondition_wait(c,&m->xl_mutex,timeout); + r = win32_xcondition_wait(c,&m->xl_mutex, + timeout ? *(uintL*)timeout : THREAD_WAIT_INFINITE); #endif /* mark again the mutex as ours */ xlock_lock_helper(m,0,false); Index: ChangeLog =================================================================== RCS file: /cvsroot/clisp/clisp/src/ChangeLog,v retrieving revision 1.7573 retrieving revision 1.7574 diff -u -d -r1.7573 -r1.7574 --- ChangeLog 28 Oct 2010 20:36:50 -0000 1.7573 +++ ChangeLog 30 Oct 2010 21:02:59 -0000 1.7574 @@ -1,3 +1,15 @@ +2010-10-30 Vladimir Tzankov <vtz...@gm...> + + [MULTITHREAD]: add optional :TEST predicate to MT:EXEMPTION-WAIT + * subr.d, subrkw.d (EXEMPTION-WAIT): accept optional :TEST argument + * xthread.d (xcondition_wait): accept timeout as void pointer. with + POSIX_THREADS it is absolute struct timespec, with WIN32_THREADS it is + unsigned integer specifying milliseconds to wait + * zthread.d (EXEMPTION-WAIT): loop until :TEST predicate is satisfied + thus simplifies EXEMPTION-WAIT usage with POSIX_THREADS where spurious + wakeups are possible + (xcondition_wait): handle timeout parameter properly + 2010-10-28 Sam Steingold <sd...@gn...> * modules/berkeley-db/bdb.c (time_stamp): make "prefix" const to avoid Index: subr.d =================================================================== RCS file: /cvsroot/clisp/clisp/src/subr.d,v retrieving revision 1.278 retrieving revision 1.279 diff -u -d -r1.278 -r1.279 --- subr.d 21 Oct 2010 18:42:17 -0000 1.278 +++ subr.d 30 Oct 2010 21:02:59 -0000 1.279 @@ -1451,7 +1451,7 @@ LISPFUN(make_exemption,seclass_default,0,0,norest,key,1,(kw(name))) LISPFUNNR(exemption_name,1) LISPFUNN(exemption_signal,1) -LISPFUN(exemption_wait,seclass_default,2,0,norest,key,1, - (kw(timeout))) +LISPFUN(exemption_wait,seclass_default,2,0,norest,key,2, + (kw(test),kw(timeout))) LISPFUNN(exemption_broadcast,1) #endif Index: xthread.d =================================================================== RCS file: /cvsroot/clisp/clisp/src/xthread.d,v retrieving revision 1.33 retrieving revision 1.34 diff -u -d -r1.33 -r1.34 --- xthread.d 25 Oct 2009 13:51:35 -0000 1.33 +++ xthread.d 30 Oct 2010 21:02:59 -0000 1.34 @@ -34,7 +34,6 @@ Upon entry to this file, one of these symbols shall be defined: POSIX_THREADS POSIX.1c pthread_* - SOLARIS_THREADS Solaris 2.4, 2.5 thr_* WIN32_THREADS Win32 *Thread This file defines the following types: @@ -78,9 +77,6 @@ - Unlock a mutex. extern int xmutex_unlock (xmutex_t* m); - Thread-local storage: - - (This is probably not useful at all. The number of thread-local storage - - words is limited: 512 on Win32, 128 with LinuxThreads. And it's probably - - much slower than my current_thread() function.) - Create a word of thread-local storage, and return a key to it. extern int xthread_key_create (xthread_key_t* key); - Delete a word of thread-local storage. @@ -91,8 +87,7 @@ extern void xthread_key_set (xthread_key_t key, void* value); */ - -#if !(defined(POSIX_THREADS) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS)) +#if !(defined(POSIX_THREADS) || defined(WIN32_THREADS)) #error Define your flavour of multithreading #endif @@ -241,7 +236,7 @@ int xlock_destroy(xlock_t *l); int xlock_lock_helper(xlock_t *l, uintL timeout, bool lock_real); int xlock_unlock_helper(xlock_t *l, bool unlock_real); -int xcondition_wait_helper(xcondition_t *c,xlock_t *m, uintL timeout); +int xcondition_wait(xcondition_t *c,xlock_t *m, void *timeout); /* our lisp space mutex */ #define xmutex_t xlock_t @@ -254,11 +249,6 @@ #define xmutex_trylock(m) xlock_lock_helper(m,0,true) #define xmutex_unlock(m) xlock_unlock_helper(m,true) -/* and some xcondition_t operations */ -#define xcondition_wait(c,m) xcondition_wait_helper(c,m,THREAD_WAIT_INFINITE) -#define xcondition_timedwait(c,m,millis) xcondition_wait_helper(c,m,millis) - - /* ========================================================================== Spin-locks. ------------------------------ Message: 2 Date: Sat, 30 Oct 2010 21:06:21 +0000 From: Vladimir Tzankov <vt...@us...> Subject: clisp/tests ChangeLog,1.670,1.671 mt.tst,1.25,1.26 To: cli...@li... Message-ID: <E1P...@sf...> Update of /cvsroot/clisp/clisp/tests In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv28655 Modified Files: ChangeLog mt.tst Log Message: mt.tst: add tests for :TEST and :TIMEOUT arguments of EXEMPTION-WAIT Index: mt.tst =================================================================== RCS file: /cvsroot/clisp/clisp/tests/mt.tst,v retrieving revision 1.25 retrieving revision 1.26 diff -u -d -r1.25 -r1.26 --- mt.tst 19 Feb 2010 20:36:06 -0000 1.25 +++ mt.tst 30 Oct 2010 21:06:19 -0000 1.26 @@ -182,16 +182,16 @@ (sleep 0.5) NIL (thread-active-p *th3*) T ;; kill is deferred -;; test exemtpion-broadcast and thread-interrupt :override +;; test exemption-broadcast and thread-interrupt :override (with-mutex-lock (*mu1*) (thread-interrupt *th3* :function (lambda () (with-mutex-lock (*mu1*) (setf *exemption-state* :broadcasted) (exemption-broadcast *exemption*))) :override t) - (loop until (eq *exemption-state* :broadcasted) - do (exemption-wait *exemption* *mu1*) - finally (return *exemption-state*))) + (exemption-wait *exemption* *mu1* + :test (lambda () (eq *exemption-state* :broadcasted))) + *exemption-state*) :BROADCASTED (thread-active-p *th3*) T ;; thread should be still running @@ -199,6 +199,16 @@ (thread-join *th3*) NIL (thread-active-p *th3*) NIL ;; should be dead +;; exemption-wait with :timeout (and combined with test predicate) +(let ((m (make-mutex)) + (e (make-exemption))) + (with-timeout (5 t) + (with-mutex-lock (m) + (list + (exemption-wait e m :timeout 1) + (exemption-wait e m :timeout 1 :test (constantly nil)))))) +(NIL NIL) + ;; create thread with very tiny lisp stack (thus preserving memory) ;; on mac osx lisp heap overlaps lisp stack regions (malloc-ed) when ;; the number of thread with big stacks is very high (will be inspected Index: ChangeLog =================================================================== RCS file: /cvsroot/clisp/clisp/tests/ChangeLog,v retrieving revision 1.670 retrieving revision 1.671 diff -u -d -r1.670 -r1.671 --- ChangeLog 18 Oct 2010 22:19:24 -0000 1.670 +++ ChangeLog 30 Oct 2010 21:06:19 -0000 1.671 @@ -1,3 +1,7 @@ +2010-10-31 Vladimir Tzankov <vtz...@gm...> + + * mt.tst: add tests for :TEST and :TIMEOUT arguments of EXEMPTION-WAIT + 2010-10-18 Sam Steingold <sd...@gn...> * loop.tst: add a test for bug#3089988: (loop for x do (print x)) ------------------------------ Message: 3 Date: Sat, 30 Oct 2010 21:07:49 +0000 From: Vladimir Tzankov <vt...@us...> Subject: clisp/doc impext.xml,1.658,1.659 To: cli...@li... Message-ID: <E1P...@sf...> Update of /cvsroot/clisp/clisp/doc In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv28908 Modified Files: impext.xml Log Message: document :TEST argument of MT:EXEPMTION-WAIT Index: impext.xml =================================================================== RCS file: /cvsroot/clisp/clisp/doc/impext.xml,v retrieving revision 1.658 retrieving revision 1.659 diff -u -d -r1.658 -r1.659 --- impext.xml 27 Oct 2010 18:25:28 -0000 1.658 +++ impext.xml 30 Oct 2010 21:07:47 -0000 1.659 @@ -4982,12 +4982,15 @@ <simpara>Cf. <function role="unix">pthread_cond_signal</function>.</simpara> </listitem></varlistentry> <varlistentry id="exemption-wait"><term><code>(&exemption-wait; - &exemp-r; &mutex-r; &key-amp; &timeout-k;)</code></term> + &exemp-r; &mutex-r; &key-amp; &timeout-k; &test-k;)</code></term> <listitem><simpara>Wait for another &thread; to call &exemption-signal; or &exemption-broadcast; on &exemp-r;. &mutex-r; should be locked by the caller; otherwise an &err-sig;. The function releases the &mutex-r; and waits for &exemp-r;. On return &mutex-r; is acquired again.</simpara> + <simpara>When using exemptions there is always a boolean predicate involving + shared variables associated with each exemption wait that is true if the + thread should proceed.</simpara> <simpara>The function waits up to &timeout-k; &seconds;. If timeout is not specified, waits forever.</simpara><simpara> Returns &t; if &exemp-r; was signaled and &nil; on timeout.</simpara> @@ -4995,9 +4998,17 @@ <ulink url="http://en.wikipedia.org/wiki/Spurious_wakeup">spurious wakeup</ulink>s, i.e., this function may return &t; even though no thread called &exemption-broadcast; or &exemption-signal;. - Therefore, a common idiom for using this function is <code>(&loop; - :while (some-condition-is-satisfied) :do (&exemption-wait; &exemp-r; - &mutex-r;))</code>.</para> + Therefore, a common idiom for using this function is: <simpara><code>(&loop; + :until (some-predicate) :do (&exemption-wait; &exemp-r; &mutex-r;))</code> + </simpara><simpara>Optional &test-k; argument simplifies this. When supplied + &exemption-wait; returns when either &test-k; predicate is satisfied (always + called while &mutex-r; is held) or when &timeout-k; elapses. The above loop + is equivalent to:<simpara><code>(&exemption-wait; &exemp-r; &mutex-r; + &test-k; #'some-predicate)</code></simpara> + When &test-k; is supplied &exemption-wait; returns &t; when &exemp-r; was + signaled and &test-k; predicate is satisfied and &nil; on timeout. + </simpara><simpara>This is the preferred and most portable way to wait on + exemption.</simpara></para> <simpara>Cf. <function role="unix">pthread_cond_wait</function>.</simpara> </listitem></varlistentry> <varlistentry id="exemption-broadcast"><term><code>(&exemption-broadcast; ------------------------------ Message: 4 Date: Sun, 31 Oct 2010 06:10:51 +0000 From: Sam Steingold <sd...@us...> Subject: clisp/doc impext.xml,1.659,1.660 To: cli...@li... Message-ID: <E1P...@sf...> Update of /cvsroot/clisp/clisp/doc In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv27196 Modified Files: impext.xml Log Message: tweak formatting Index: impext.xml =================================================================== RCS file: /cvsroot/clisp/clisp/doc/impext.xml,v retrieving revision 1.659 retrieving revision 1.660 diff -u -d -r1.659 -r1.660 --- impext.xml 30 Oct 2010 21:07:47 -0000 1.659 +++ impext.xml 31 Oct 2010 06:10:49 -0000 1.660 @@ -4998,17 +4998,17 @@ <ulink url="http://en.wikipedia.org/wiki/Spurious_wakeup">spurious wakeup</ulink>s, i.e., this function may return &t; even though no thread called &exemption-broadcast; or &exemption-signal;. - Therefore, a common idiom for using this function is: <simpara><code>(&loop; + Therefore, a common idiom for using this function is: <code>(&loop; :until (some-predicate) :do (&exemption-wait; &exemp-r; &mutex-r;))</code> - </simpara><simpara>Optional &test-k; argument simplifies this. When supplied - &exemption-wait; returns when either &test-k; predicate is satisfied (always - called while &mutex-r; is held) or when &timeout-k; elapses. The above loop - is equivalent to:<simpara><code>(&exemption-wait; &exemp-r; &mutex-r; - &test-k; #'some-predicate)</code></simpara> - When &test-k; is supplied &exemption-wait; returns &t; when &exemp-r; was - signaled and &test-k; predicate is satisfied and &nil; on timeout. + <simpara>The &test-k; argument simplifies this. When supplied, + &exemption-wait; returns when either &test-k; predicate is satisfied + (always called while &mutex-r; is held) or when &timeout-k; elapses. + The above loop is equivalent to: <code>(&exemption-wait; &exemp-r; + &mutex-r; &test-k; #'some-predicate)</code>. + When &test-k; is supplied, &exemption-wait; returns &t; when &exemp-r; was + signaled and &test-k; predicate is satisfied and &nil; on timeout. </simpara><simpara>This is the preferred and most portable way to wait on - exemption.</simpara></para> + an exemption.</simpara></para> <simpara>Cf. <function role="unix">pthread_cond_wait</function>.</simpara> </listitem></varlistentry> <varlistentry id="exemption-broadcast"><term><code>(&exemption-broadcast; ------------------------------ ------------------------------------------------------------------------------ Nokia and AT&T present the 2010 Calling All Innovators-North America contest Create new apps & games for the Nokia N8 for consumers in U.S. and Canada $10 million total in prizes - $4M cash, 500 devices, nearly $6M in marketing Develop with Nokia Qt SDK, Web Runtime, or Java and Publish to Ovi Store http://p.sf.net/sfu/nokia-dev2dev ------------------------------ _______________________________________________ clisp-cvs mailing list cli...@li... https://lists.sourceforge.net/lists/listinfo/clisp-cvs End of clisp-cvs Digest, Vol 54, Issue 21 ***************************************** |