Revision: | 1.37 |
Committed: | Fri Dec 1 02:17:37 2006 UTC (17 years, 6 months ago) by root |
Branch: | MAIN |
CVS Tags: | rel-4_22, rel-4_21, rel-4_0, rel-4_3, rel-3_41, rel-4_13, rel-4_11, rel-3_55, rel-3_51, rel-4_01, rel-4_03, rel-4_02, rel-3_6, rel-3_62, rel-3_63, rel-3_61, rel-3_4, rel-3_1, rel-3_5, rel-3_3, rel-3_2, rel-3_0, rel-3_01, rel-4_50, rel-4_51, rel-4_4, rel-3_11, rel-4_45, rel-4_49, rel-4_48, rel-4_1, rel-4_2, rel-4_47, rel-4_46, rel-3_501, rel-4_31, rel-4_32, rel-4_33, rel-4_34, rel-4_35, rel-4_36, rel-4_37 |
Changes since 1.36: | +2 -2 lines |
Log Message: | *** empty log message *** |
# | Content |
---|---|
1 | =head1 NAME |
2 | |
3 | Coro::RWLock - reader/write locks |
4 | |
5 | =head1 SYNOPSIS |
6 | |
7 | use Coro::RWLock; |
8 | |
9 | $lck = new Coro::RWLock; |
10 | |
11 | $lck->rdlock; # acquire read lock |
12 | |
13 | $lck->unlock; |
14 | |
15 | =head1 DESCRIPTION |
16 | |
17 | This module implements reader/write locks. A read can be acquired for |
18 | read by many coroutines in parallel as long as no writer has locked it |
19 | (shared access). A single write lock can be acquired when no readers |
20 | exist. RWLocks basically allow many concurrent readers (without writers) |
21 | OR a single writer (but no readers). |
22 | |
23 | =over 4 |
24 | |
25 | =cut |
26 | |
27 | package Coro::RWLock; |
28 | |
29 | BEGIN { eval { require warnings } && warnings->unimport ("uninitialized") } |
30 | |
31 | use Coro (); |
32 | |
33 | $VERSION = 1.9; |
34 | |
35 | =item $l = new Coro::RWLock; |
36 | |
37 | Create a new reader/writer lock. |
38 | |
39 | =cut |
40 | |
41 | sub new { |
42 | # [rdcount, [readqueue], wrcount, [writequeue]] |
43 | bless [0, [], 0, []], $_[0]; |
44 | } |
45 | |
46 | =item $l->rdlock |
47 | |
48 | Acquire a read lock. |
49 | |
50 | =item $l->tryrdlock |
51 | |
52 | Try to acquire a read lock. |
53 | |
54 | =cut |
55 | |
56 | sub rdlock { |
57 | while ($_[0][0]) { |
58 | push @{$_[0][3]}, $Coro::current; |
59 | &Coro::schedule; |
60 | } |
61 | ++$_[0][2]; |
62 | } |
63 | |
64 | sub tryrdlock { |
65 | return if $_[0][0]; |
66 | ++$_[0][2]; |
67 | } |
68 | |
69 | =item $l->wrlock |
70 | |
71 | Acquire a write lock. |
72 | |
73 | =item $l->trywrlock |
74 | |
75 | Try to acquire a write lock. |
76 | |
77 | =cut |
78 | |
79 | sub wrlock { |
80 | while ($_[0][0] || $_[0][2]) { |
81 | push @{$_[0][1]}, $Coro::current; |
82 | &Coro::schedule; |
83 | } |
84 | ++$_[0][0]; |
85 | } |
86 | |
87 | sub trywrlock { |
88 | return if $_[0][0] || $_[0][2]; |
89 | ++$_[0][0]; |
90 | } |
91 | |
92 | =item $l->unlock |
93 | |
94 | Give up the rwlock. |
95 | |
96 | =cut |
97 | |
98 | sub unlock { |
99 | # either we are a reader or a writer. decrement accordingly. |
100 | if ($_[0][2]) { |
101 | return if --$_[0][2]; |
102 | } else { |
103 | $_[0][0]--; |
104 | } |
105 | # now we have the choice between waking up a reader or a writer. we choose the writer. |
106 | if (@{$_[0][1]}) { |
107 | (shift @{$_[0][1]})->ready; |
108 | } elsif (@{$_[0][3]}) { |
109 | (shift @{$_[0][3]})->ready; |
110 | } |
111 | } |
112 | |
113 | 1; |
114 | |
115 | =back |
116 | |
117 | =head1 AUTHOR |
118 | |
119 | Marc Lehmann <schmorp@schmorp.de> |
120 | http://home.schmorp.de/ |
121 | |
122 | =cut |
123 |