Hi, Mark
I'm interesting in your work.
First, I'd like to know, how to do a "condition variable wait with timeout" with your exist work,
Second, do you think it's possible to make ABCL supporting some atomic operations, something like ATOMIC-INCF or ATOMIC-PUSH, this can be very useful to implement some lockless algorithms.
Regards,
Chun Tian (binghe)
在 2011-3-18,15:50, Mark Evenson 写道:
On 3/2/11 8:50 PM, Martin Simmons wrote:
I think that the implementation of condition-wait has some major problems:
Thanks very much for the comments.
I have an [updated patch][1] that attempts to address these issues for further review for inclusion in BORDEAUX-THREADS.
- If no other threads are trying to claim the lock, then condition-wait will
return immediately rather than waiting.
I couldn't reproduce this behavior. In ABCL, the THREADS:OBJECT-WAIT implementation is mainly a simple wrapping of the underlying [java.lang.Object.wait()][2] which clearly should wait.
- If two threads are waiting in condition-wait and two other threads call
condition-notify, then it is possible that only one thread will return from condition-wait because the call to acquire-lock in one of them might return nil causing it to wait again.
The DO looping construct has been replaced with a simpler subsequent BT:ACQUIRE-LOCK that should solve this bug.
- If condition-notify is called by one thread when a waiting thread is just
about to enter the threads:synchronized-on form (but before it gets synchronized), then the notify will be lost. This happens because the underlying threading primitives have no "memory" of calls to notify when nothing it waiting (which is also the expected semantics for POSIX condition variables BTW).
THREADS:SYNCHRONIZED-ON is now the first form executed by BT:CONDITION-WAIT so the window here is considerably narrowed.
Also, I think condition-notify should be using threads:object-notify rather than threads:object-notify-all.
We now use THREADS:OBJECT-NOTIFY.
-- "A screaming comes across the sky. It has happened before, but there is nothing to compare to it now."
Bordeaux-threads-devel mailing list Bordeaux-threads-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/bordeaux-threads-devel
On 3/21/11 15:21 , Chun Tian (binghe) wrote:
Hi, Mark
I'm interesting in your work.
First, I'd like to know, how to do a "condition variable wait with timeout" with your exist work,
It should be pretty easy, as THREADS:OBJECT-WAIT has an optional parameter for TIMEOUT (see [the Java API for the semantics associated with this value][1])
[1]: http://download.oracle.com/javase/6/docs/api/java/lang/Object.html#wait%28lo...
So, one could naively extend my BORDEAUX-THREADS implementation as follows:
(defun condition-wait (condition lock &optional timeout) (threads:synchronized-on condition (release-lock lock) (if timeout (threads:object-wait condition timeout) (threads:object-wait condition)) (acquire-lock lock))
But then a wait on the condition variable which exceeded the timeout would be the same as a thread which was notified, which probably isn't what we want.
If you don't need to follow the B-T API, then I might go for an encapsulation [of the actual Condition class][2] which returns a boolean indicating whether the wait has returned because the timeout has expired.
[2]: http://download.oracle.com/javase/6/docs/api/java/util/concurrent/locks/Cond...
I'm not sure of your comfort with ABCL's Java FFI, but I would be happy to mentor you through an implementation that suits your needs, subject to possible time delays on my part due to other tasks.
Second, do you think it's possible to make ABCL supporting some atomic operations, something like ATOMIC-INCF or ATOMIC-PUSH, this can be very useful to implement some lockless algorithms.
Here, I would use the [atomic lock-free implementation in the JVM][3], which could give us such things quite cheaply.
[3]: http://download.oracle.com/javase/6/docs/api/java/util/concurrent/atomic/pac...
Do you have a Lisp-side API to recommend?
On Mon, Mar 21, 2011 at 4:04 PM, Mark Evenson evenson@panix.com wrote:
On 3/21/11 15:21 , Chun Tian (binghe) wrote:
Hi, Mark
I'm interesting in your work.
First, I'd like to know, how to do a "condition variable wait with timeout" with your exist work,
It should be pretty easy, as THREADS:OBJECT-WAIT has an optional parameter for TIMEOUT (see [the Java API for the semantics associated with this value][1])
So, one could naively extend my BORDEAUX-THREADS implementation as follows:
(defun condition-wait (condition lock &optional timeout) (threads:synchronized-on condition (release-lock lock) (if timeout (threads:object-wait condition timeout) (threads:object-wait condition)) (acquire-lock lock))
But then a wait on the condition variable which exceeded the timeout would be the same as a thread which was notified, which probably isn't what we want.
If you don't need to follow the B-T API, then I might go for an encapsulation [of the actual Condition class][2] which returns a boolean indicating whether the wait has returned because the timeout has expired.
Is condition-wait's return value significant? If not, it could be a boolean telling the user the if a timeout is the reason for the wakeup. object-wait would need to be modified accordingly. However, this is stepping outside the bordeaux-threads API, your code won't be portable.
I'm not sure of your comfort with ABCL's Java FFI, but I would be happy to mentor you through an implementation that suits your needs, subject to possible time delays on my part due to other tasks.
Second, do you think it's possible to make ABCL supporting some atomic operations, something like ATOMIC-INCF or ATOMIC-PUSH, this can be very useful to implement some lockless algorithms.
Here, I would use the [atomic lock-free implementation in the JVM][3], which could give us such things quite cheaply.
That's the way to do it on the JVM, but note that you need to declare in advance that you want an atomically-updatable "thing":
(let ((foo 1)) (atomic-incf foo)) ;;won't work (let ((foo (make-atomic-integer 1))) (atomic-incf foo)) ;;this will
this means you can't mix atomic references with unaware code, unless we provide atomic versions of LispObject and friends.
Alessio
Hi, Mark
Thanks you very much, now I know how to write CONDITION-VARIABLE-WAIT-WITH-TIMEOUT.
Actually I'm working on support of ABCL for PortableThreads [1], based on your work posted these days. Compare to Bordeaux-threads, PortableThreads is much more professional, it did many non-trivial threading API using each platform's exist features as basis. Bordeaux-threads is famous partly because it's ASDF-friendly from the very beginning, but PortableThreads has a single lisp file, which means it's very easy to directly be part of any threading-aware lisp packages, that's just what I did in my package.
I've already done most of the porting work, at least the relatively easy part. Do a diff between official version [1] and my version [2] of that single file, you'll find how ABCL support of this package was written. I also have sent an early version to GBBopen's author (Dr. Corkill).
PortableThreads also have four atomic operations: ATOMIC-INCF, ATOMIC-DECF, ATOMIC-PUSH and ATOMIC-POP, they do atomic operations on Lisp list and integers. When a platform doesn't have any atomic operator, PortableThread use a general way to support these atomic APIs: define a global lock, and wrap all atomic operations into that single global lock. This is not a efficient way, but do works.
I hope once GBBopen official adopts and complete this port, they can do a full unit test on it, to help finding out most of the potential issues in ABCL's current threading support.
P. S. For multi-threading APIs among all modern CL platforms, I think LispWorks defines the most beautiful and feature-rich SMP/multi-threading API [3]. However, that's too complex, hard to copy. In practical, PortableThreads API is just enough, I think.
Regards,
Chun Tian (binghe)
[1] http://gbbopen.org/svn/GBBopen/trunk/source/tools/portable-threads.lisp [2] https://cl-net-snmp.svn.sourceforge.net/svnroot/cl-net-snmp/snmp/branches/6/... [3] http://www.lispworks.com/documentation/lw60/LW/html/lw-228.htm#pgfId-885976
在 2011-3-21,23:04, Mark Evenson 写道:
On 3/21/11 15:21 , Chun Tian (binghe) wrote:
Hi, Mark
I'm interesting in your work.
First, I'd like to know, how to do a "condition variable wait with timeout" with your exist work,
It should be pretty easy, as THREADS:OBJECT-WAIT has an optional parameter for TIMEOUT (see [the Java API for the semantics associated with this value][1])
So, one could naively extend my BORDEAUX-THREADS implementation as follows:
(defun condition-wait (condition lock &optional timeout) (threads:synchronized-on condition (release-lock lock) (if timeout (threads:object-wait condition timeout) (threads:object-wait condition)) (acquire-lock lock))
But then a wait on the condition variable which exceeded the timeout would be the same as a thread which was notified, which probably isn't what we want.
If you don't need to follow the B-T API, then I might go for an encapsulation [of the actual Condition class][2] which returns a boolean indicating whether the wait has returned because the timeout has expired.
I'm not sure of your comfort with ABCL's Java FFI, but I would be happy to mentor you through an implementation that suits your needs, subject to possible time delays on my part due to other tasks.
Second, do you think it's possible to make ABCL supporting some atomic operations, something like ATOMIC-INCF or ATOMIC-PUSH, this can be very useful to implement some lockless algorithms.
Here, I would use the [atomic lock-free implementation in the JVM][3], which could give us such things quite cheaply.
Do you have a Lisp-side API to recommend?
-- "A screaming comes across the sky. It has happened before, but there is nothing to compare to it now."
armedbear-devel mailing list armedbear-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/armedbear-devel
armedbear-devel@common-lisp.net