<commit_before>//
//  Async.swift
//  BrightFutures
//
//  Created by <NAME> on 09/07/15.
//  Copyright © 2015 <NAME>. All rights reserved.
//

import Foundation

public class Async<Value>: AsyncType {

    typealias CompletionCallback = Value -> ()
    
    public private(set) var value: Value? {
        willSet {
            assert(value == nil)
        }
        
        didSet {
            assert(value != nil)
            try! runCallbacks()
        }
    }
    
    /// This queue is used for all callback related administrative tasks
    /// to prevent that a callback is added to a completed future and never
    /// executed or perhaps excecuted twice.
    private let queue = Queue()

    /// Upon completion of the future, all callbacks are asynchronously scheduled to their
    /// respective execution contexts (which is either given by the client or returned from
    /// DefaultThreadingModel). Inside the context, this semaphore will be used
    /// to make sure that all callbacks are executed serially.
    private let callbackExecutionSemaphore = Semaphore(value: 1);
    private var callbacks = [CompletionCallback]()
    
    public required init() {
        
    }
    
    public required init(value: Value) {
        self.value = value
    }
    
    public required init<A: AsyncType where A.Value == Value>(other: A) {
        completeWith(other)
    }
    
    private func runCallbacks() throws {
        guard let result = self.value else {
            throw BrightFuturesError<NoError>.IllegalState
        }
        
        for callback in self.callbacks {
            callback(result)
        }
        
        self.callbacks.removeAll()
    }
    
    public func complete(value: Value) throws {
        try queue.sync {
            print("attempting to complete \(self)")
            guard self.value == nil else {
                throw BrightFuturesError<NoError>.IllegalState
            }
            
            self.value = value
        }
    }
    
    /// `true` if the future completed (either `isSuccess` or `isFailure` will be `true`)
    public var isCompleted: Bool {
        return self.value != nil
    }
    
    /// Adds the given closure as a callback for when the Async completes. The closure is executed on the given context.
    /// If no context is given, the behavior is defined by the default threading model (see README.md)
    /// Returns self
    public func onComplete(context c: ExecutionContext = DefaultThreadingModel(), callback: Value -> ()) -> Self {
        let wrappedCallback : Value -> () = { value in
            c {
                self.callbackExecutionSemaphore.execute {
                    print("calling back with value \(value)")
                    callback(value)
                    print("done calling back")
                }
                return
            }
        }
        <commit_msg>removed logging<commit_after>//
//  Async.swift
//  BrightFutures
//
//  Created by <NAME> on 09/07/15.
//  Copyright © 2015 <NAME>. All rights reserved.
//

import Foundation

public class Async<Value>: AsyncType {

    typealias CompletionCallback = Value -> ()
    
    public private(set) var value: Value? {
        willSet {
            assert(value == nil)
        }
        
        didSet {
            assert(value != nil)
            try! runCallbacks()
        }
    }
    
    /// This queue is used for all callback related administrative tasks
    /// to prevent that a callback is added to a completed future and never
    /// executed or perhaps excecuted twice.
    private let queue = Queue()

    /// Upon completion of the future, all callbacks are asynchronously scheduled to their
    /// respective execution contexts (which is either given by the client or returned from
    /// DefaultThreadingModel). Inside the context, this semaphore will be used
    /// to make sure that all callbacks are executed serially.
    private let callbackExecutionSemaphore = Semaphore(value: 1);
    private var callbacks = [CompletionCallback]()
    
    public required init() {
        
    }
    
    public required init(value: Value) {
        self.value = value
    }
    
    public required init<A: AsyncType where A.Value == Value>(other: A) {
        completeWith(other)
    }
    
    private func runCallbacks() throws {
        guard let result = self.value else {
            throw BrightFuturesError<NoError>.IllegalState
        }
        
        for callback in self.callbacks {
            callback(result)
        }
        
        self.callbacks.removeAll()
    }
    
    public func complete(value: Value) throws {
        try queue.sync {
            guard self.value == nil else {
                throw BrightFuturesError<NoError>.IllegalState
            }
            
            self.value = value
        }
    }
    
    /// `true` if the future completed (either `isSuccess` or `isFailure` will be `true`)
    public var isCompleted: Bool {
        return self.value != nil
    }
    
    /// Adds the given closure as a callback for when the Async completes. The closure is executed on the given context.
    /// If no context is given, the behavior is defined by the default threading model (see README.md)
    /// Returns self
    public func onComplete(context c: ExecutionContext = DefaultThreadingModel(), callback: Value -> ()) -> Self {
        let wrappedCallback : Value -> () = { value in
            c {
                self.callbackExecutionSemaphore.execute {
                    callback(value)
                }
                return
            }
        }
        
{'fraction_non_alphanumeric': 0.08376403493138478, 'fraction_numerical': 0.003920869720192479, 'mean_word_length': 1.8286290322580645, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3275019', 'n_tokens_mistral': 1452, 'n_tokens_neox': 1411, 'n_words': 505}