<commit_before>//
//  Lock.swift
//  SwiftFoundation
//
//  Created by <NAME> on 4/9/16.
//  Copyright © 2016 PureSwift. All rights reserved.
//

#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
    import Darwin.C
#elseif os(Linux)
    import Glibc
#endif

/// Protocol defining lock and unlock operations.
public protocol Locking {
    
    /// Block until acquiring lock.
    func lock()
    
    /// Relinquish lock.
    func unlock()
}

/// Used to coordinate the operation of multiple threads of execution within the same application. 
/// A lock object can be used to mediate access to an application’s global data or to protect a critical section of code,
/// allowing it to run atomically.
///
/// - Note: `Lock` uses POSIX threads to implement its locking behavior.
/// When sending an unlock message to a `Lock`, you must be sure that message is sent from the same thread
/// that sent the initial lock message. Unlocking a lock from a different thread can result in undefined behavior.
/// You should not use this class to implement a recursive lock. 
/// Calling the lock method twice on the same thread will lock up your thread permanently. 
/// Unlocking a lock that is not locked is considered a programmer error and should be fixed in your code.
/// The `Lock` reports such errors by printing an error message to the console when they occur.
public final class Lock: Locking {
    
    // MARK: - Properties
    
    /// You can use a name string to identify a lock within your code.
    public var name: String?
    
    private var internalMutex = pthread_mutex_t()
    
    // MARK: - Intialization
    
    deinit { pthread_mutex_destroy(&internalMutex) }
    
    public init() {
        
        pthread_mutex_init(&internalMutex, nil)
    }
    
    // MARK: - Methods
    
    /// Attempts to acquire a lock before a given time.
    ///
    /// - Discussion: The thread is blocked until the receiver acquires the lock or limit is reached.
    public func lock(before limit: Date) {
        
        assert(Date() < limit, "\(limit) must be after the current date.")
        
        guard tryLock() else {
            
            repeat { sched_yield() }
                
            while limit - Date() > 0
            
            return
        }
    }
    
    @inline(__always)
    public func lock() {
        
        let errorCode = pthread_mutex_lock(&internalMutex)
        
        assert(errorCode == 0, "Could not lock mutex. \(POSIXError(rawValue: errorCode)!)")
    }
    
    @inline(__always)
    public func unlock() {
        
        let errorCode = pthread_mutex_unlock(&internalMutex)
        
        assert(errorCode == 0, "Could not unlock mutex. \(POSIXError(rawValue: errorCode)!)")
    }
    
    /// Try to acquire lock and return immediately.
    @inline(__always)
    public func tryLock() -> Bool {
        
        return pthread_mutex_trylock(&internalMutex) == 0
    }
}

// MARK: - Private Types

private extension Lock {
    
    /// POSIX Mutex (`Lock`) Attribute
    private final class Attribute {
        
        // MARK: - Singletons
        
        private static let Normal = Attribute(type: .normal)
        
        private static let ErrorCheck = Attribute(type: .errorCheck)
        
        private static let Recursive = Attribute(type: .recursive)
        
        // MARK: - Properties
        
        private var internalAttribute = pthread_mutexattr_t()
        
        // MARK: - Initialization
        
        deinit { pthread_mutexattr_destroy(&internalAttribute) }
        
        private init() {
            
            pthread_mutexattr_init(&internalAttribute)
        }
        
        private convenience init(type: AttributeType) {
            
            self.init()
            
            self.type = type
        }
        
        // MARK: - Methods
        
        private var type: AttributeType {
            
            get {
                
                var typeRawValue: CInt = 0
                
                pthread_mutexattr_gettype(&internalAttribute, &typeRawValue)
                
                return AttributeType(rawValue: typeRawValue)!
            }
            
            set { pthread_mutexattr_settype(&internalAttribute, newValue.rawValue) }
        }
    }
    
    /// POSIX Mutex (`Lock`) Attribute Type
    private enum AttributeType: CInt {
        
        case normal     = 0
        case errorCheck = 1
        case recursive  = 2
        
        private init() { self = normal }
    }
}<commit_msg>Updated Lock to match Foundation API<commit_after>//
//  Lock.swift
//  SwiftFoundation
//
//  Created by <NAME> on 4/9/16.
//  Copyright © 2016 PureSwift. All rights reserved.
//

#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
    import Darwin.C
#elseif os(Linux)
    import Glibc
#endif

public protocol Locking {
    
    func lock()
    func unlock()
}

public class Lock: Locking {
    
    private var mutex = UnsafeMutablePointer<pthread_mutex_t>(allocatingCapacity: 1)
    
    public init() {
        pthread_mutex_init(mutex, nil)
    }
    
    deinit {
        pthread_mutex_destroy(mutex)
        mutex.deinitialize()
        mutex.deallocateCapacity(1)
    }
    
    public func lock() {
        pthread_mutex_lock(mutex)
    }
    
    public func unlock() {
        pthread_mutex_unlock(mutex)
    }
    
    public func tryLock() -> Bool {
        return pthread_mutex_trylock(mutex) == 0
    }
    
    public var name: String?
}

extension Lock {
    internal func synchronized<T>(_ closure: @noescape () -> T) -> T {
        self.lock()
        defer { self.unlock() }
        return closure()
    }
}

public class NSConditionLock : NSObject, Locking {
    internal var _cond = Condition()
    internal var _value: Int
    internal var _thread: pthread_t?
    
    public convenience override init() {
        self.init(condition: 0)
    }
    
    public init(condition: Int) {
        _value = condition
    }
    
    public func lock() {
        let _ = lockBeforeDate(Date.distantFuture)
    }
    
    public func unlock() {
        _cond.lock()
        _thread = nil
        _cond.broadcast()
        _cond.unlock()
    }
    
    public var condition: Int {
        return _value
    }
    
    public func lockWhenCondition(_ condition: Int) {
        let _ = lockWhenCondition(condition, beforeDate: Date.distantFuture)
    }
    
    public func tryLock() -> Bool {
        return lockBeforeDate(Date.distantPast)
    }
    
    public func tryLockWhenCondition(_ condition: Int) -> Bool {
        return lockWhenCondition(condition, beforeDate: Date.distantPast)
    }
    
    public func unlockWithCondition(_ condition: Int) {
        _cond.lock()
        _thread = nil
        _value = condition
        _cond.broadcast()
        _cond.unlock()
    }
    
    public func lockBeforeDate(_ limit: Date) -> Bool {
        _cond.lock()
        while _thread == nil {
            if !_cond.waitUntilDate(limit) {
                _cond.unlock()
                return false
            }
        }
        _thread = pthread_self()
        _cond.unlock()
        return true
    }
    
    public func lockWhenCondition(_ condition: Int, beforeDate limit: Date) -> Bool {
        _cond.lock()
        while _thread != nil || _value != condition {
            if !_cond.waitUntilDate(limit) {
                _cond.unlock()
                return false
            }
        }
        _thread = pthread_self()
        _cond.unlock()
        return true
    }
    
    public var name: String?
}

public class RecursiveLock: NSObject, Locking {
    internal var mutex = UnsafeMutablePointer<pthread_mutex_t>(allocatingCapacity: 1)
    
    public override init() {
        super.init()
        var attrib = pthread_mutexattr_t()
        withUnsafeMutablePointer(&attrib) { attrs in
            pthread_mutexattr_settype(attrs, Int32(PTHREAD_MUTEX_RECURSIVE))
            pthread_mutex_init(mutex, attrs)
        }
    }
    
    deinit {
        pthread_mutex_destroy(mutex)
        mutex.deinitialize()
        mutex.deallocateCapacity(1)
    }
    
    public func lock() {
        pthread_mutex_lock(mutex)
    }
    
    public func unlock() {
        pthread_mutex_unlock(mutex)
    }
    
    public func tryLock() -> Bool {
        return pthread_mutex_trylock(mutex) == 0
    }
    
    public var name: String?
}

public class Condition: NSObject, Locking {
    internal var mutex = UnsafeMutablePointer<pthread_mutex_t>(allocatingCapacity: 1)
    internal var cond = UnsafeMutablePointer<pthread_cond_t>(allocatingCapacity: 1)
    
    public override init() {
        pthread_mutex_init(mutex, nil)
        pthread_cond_init(cond, nil)
    }
    
    deinit {
        pthread_mutex_destroy(mutex)
        pthread_cond_destroy(cond)
        mutex.deinitialize()
        cond.deinitialize()
        mutex.deallocateCapacity(1)
        cond.deallocateCapacity(1)
    }
    
    public func lock() {
        pthread_mutex_lock(mutex)
    }
    
    public func unlock() {
        pthread_mutex_unlock(mutex)
    }
    
    public func wait() {
        pthread_cond_wait(cond, mutex)
    }
    
    public func waitUntilDate(_ limit: Date) -> Bool {
        let lim = limit.timeIntervalSinceReferenceDate
        let ti = lim - CFAbsoluteTimeGetCurrent()
        if ti < 0.0 {
            return false
        }
        var ts = timespec()
        ts.tv_sec = Int(floor(ti))
        ts.tv_nsec = Int((ti - Double(ts.tv_sec)) * 1000000000.0)
        var tv = timeval()
        withUnsafeMutablePointer(&tv) { t in
            gettimeofday(t, nil)
            ts.tv_sec += t.pointee.tv_sec
            ts.tv_nsec += Int((t.pointee.tv_usec * 1000000) / 1000000000)
        }
        let retVal: Int32 = withUnsafePointer(&ts) { t in
            return pthread_cond_timedwait(cond, mutex, t)
        }
        
        return retVal == 0
    }
    
    public func signal() {
        pthread_cond_signal(cond)
    }
    
    public func broadcast() {
        pthread_cond_broadcast(cond)
    }
    
    public var name: String?
}
{'fraction_non_alphanumeric': 0.08807829181494661, 'fraction_numerical': 0.006919731119019375, 'mean_word_length': 1.8700709219858156, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, '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': '2535600', 'n_tokens_mistral': 2985, 'n_tokens_neox': 2861, 'n_words': 799}