sig
  module Down :
    sig
      type ('a, 'b) t = { tick : unit Join.chan; wait : unit -> unit; }
      val create : int -> ('a, 'b) JoinCount.Down.t
    end
  module Collector :
    sig
      type ('a, 'b) t = { collect : 'a Join.chan; wait : unit -> 'b; }
      val create :
        ('a -> 'b -> 'b) -> 'b -> int -> ('a, 'b) JoinCount.Collector.t
    end
  module Dynamic :
    sig
      type ('a, 'b) t = {
        enter : unit -> unit;
        leave : 'a Join.chan;
        wait : unit -> 'b;
        finished : unit Join.chan;
      }
      val create : ('a -> 'b -> 'b) -> 'b -> ('a, 'b) JoinCount.Dynamic.t
    end
  module Monitor :
    sig
      type key
      type ('a, 'b, 'c) t = {
        enter : 'a -> JoinCount.Monitor.key;
        leave : JoinCount.Monitor.key * 'b -> unit;
        is_pending : JoinCount.Monitor.key -> bool;
        get_pendings : unit -> (JoinCount.Monitor.key * 'a) list;
        wait : unit -> 'c;
        finished : unit Join.chan;
      }
      val create : ('a -> 'b -> 'b) -> 'b -> ('c, 'a, 'b) JoinCount.Monitor.t
    end
end