<commit_before>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

import Foundation
import FBControlCore

/**
 A Protocol for defining
 */
protocol Relay {
  func start() throws
  func stop() throws
}

/**
 A Relay that composes multiple relays.
 */
class CompositeRelay : Relay {
  let relays: [Relay]

  init(relays: [Relay]) {
    self.relays = relays
  }

  func start() throws {
    for relay in self.relays {
      try relay.start()
    }
  }

  func stop() throws {
    for relay in self.relays {
      // We want to stop all relays, so ignoring error propogation will ensure we clean up all of them.
      try? relay.stop()
    }
  }
}

/**
 Wraps an existing Relay, spinning the run loop after the underlying relay has started.
 */
class SynchronousRelay : Relay {
  let relay: Relay
  let reporter: EventReporter
  let continuation: FBiOSTargetContinuation?
  let started: () -> Void

  init(relay: Relay, reporter: EventReporter, continuation: FBiOSTargetContinuation?, started: @escaping () -> Void) {
    self.relay = relay
    self.reporter = reporter
    self.continuation = continuation
    self.started = started
  }

  func start() throws {
    // Start the Relay and notify consumers.
    try self.relay.start()
    self.started()

    var futures: [FBFuture<NSNull>] = []
    if let completedFuture = self.continuation?.completed {
      futures.append(completedFuture)
    }
    let signalFuture = SignalHandler.future.onQueue(DispatchQueue.main, map: { info in
      self.reporter.reportSimple(.signalled, .discrete, info)
      return NSNull()
    }) as! FBFuture<NSNull>
    futures.append(signalFuture)
    let _ = try FBFuture(race: futures).await()
  }

  func stop() throws {
    try self.relay.stop()
  }
}

/**
 Bridges an Action Reader to a Relay
 */
extension FBiOSActionReader : Relay {
  func start() throws {
    try self.startListening().await()
  }

  func stop() throws {
    try self.stopListening().await()
  }
}<commit_msg>Wait for Cancellation in Continuations<commit_after>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

import Foundation
import FBControlCore

/**
 A Protocol for defining
 */
protocol Relay {
  func start() throws
  func stop() throws
}

/**
 A Relay that composes multiple relays.
 */
class CompositeRelay : Relay {
  let relays: [Relay]

  init(relays: [Relay]) {
    self.relays = relays
  }

  func start() throws {
    for relay in self.relays {
      try relay.start()
    }
  }

  func stop() throws {
    for relay in self.relays {
      // We want to stop all relays, so ignoring error propogation will ensure we clean up all of them.
      try? relay.stop()
    }
  }
}

/**
 Wraps an existing Relay, spinning the run loop after the underlying relay has started.
 */
class SynchronousRelay : Relay {
  let relay: Relay
  let reporter: EventReporter
  let continuation: FBiOSTargetContinuation?
  let started: () -> Void

  init(relay: Relay, reporter: EventReporter, continuation: FBiOSTargetContinuation?, started: @escaping () -> Void) {
    self.relay = relay
    self.reporter = reporter
    self.continuation = continuation
    self.started = started
  }

  func start() throws {
    // Start the Relay and notify consumers.
    try self.relay.start()
    self.started()

    // Construct the futures, whichever completes first will cause the await to break.
    var futures: [FBFuture<NSNull>] = []
    if let completedFuture = self.continuation?.completed {
      futures.append(completedFuture)
    }
    let signalFuture = SignalHandler.future.onQueue(DispatchQueue.main, map: { info in
      self.reporter.reportSimple(.signalled, .discrete, info)
      return NSNull()
    }) as! FBFuture<NSNull>
    futures.append(signalFuture)
    let _ = try FBFuture(race: futures).await()

    // If there's an async cancellation, we can ensure that we wait for it to finish.
    if let completedFuture = self.continuation?.completed, completedFuture.state == .completedWithCancellation {
      let _ = try completedFuture.cancel().await()
    }
  }

  func stop() throws {
    try self.relay.stop()
  }
}

/**
 Bridges an Action Reader to a Relay
 */
extension FBiOSActionReader : Relay {
  func start() throws {
    try self.startListening().await()
  }

  func stop() throws {
    try self.stopListening().await()
  }
}
{'fraction_non_alphanumeric': 0.09906542056074766, 'fraction_numerical': 0.0016614745586708203, 'mean_word_length': 3.10221465076661, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '365811', 'n_tokens_mistral': 1494, 'n_tokens_neox': 1433, 'n_words': 490}