2008-02-18 06:07:40 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								! Copyright (C) 2008 Slava Pestov.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								! See http://factorcode.org/license.txt for BSD license.
							 | 
						
					
						
							
								
									
										
										
										
											2008-08-19 15:06:20 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								USING: deques dlists kernel threads continuations math
							 | 
						
					
						
							
								
									
										
										
										
											2008-08-30 22:19:06 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								concurrency.conditions combinators.short-circuit accessors ;
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 06:07:40 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								IN: concurrency.locks
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								! Simple critical sections
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 17:20:18 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								TUPLE: lock threads owner reentrant? ;
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 06:07:40 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 17:20:18 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								: <lock> ( -- lock )
							 | 
						
					
						
							
								
									
										
										
										
											2008-04-13 16:06:27 -04:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    <dlist> f f lock boa ;
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 17:20:18 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								: <reentrant-lock> ( -- lock )
							 | 
						
					
						
							
								
									
										
										
										
											2008-04-13 16:06:27 -04:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    <dlist> f t lock boa ;
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 06:07:40 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								<PRIVATE
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 10:08:59 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								: acquire-lock ( lock timeout -- )
							 | 
						
					
						
							
								
									
										
										
										
											2008-08-30 22:19:06 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    over owner>>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    [ 2dup >r threads>> r> "lock" wait ] when drop
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    self >>owner drop ;
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 06:07:40 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								: release-lock ( lock -- )
							 | 
						
					
						
							
								
									
										
										
										
											2008-08-30 22:19:06 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    f >>owner
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    threads>> notify-1 ;
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 06:07:40 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 10:08:59 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								: do-lock ( lock timeout quot acquire release -- )
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-22 00:47:06 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    >r >r pick rot r> call ! use up  timeout acquire
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    swap r> curry [ ] cleanup ; inline
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 17:20:18 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								: (with-lock) ( lock timeout quot -- )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    [ acquire-lock ] [ release-lock ] do-lock ; inline
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 06:07:40 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								PRIVATE>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-22 00:47:06 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								: with-lock-timeout ( lock timeout quot -- )
							 | 
						
					
						
							
								
									
										
										
										
											2008-08-30 22:19:06 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    pick reentrant?>> [
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        pick owner>> self eq? [
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 17:20:18 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            2nip call
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ] [
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            (with-lock)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ] if
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ] [
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        (with-lock)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ] if ; inline
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 06:07:40 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-22 00:47:06 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								: with-lock ( lock quot -- )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    f swap with-lock-timeout ; inline
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 06:07:40 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								! Many-reader/single-writer locks
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								TUPLE: rw-lock readers writers reader# writer ;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								: <rw-lock> ( -- lock )
							 | 
						
					
						
							
								
									
										
										
										
											2008-04-13 16:06:27 -04:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    <dlist> <dlist> 0 f rw-lock boa ;
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 06:07:40 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								<PRIVATE
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2008-03-01 02:57:34 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								: add-reader ( lock -- )
							 | 
						
					
						
							
								
									
										
										
										
											2008-08-30 22:19:06 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    [ 1+ ] change-reader# drop ;
							 | 
						
					
						
							
								
									
										
										
										
											2008-03-01 02:57:34 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 17:20:18 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								: acquire-read-lock ( lock timeout -- )
							 | 
						
					
						
							
								
									
										
										
										
											2008-08-30 22:19:06 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    over writer>>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    [ 2dup >r readers>> r> "read lock" wait ] when drop
							 | 
						
					
						
							
								
									
										
										
										
											2008-03-01 02:57:34 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    add-reader ;
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 06:07:40 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								: notify-writer ( lock -- )
							 | 
						
					
						
							
								
									
										
										
										
											2008-08-30 22:19:06 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    writers>> notify-1 ;
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 06:07:40 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2008-03-01 02:57:34 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								: remove-reader ( lock -- )
							 | 
						
					
						
							
								
									
										
										
										
											2008-08-30 22:19:06 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    [ 1- ] change-reader# drop ;
							 | 
						
					
						
							
								
									
										
										
										
											2008-03-01 02:57:34 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 06:07:40 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								: release-read-lock ( lock -- )
							 | 
						
					
						
							
								
									
										
										
										
											2008-03-01 02:57:34 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    dup remove-reader
							 | 
						
					
						
							
								
									
										
										
										
											2008-08-30 22:19:06 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    dup reader#>> zero? [ notify-writer ] [ drop ] if ;
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 06:07:40 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 17:20:18 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								: acquire-write-lock ( lock timeout -- )
							 | 
						
					
						
							
								
									
										
										
										
											2008-08-30 22:19:06 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    over writer>> pick reader#>> 0 > or
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    [ 2dup >r writers>> r> "write lock" wait ] when drop
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    self >>writer drop ;
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 06:07:40 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								: release-write-lock ( lock -- )
							 | 
						
					
						
							
								
									
										
										
										
											2008-08-30 22:19:06 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    f >>writer
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    dup readers>> deque-empty?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    [ notify-writer ] [ readers>> notify-all ] if ;
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 06:07:40 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2008-03-01 02:57:34 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								: reentrant-read-lock-ok? ( lock -- ? )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    #! If we already have a write lock, then we can grab a read
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    #! lock too.
							 | 
						
					
						
							
								
									
										
										
										
											2008-08-30 22:19:06 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    writer>> self eq? ;
							 | 
						
					
						
							
								
									
										
										
										
											2008-03-01 02:57:34 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								: reentrant-write-lock-ok? ( lock -- ? )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    #! The only case where we have a writer and > 1 reader is
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    #! write -> read re-entrancy, and in this case we prohibit
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    #! a further write -> read -> write re-entrancy.
							 | 
						
					
						
							
								
									
										
										
										
											2008-08-30 22:19:06 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    { [ writer>> self eq? ] [ reader#>> zero? ] } 1&& ;
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 06:07:40 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								PRIVATE>
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-22 00:47:06 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								: with-read-lock-timeout ( lock timeout quot -- )
							 | 
						
					
						
							
								
									
										
										
										
											2008-03-01 02:57:34 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    pick reentrant-read-lock-ok? [
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        [ drop add-reader ] [ remove-reader ] do-lock
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ] [
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 06:07:40 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        [ acquire-read-lock ] [ release-read-lock ] do-lock
							 | 
						
					
						
							
								
									
										
										
										
											2008-03-01 02:57:34 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ] if ; inline
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 06:07:40 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-22 00:47:06 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								: with-read-lock ( lock quot -- )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    f swap with-read-lock-timeout ; inline
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								: with-write-lock-timeout ( lock timeout quot -- )
							 | 
						
					
						
							
								
									
										
										
										
											2008-03-01 02:57:34 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    pick reentrant-write-lock-ok? [ 2nip call ] [
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-18 06:07:40 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        [ acquire-write-lock ] [ release-write-lock ] do-lock
							 | 
						
					
						
							
								
									
										
										
										
											2008-03-01 02:57:34 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ] if ; inline
							 | 
						
					
						
							
								
									
										
										
										
											2008-02-22 00:47:06 -05:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								: with-write-lock ( lock quot -- )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    f swap with-write-lock-timeout ; inline
							 |