txt: ## dist_zef-raku-community-modules-Concurrent-Progress.md
  [![Actions Status](https://github.com/raku-community-modules/Concurrent-Progress/actions/workflows/linux.yml/badge.svg)](https://github.com/raku-community-modules/Concurrent-Progress/actions) [![Actions Status](https://github.com/raku-community-modules/Concurrent-Progress/actions/workflows/macos.yml/badge.svg)](https://github.com/raku-community-modules/Concurrent-Progress/actions) [![Actions Status](https://github.com/raku-community-modules/Concurrent-Progress/actions/workflows/windows.yml/badge.svg)](https://github.com/raku-community-modules/Concurrent-Progress/actions)
  
  # NAME
  
  Concurrent::Progress - Report on the progress of a concurrent operation
  
  # SYNOPSIS
  
  In the operation that should report progress, take `Concurrent::Progress` as a parameter (usually optional) and use it. If no instance is passed, then the method calls will be made on the type object, and will silently do nothing.
  
  ```
  use Concurrent::Progress;
  
  sub some-async-operation(Concurrent::Progress :$progress) {
      start {
          # Optionally set a target (get percentage completion
          # calculation for free).
          my @things-to-do = ...;
          $progress.set-target(@things-to-do.elems);
  
          # Can add 1 to the count of things completed.
          for @things-to-do {
              ...;
              $progress.increment();
          }
  
          # Or can add many.
          for @things-to-do.batch(5) -> @batch {
              ...;
              $progress.add(@batch.elems);
          }
  
          # Or can just set the value, if we're counting by ourselves.
          for @things-to-do.kv -> $idx, $obj {
              ...;
              $progress.set-value($idx + 1);
          }
      }
  }
  
  ```
  
  Meanwhile, in the caller (note that `whenever` automatically calls `Supply` on the `Concurrent::Progress` object):
  
  ```
  my $progress = Concurrent::Progress.new;
  react {
      whenever $progress -> $status {
          say "$status.value() / $status.target() ($status.percent()%)";
      }
  
      whenever some-async-operation(:$progress) {
          say "Completed";
      }
  }
  
  ```
  
  # DESCRIPTION
  
  It's fairly straightforward to wire up concurrent progress reporting in Raku: create a `Supplier`, use it to emit progress reports, and have things wishing to receive progress reports tap the `Supply`.
  
  That's exactly what this module does on this inside; it just saves some boilerplate and helps get a little more intent into the code. It is best suited to cases where "N out of M"-style progress reports are desired, where N reaching M indicates completion. However, it may be used in cases where there is no target also.
  
  # CONSTRUCTION
  
  A `Concurrent::Progress` instance will usually be constructed by the initiator of an asynchronous operation. No options are required, but the following may be provided:
  
  ## auto-done
  
  Automatically emits a `done` message on the `Supply` of progress reports when the current value reaches the target. This means a `whenever` will complete (which is why the `react` block in the synopsis example terminates). Defaults to `True`. Note this isi only applicable if `set-target` is called.
  
  ## min-interval
  
  The minimum time interval between progress updates. Can be provided as a `Real` (`Int`, `Rat`, `Duration`, etc.) If provided, then there will be at most one update per the specified time interval (so, passing 1 means at most one update per second). If this option is not specified, then every progress report will be emitted.
  
  # Methods for reporting progress
  
  The following methods may be called to report progress:
  
  ## set-target(Int $target)
  
  Sets the target to be reached to indicate completion. In many cases, where the total amount of work is known up-front, then this will be called once. Calling it allows automatic computation of the percentage complete in progress reports; if it is not called, then the percentage complete will be undefined. It is allowed to call `set-target` multiple times if there is a "moving target", but if using `auto-done` then it is up to you to ensure the value never reaches the target prematurely.
  
  ## add-target(Int $amount)
  
  Adds a specific value to the current target.
  
  ## increment-target()
  
  Increments the target value by one.
  
  ## set-value(Int $value)
  
  Sets the current value included in progress reports, and triggers emitting a progress report if appropriate.
  
  ## increment
  
  Adds 1 to the current value. It is safe to make multiple concurrent calls to `increment` (making this highly convenient for divide and conquer style code).
  
  ## add(Int $n)
  
  Adds `$n` to the current value. As with `increment`, multiple concurrent calls are safe.
  
  # Methods for receiving progress reports
  
  Progress reports are delivered using a `Supply`. This is a *live* `Supply`, so if it matters that you receive every progress report then be sure to tap it prior to starting the work.
  
  The `Supply` method is used to obtain the `Supply` of progress reports (which means a `Concurrent::Progress` object may be usedi directly with `whenever`).
  
  The `Supply` will `emit` instances of `Concurrent::Progress::Report`, which has the following properties:
  
  ## value
  
  The current value (which will typically correspond to items processed, bytes download/uploaded, etc.)
  
  ## target
  
  If set, the target to which the `value` property is working (total items to process, total bytes to be downloaded/uploaded, etc.)
  
  ## percent
  
  If `target` is defined, then `(100 * $.value / $.target).Int`; if not, then an `Int` type object will be returned.
  
  Provided `auto-done` was not disabled at construction time, then a `done` will be sent when `value` reaches `target`.
  
  It is also possible to pass `auto-done` and `min-interval` to the `Supply` method, in order to override them on a per-Supply basis. This may be useful if you did not have control over the creation of the `Concurrent::Progress` instance.
  
  # AUTHOR
  
  Jonathan Worthington
  
  # COPYRIGHT AND LICENSE
  
  Copyright 2017 - 2024 Jonathan Worthington
  
  Copyright 2024 Raku Community
  
  This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.
  