@@ -20,7 +20,7 @@ class MetamodelX::MonitorHOW is Metamodel::ClassHOW {
2020 }
2121
2222 method add_method (Mu \type, $ name , $ meth ) {
23- $ name ne ' BUILDALL' && $ meth . wrap (-> \SELF, | {
23+ ! ( $ name eq ' BUILDALL' | ' POPULATE ' ) && $ meth . wrap (-> \SELF, | {
2424 if SELF. DEFINITE {
2525 # Instance method call; acquire lock.
2626 my $ * MONITOR := SELF;
@@ -65,12 +65,20 @@ class MetamodelX::MonitorHOW is Metamodel::ClassHOW {
6565 callsame ();
6666 };
6767 }
68+ elsif self . method_table(type)<POPULATE >: exists {
69+ self . method_table(type)<POPULATE >. wrap : -> \SELF, | {
70+ $ ! lock-attr . set_value(SELF, Lock . new );
71+ callsame ();
72+ };
73+ }
6874 else {
6975 my $ lock-attr := $ ! lock-attr ;
70- self . add_method(type, ' BUILDALL ' , anon method BUILDALL (Mu \SELF: | ) {
76+ my $ method := anon method POPULATE (Mu \SELF: | ) {
7177 $ lock-attr . set_value(SELF, Lock . new );
7278 callsame ();
73- });
79+ }
80+ self . add_method(type, ' BUILDALL' , $ method );
81+ self . add_method(type, ' POPULATE' , $ method );
7482 }
7583 self . Metamodel ::ClassHOW::compose(type);
7684 }
@@ -113,126 +121,4 @@ my package EXPORTHOW {
113121 }
114122}
115123
116- = begin pod
117-
118- = head1 NAME
119-
120- OO::Monitors - Objects with mutual exclusion and condition variables
121-
122- = head1 SYNOPSIS
123-
124- = begin code :lang<raku>
125-
126- use OO::Monitors;
127-
128- monitor Foo {
129- has $.bar
130-
131- # accessible by one thread at a time
132- method frobnicate() { }
133- }
134-
135- = end code
136-
137- = head1 DESCRIPTION
138-
139- A monitor provides per-instance mutual exclusion for objects. This means
140- that for a given object instance, only one thread can ever be inside its
141- methods at a time. This is achieved by a lock being associated with each
142- object. The lock is acquired automatically at the entry to each method
143- in the monitor. Condition variables are also supported.
144-
145- = head2 Basic Usage
146-
147- A monitor looks like a normal class, but declared with the C < monitor > keyword.
148-
149- = begin code :lang<raku>
150-
151- use OO::Monitors;
152-
153- monitor IPFilter {
154- has %!active;
155- has %!blacklist;
156- has $.limit = 10;
157- has $.blocked = 0;
158-
159- method should-start-request($ip) {
160- if %!blacklist{$ip}
161- || (%!active{$ip} // 0) == $.limit {
162- $!blocked++;
163- return False;
164- }
165- else {
166- %!active{$ip}++;
167- return True;
168- }
169- }
170-
171- method end-request($ip) {
172- %!active{$ip}--;
173- }
174- }
175-
176- = end code
177-
178- That's about all there is to it. The monitor meta-object enforces mutual
179- exclusion.
180-
181- = head2 Conditions
182-
183- Condition variables are declared with the C < conditioned > trait on the
184- monitor. To wait on a condition, use C < wait-condition > . To signal that
185- a condition has been met, use C < meet-condition > . Here is an example of
186- a bounded queue.
187-
188- = begin code :lang<raku>
189-
190- monitor BoundedQueue is conditioned(<not-full not-empty>) {
191- has @!tasks;
192- has $.limit = die "Must specify a limit";
193-
194- method add-task($task) {
195- while @!tasks.elems == $!limit {
196- wait-condition <not-full>;
197- }
198- @!tasks.push($task);
199- meet-condition <not-empty>;
200- }
201-
202- method take-task() {
203- until @!tasks {
204- wait-condition <not-empty>;
205- }
206- meet-condition <not-full>;
207- return @!tasks.shift;
208- }
209- }
210-
211- = end code
212-
213- When C < wait-condition > is used, the lock is released and the thread
214- blocks until the condition is met by some other thread. By contrast,
215- C < meet-condition > just marks a waiting thread as unblocked, but retains
216- the lock until the method is over.
217-
218- = head2 Circular waiting
219-
220- Monitors are vulnerable to deadlock, if you set up a circular dependency. Keep
221- object graphs involving monitors simple and cycle-free, so far as is possible.
222-
223- = head1 AUTHOR
224-
225- Jonathan Worthington
226-
227- Source can be located at: https://github.com/raku-community-modules/OO-Monitors .
228- Comments and Pull Requests are welcome.
229-
230- = head1 COPYRIGHT AND LICENSE
231-
232- Copyright 2014 - 2021 Jonathan Worthington
233-
234- Copyright 2024 Raku Community
235-
236- This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.
237-
238- = end pod
124+ # vim: expandtab shiftwidth=4
0 commit comments