///|
priv struct Connection {
  conn : &@rt.Conn
  mut task : @async.Task[Unit]?
}

///|
priv struct ServerState {
  mut control : @control.Lifecycle
  connections : Map[Int64, Connection]
  changed : @cond_var.Cond
  mut stop_accept : (() -> Unit)?
  background : Map[Int64, @async.Task[Unit]?]
  mut next_id : Int64
}

///|
fn ServerState::new() -> ServerState {
  {
    control: @control.Lifecycle::new(),
    connections: {},
    changed: @cond_var.Cond(),
    stop_accept: None,
    background: {},
    next_id: 0L,
  }
}

///|
// Commit pure decisions before interpreting resource effects, including wakeups.
fn ServerState::step(self : ServerState, event : @control.ServerEvent) -> Bool {
  let change = self.control.step(event)
  self.control = change.state
  let mut accept_failure = false
  for action in change.actions {
    match action {
      StopAccept => if self.stop_accept is Some(stop) { stop() }
      CloseConnection(id) =>
        if self.connections.get(id) is Some(c) {
          c.conn.close()
        }
      CancelConnection(id) =>
        if self.connections.get(id) is Some(c) {
          if c.task is Some(task) {
            task.cancel()
          }
        }
      CancelBackground(id) =>
        if self.background.get(id) is Some(Some(task)) {
          task.cancel()
        }
      ReportAccept => accept_failure = true
    }
  }
  self.changed.broadcast()
  accept_failure
}