///|
/// Opaque handle of one listener registration. `cancel` is idempotent and
/// releases the handler reference; a handle whose runtime is gone cancels to
/// a no-op.
///
/// # Example
/// ```mbt check
/// test {
///   let cancels = Ref(0)
///   let subscription = @events.Subscription::from_cancel(fn() {
///     cancels.val = cancels.val + 1
///   })
///   subscription.cancel()
///   subscription.cancel()
///   assert_eq(cancels.val, 1)
/// }
/// ```
pub struct Subscription {
  priv cancel_ : () -> Unit
  priv active : Ref[Bool]
}

///|
/// Framework construction hook. Product code receives subscriptions from
/// `Events::subscribe` and does not need this constructor.
pub fn Subscription::from_cancel(cancel : () -> Unit) -> Subscription {
  { cancel_: cancel, active: Ref(true), }
}

///|
pub fn Subscription::cancel(self : Subscription) -> Unit {
  if self.active.val {
    self.active.val = false
    (self.cancel_)()
  }
}