<commit_before>//
//  BriskAsync2Sync.swift
//  Brisk
//
//  Created by <NAME> on 8/12/16.
//  Copyright © 2016 <NAME>. All rights reserved.
//

import Foundation

// let .. = <-{ func(i, handler: $0) }              call func on current queue
// let .. = <~{ func(i, handler: $0) }              call func on bg queue
// let .. = <+{ func(i, handler: $0) }              call func on main queue
// let .. = <~myQueue ~~ { func(i, handler: $0) }   call func on specified queue

prefix operator <- {}
prefix operator <~ {}
prefix operator <+ {}
infix  operator ~~ { precedence 95 }


/// Returns the queue this prefix is applied to.  This is used to prettify the
/// syntax:
///
/// - e.g.: let x = <~myQueue ~~ { func(i, handler: $0) }
@inline(__always) public prefix func <~(q: dispatch_queue_t) -> dispatch_queue_t {
    return q
}

/// Executes the attached operation synchronously on the current queue
/// and waits for it to complete.  Returns the result of the callback handler that
/// $0 was attached to.
///
/// - e.g.: ```let x = <-{ func(i, callback: $0)``` }
public prefix func <-<O>(@noescape operation: (callbackHandler: (param: O) -> ()) -> ()) -> O {
    
    // This value will eventually hold the response from the async function
    var handledResponse: O?
    
    // This is the async group we'll use to wait for a response
    let group = dispatch_group_create()
    
    let theHandler: (p: O) -> () = { responseFromCallback in
        handledResponse = responseFromCallback
        dispatch_group_leave(group)
    }
    
    dispatch_group_enter(group)
    operation(callbackHandler: theHandler)
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER)
    
    // It's ok to use ! -- theoretically we are garanteed that handledResponse
    // has been set by this point (inside theHandler)
    return handledResponse!
}

/// Using a generic handler for the non-noescape versions
@inline(__always) private func processAsync2Sync<O>(operation: (callbackHandler: (param: O) -> ()) -> (),
                                                        queue: dispatch_queue_t) -> O {
    
    // This value will eventually hold the response from the async function
    var handledResponse: O?
    
    // This is the async group we'll use to wait for a response
    let group = dispatch_group_create()
    
    let theHandler: (p: O) -> () = { responseFromCallback in
        handledResponse = responseFromCallback
        dispatch_group_leave(group)
    }
    
    dispatch_group_enter(group)
    
    dispatch_async(queue) {
        operation(callbackHandler: theHandler)
    }
    
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER)
    
    // It's ok to use ! -- theoretically we are garanteed that handledResponse
    // has been set by this point (inside theHandler)
    return handledResponse!
}


/// Executes the attached operation on the general concurrent background queue
/// and waits for it to complete.  Returns the result of the callback handler that
/// $0 was attached to.
///
/// - e.g.: ```let x = <~{ func(i, callback: $0)``` }
public prefix func <~<O>(operation: (callbackHandler: (param: O) -> ()) -> ()) -> O {
    return processAsync2Sync(operation, queue: backgroundQueue)
}


/// Executes the attached operation on the main queue
/// and waits for it to complete.  Returns the result of the callback handler that
/// $0 was attached to.
///
/// - e.g.: ```let x = <+{ func(i, callback: $0)``` }
public prefix func <+<O>(operation: (callbackHandler: (param: O) -> ()) -> ()) -> O {
    return processAsync2Sync(operation, queue: mainQueue)
}


/// Executes the attached operation on the supplied queue from the left side
/// and waits for it to complete.  Returns the result of the callback handler that
/// $0 was attached to.
///<commit_msg>use briskgate<commit_after>//
//  BriskAsync2Sync.swift
//  Brisk
//
//  Created by <NAME> on 8/12/16.
//  Copyright © 2016 <NAME>. All rights reserved.
//

import Foundation

// let .. = <-{ func(i, handler: $0) }              call func on current queue
// let .. = <~{ func(i, handler: $0) }              call func on bg queue
// let .. = <+{ func(i, handler: $0) }              call func on main queue
// let .. = <~myQueue ~~ { func(i, handler: $0) }   call func on specified queue

prefix operator <- {}
prefix operator <~ {}
prefix operator <+ {}
infix  operator ~~ { precedence 95 }


/// Returns the queue this prefix is applied to.  This is used to prettify the
/// syntax:
///
/// - e.g.: let x = <~myQueue ~~ { func(i, handler: $0) }
@inline(__always) public prefix func <~(q: dispatch_queue_t) -> dispatch_queue_t {
    return q
}

/// Executes the attached operation synchronously on the current queue
/// and waits for it to complete.  Returns the result of the callback handler that
/// $0 was attached to.
///
/// - e.g.: ```let x = <-{ func(i, callback: $0)``` }
public prefix func <-<O>(@noescape operation: (callbackHandler: (param: O) -> ()) -> ()) -> O {
    
    // Our gating mechanism
    let gate = BriskGate()
    
    // This value will eventually hold the response from the async function
    var handledResponse: O?
    
    let theHandler: (p: O) -> () = { responseFromCallback in
        handledResponse = responseFromCallback
        gate.signal()
    }
    
    operation(callbackHandler: theHandler)
    gate.wait()
    
    // It's ok to use ! -- theoretically we are garanteed that handledResponse
    // has been set by this point (inside theHandler)
    return handledResponse!
}

/// Using a generic handler for the non-noescape versions
@inline(__always) private func processAsync2Sync<O>(operation: (callbackHandler: (param: O) -> ()) -> (),
                                                        queue: dispatch_queue_t) -> O {
    
    // Our gating mechanism
    let gate = BriskGate()
    
    // This value will eventually hold the response from the async function
    var handledResponse: O?
    
    let theHandler: (p: O) -> () = { responseFromCallback in
        handledResponse = responseFromCallback
        gate.signal()
    }
    
    dispatch_async(queue) {
        operation(callbackHandler: theHandler)
    }
    
    gate.wait()
    
    // It's ok to use ! -- theoretically we are garanteed that handledResponse
    // has been set by this point (inside theHandler)
    return handledResponse!
}


/// Executes the attached operation on the general concurrent background queue
/// and waits for it to complete.  Returns the result of the callback handler that
/// $0 was attached to.
///
/// - e.g.: ```let x = <~{ func(i, callback: $0)``` }
public prefix func <~<O>(operation: (callbackHandler: (param: O) -> ()) -> ()) -> O {
    return processAsync2Sync(operation, queue: backgroundQueue)
}


/// Executes the attached operation on the main queue
/// and waits for it to complete.  Returns the result of the callback handler that
/// $0 was attached to.
///
/// - e.g.: ```let x = <+{ func(i, callback: $0)``` }
public prefix func <+<O>(operation: (callbackHandler: (param: O) -> ()) -> ()) -> O {
    return processAsync2Sync(operation, queue: mainQueue)
}


/// Executes the attached operation on the supplied queue from the left side
/// and waits for it to complete.  Returns the result of the callback handler that
/// $0 was attached to.
///
{'fraction_non_alphanumeric': 0.13084624879989026, 'fraction_numerical': 0.007406391441503223, 'mean_word_length': 2.56228627259404, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1331431', 'n_tokens_mistral': 2134, 'n_tokens_neox': 2072, 'n_words': 783}