txt: ## lock.md
  class Lock
  
  A low-level, re-entrant, mutual exclusion lock
  
  ```raku
  class Lock {}
  ```
  
  A `Lock` is a low-level concurrency control construct. It provides mutual exclusion, meaning that only one thread may hold the lock at a time. Once the lock is unlocked, another thread may then lock it.
  
  A `Lock` is typically used to protect access to one or more pieces of state. For example, in this program:
  
  ```raku
  my $x = 0;
  my $l = Lock.new;
  await (^10).map: {
      start {
          $l.protect({ $x++ });
      }
  }
  say $x;         # OUTPUT: «10␤»
  ```
  
  The `Lock` is used to protect operations on `$x`. An increment is not an atomic operation; without the lock, it would be possible for two threads to both read the number 5 and then both store back the number 6, thus losing an update. With the use of the `Lock`, only one thread may be running the increment at a time.
  
  A `Lock` is re-entrant, meaning that a thread that holds the lock can lock it again without blocking. That thread must unlock the same number of times before the lock can be obtained by another thread (it works by keeping a recursion count).
  
  It's important to understand that there is no direct connection between a `Lock` and any particular piece of data; it is up to the programmer to ensure that the `Lock` is held during all operations that involve the data in question. The `OO::Monitors` module, while not a complete solution to this problem, does provide a way to avoid dealing with the lock explicitly and encourage a more structured approach.
  
  The `Lock` class is backed by operating-system provided constructs, and so a thread that is waiting to acquire a lock is, from the point of view of the operating system, blocked.
  
  Code using high-level Raku concurrency constructs should avoid using `Lock`. Waiting to acquire a `Lock` blocks a real [`Thread`](/type/Thread), meaning that the thread pool (used by numerous higher-level Raku concurrency mechanisms) cannot use that thread in the meantime for anything else.
  
  Any `await` performed while a `Lock` is held will behave in a blocking manner; the standard non-blocking behavior of `await` relies on the code following the `await` resuming on a different [`Thread`](/type/Thread) from the pool, which is incompatible with the requirement that a `Lock` be unlocked by the same thread that locked it. See [`Lock::Async`](/type/Lock/Async) for an alternative mechanism that does not have this shortcoming. Other than that, the main difference is that `Lock` mainly maps to operating system mechanisms, while [`Lock::Async`](/type/Lock/Async) uses Raku primitives to achieve similar effects. If you're doing low-level stuff (native bindings) and/or actually want to block real OS threads, use `Lock`. However, if you want a non-blocking mutual exclusion and don't need recursion and are running code on the Raku thread pool, use Lock::Async.
  
  By their nature, `Lock`s are not composable, and it is possible to end up with hangs should circular dependencies on locks occur. Prefer to structure concurrent programs such that they communicate results rather than modify shared data structures, using mechanisms like [`Promise`](/type/Promise), [`Channel`](/type/Channel) and [`Supply`](/type/Supply).
  
  # [Methods](#class_Lock "go to top of document")[§](#Methods "direct link")
  
  ## [method protect](#class_Lock "go to top of document")[§](#method_protect "direct link")
  
  ```raku
  multi method protect(Lock:D: &code)
  ```
  
  Obtains the lock, runs `&code`, and releases the lock afterwards. Care is taken to make sure the lock is released even if the code is left through an exception.
  
  Note that the `Lock` itself needs to be created outside the portion of the code that gets threaded and it needs to protect. In the first example below, `Lock` is first created and assigned to `$lock`, which is then used *inside* the [`Promise`](/type/Promise)s to protect the sensitive code. In the second example, a mistake is made: the `Lock` is created right inside the [`Promise`](/type/Promise), so the code ends up with a bunch of separate locks, created in a bunch of threads, and thus they don't actually protect the code we want to protect.
  
  ```raku
  # Right: $lock is instantiated outside the portion of the
  # code that will get threaded and be in need of protection
  my $lock = Lock.new;
  await ^20 .map: {
      start {
          $lock.protect: {
              print "Foo";
              sleep rand;
              say "Bar";
          }
      }
  }
  
  # !!! WRONG !!! Lock is created inside threaded area!
  await ^20 .map: {
      start {
          Lock.new.protect: {
              print "Foo"; sleep rand; say "Bar";
          }
      }
  }
  ```
  
  ## [method lock](#class_Lock "go to top of document")[§](#method_lock "direct link")
  
  ```raku
  method lock(Lock:D:)
  ```
  
  Acquires the lock. If it is currently not available, waits for it.
  
  ```raku
  my $l = Lock.new;
  $l.lock;
  ```
  
  Since a `Lock` is implemented using OS-provided facilities, a thread waiting for the lock will not be scheduled until the lock is available for it. Since `Lock` is re-entrant, if the current thread already holds the lock, calling `lock` will simply bump a recursion count.
  
  While it's easy enough to use the `lock` method, it's more difficult to correctly use [`unlock`](/type/Lock#method_unlock). Instead, prefer to use the [`protect`](/type/Lock#method_protect) method instead, which takes care of making sure the `lock`/`unlock` calls always both occur.
  
  ## [method unlock](#class_Lock "go to top of document")[§](#method_unlock "direct link")
  
  ```raku
  method unlock(Lock:D:)
  ```
  
  Releases the lock.
  
  ```raku
  my $l = Lock.new;
  $l.lock;
  $l.unlock;
  ```
  
  It is important to make sure the `Lock` is always released, even if an exception is thrown. The safest way to ensure this is to use the [`protect`](/type/Lock#method_protect) method, instead of explicitly calling `lock` and `unlock`. Failing that, use a `LEAVE` phaser.
  
  ```raku
  my $l = Lock.new;
  {
      $l.lock;
      LEAVE $l.unlock;
  }
  ```
  
  ## [method condition](#class_Lock "go to top of document")[§](#method_condition "direct link")
  
  ```raku
  method condition(Lock:D: )
  ```
  
  Returns a condition variable as a [`Lock::ConditionVariable`](/type/Lock/ConditionVariable) object. Check [this article](https://web.stanford.edu/~ouster/cgi-bin/cs140-spring14/lecture.php?topic=locks) or [the Wikipedia](https://en.wikipedia.org/wiki/Monitor_%28synchronization%29) for background on condition variables and how they relate to locks and mutexes.
  
  ```raku
  my $l = Lock.new;
  $l.condition;
  ```
  
  You should use a condition over a lock when you want an interaction with it that is a bit more complex than simply acquiring or releasing the lock.
  
  ```raku
  constant ITEMS = 100;
  my $lock = Lock.new;
  my $cond = $lock.condition;
  my $todo = 0;
  my $done = 0;
  my @in = 1..ITEMS;
  my @out = 0 xx ITEMS;
  
  loop ( my $i = 0; $i < @in; $i++ ) {
      my $in := @in[$i];
      my $out := @out[$i];
      Thread.start( {
        my $partial = $in² +1;
        if $partial.is-prime {
            $out = $partial but "Prime";
        } else {
            $out = $partial;
        }
        $lock.protect( {
           $done++;
           $cond.signal if $done == $todo;
        } );
      } );
      $todo++;
  }
  $lock.protect( {
      $cond.wait({  $done == $todo } );
  });
  
  say @out.map: { $_.^roles > 2 ?? $_.Num ~ "*" !! $_ };
  # OUTPUT: «2* 5* 10 17* 26 37* 50 65 82 101* … »
  
  ```
  
  In this case, we use the condition variable `$cond` to wait until all numbers have been generated and checked and also to `.signal` to another thread to wake up when the particular thread is done.
  
  # [Typegraph](# "go to top of document")[§](#typegraphrelations "direct link")
  
  Type relations for `Lock`
  
  
  
  raku-type-graph
  
  
  
  Lock
  Lock
  
  
  Any
  Any
  
  
  Lock->Any
  
  
  
  Mu
  Mu
  
  
  Any->Mu
  
  [Expand chart above](/assets/typegraphs/Lock.svg)
  