# OO::Monitors A monitor provides per-instance mutual exclusion for objects. This means that for a given object instance, only one thread can ever be inside its methods at a time. This is achieved by a lock being associated with each object. The lock is acquired automatically at the entry to each method in the monitor. Condition variables are also supported. ## Basic Usage A monitor looks like a normal class, but declared with the `monitor` keyword. use OO::Monitors; monitor IPFilter { has %!active; has $.limit = 10; has $.blocked = 0; method should-start-request($ip) { if %!blacklist{$ip} || (%!active{$ip} // 0) == $.limit { $!blocked++; return False; } else { %!active{$ip}++; return True; } } method end-request($ip) { %!active{$ip}--; } } That's about all there is to it. The monitor meta-object enforces mutual exclusion. ## Conditions Condition variables are declared with the `conditioned` trait on the monitor. To wait on a condition, use `wait-condition`. To signal that a condition has been met, use `meet-condition`. Here is an example of a bounded queue. monitor BoundedQueue is conditioned(< not-full not-empty >) { has @!tasks; has $.limit = die "Must specify a limit"; method add-task($task) { while @!tasks.elems == $!limit { wait-condition ; } @!tasks.push($task); meet-condition ; } method take-task() { until @!tasks { wait-condition ; } meet-condition ; return @!tasks.shift; } } When `wait-conditon` is used, the lock is released and the thread blocks until the condition is met by some other thread. By contrast, `meet-condition` just marks a waiting thread as unblocked, but retains the lock until the method is over. ## Circular waiting Monitors are vulnerable to deadlock, if you set up a circular dependency. Keep object graphs involving monitors simple and cycle-free, so far as is possible.