2008-02-18 06:07:40 -05:00
|
|
|
! Copyright (C) 2008 Slava Pestov.
|
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
2008-02-18 10:08:59 -05:00
|
|
|
USING: dlists kernel threads continuations math
|
|
|
|
concurrency.conditions ;
|
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 )
|
|
|
|
<dlist> f f lock construct-boa ;
|
|
|
|
|
|
|
|
: <reentrant-lock> ( -- lock )
|
|
|
|
<dlist> f t lock construct-boa ;
|
2008-02-18 06:07:40 -05:00
|
|
|
|
|
|
|
<PRIVATE
|
|
|
|
|
2008-02-18 10:08:59 -05:00
|
|
|
: acquire-lock ( lock timeout -- )
|
|
|
|
over lock-owner
|
2008-02-19 15:38:02 -05:00
|
|
|
[ 2dup >r lock-threads r> "lock" wait ] when drop
|
2008-02-18 06:07:40 -05:00
|
|
|
self swap set-lock-owner ;
|
|
|
|
|
|
|
|
: release-lock ( lock -- )
|
|
|
|
f over set-lock-owner
|
|
|
|
lock-threads notify-1 ;
|
|
|
|
|
2008-02-18 10:08:59 -05:00
|
|
|
: do-lock ( lock timeout quot acquire release -- )
|
2008-02-18 17:20:18 -05:00
|
|
|
>r swap compose pick >r 2curry r> r> curry [ ] cleanup ;
|
|
|
|
inline
|
|
|
|
|
|
|
|
: (with-lock) ( lock timeout quot -- )
|
|
|
|
[ acquire-lock ] [ release-lock ] do-lock ; inline
|
2008-02-18 06:07:40 -05:00
|
|
|
|
|
|
|
PRIVATE>
|
|
|
|
|
2008-02-18 10:08:59 -05:00
|
|
|
: with-lock ( lock timeout quot -- )
|
2008-02-18 17:20:18 -05:00
|
|
|
pick lock-reentrant? [
|
|
|
|
pick lock-owner self eq? [
|
|
|
|
2nip call
|
|
|
|
] [
|
|
|
|
(with-lock)
|
|
|
|
] if
|
|
|
|
] [
|
|
|
|
(with-lock)
|
|
|
|
] if ; inline
|
2008-02-18 06:07:40 -05:00
|
|
|
|
|
|
|
! Many-reader/single-writer locks
|
|
|
|
TUPLE: rw-lock readers writers reader# writer ;
|
|
|
|
|
|
|
|
: <rw-lock> ( -- lock )
|
|
|
|
<dlist> <dlist> 0 f rw-lock construct-boa ;
|
|
|
|
|
|
|
|
<PRIVATE
|
|
|
|
|
2008-02-18 17:20:18 -05:00
|
|
|
: acquire-read-lock ( lock timeout -- )
|
|
|
|
over rw-lock-writer
|
2008-02-19 15:38:02 -05:00
|
|
|
[ 2dup >r rw-lock-readers r> "read lock" wait ] when drop
|
2008-02-18 06:07:40 -05:00
|
|
|
dup rw-lock-reader# 1+ swap set-rw-lock-reader# ;
|
|
|
|
|
|
|
|
: notify-writer ( lock -- )
|
2008-02-18 10:08:59 -05:00
|
|
|
rw-lock-writers notify-1 ;
|
2008-02-18 06:07:40 -05:00
|
|
|
|
|
|
|
: release-read-lock ( lock -- )
|
|
|
|
dup rw-lock-reader# 1- dup pick set-rw-lock-reader#
|
2008-02-18 10:08:59 -05:00
|
|
|
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 -- )
|
|
|
|
over rw-lock-writer pick rw-lock-reader# 0 > or
|
2008-02-19 15:38:02 -05:00
|
|
|
[ 2dup >r rw-lock-writers r> "write lock" wait ] when drop
|
2008-02-18 10:08:59 -05:00
|
|
|
self swap set-rw-lock-writer ;
|
2008-02-18 06:07:40 -05:00
|
|
|
|
|
|
|
: release-write-lock ( lock -- )
|
|
|
|
f over set-rw-lock-writer
|
|
|
|
dup rw-lock-readers dlist-empty?
|
|
|
|
[ notify-writer ] [ rw-lock-readers notify-all ] if ;
|
|
|
|
|
2008-02-18 17:20:18 -05:00
|
|
|
: do-reentrant-rw-lock ( lock timeout quot quot' -- )
|
2008-02-18 10:08:59 -05:00
|
|
|
>r pick rw-lock-writer self eq? [ 2nip call ] r> if ; inline
|
2008-02-18 06:07:40 -05:00
|
|
|
|
|
|
|
PRIVATE>
|
|
|
|
|
2008-02-18 10:08:59 -05:00
|
|
|
: with-read-lock ( lock timeout quot -- )
|
2008-02-18 06:07:40 -05:00
|
|
|
[
|
|
|
|
[ acquire-read-lock ] [ release-read-lock ] do-lock
|
2008-02-18 17:20:18 -05:00
|
|
|
] do-reentrant-rw-lock ; inline
|
2008-02-18 06:07:40 -05:00
|
|
|
|
2008-02-18 10:08:59 -05:00
|
|
|
: with-write-lock ( lock timeout quot -- )
|
2008-02-18 06:07:40 -05:00
|
|
|
[
|
|
|
|
[ acquire-write-lock ] [ release-write-lock ] do-lock
|
2008-02-18 17:20:18 -05:00
|
|
|
] do-reentrant-rw-lock ; inline
|