<commit_before>//===--- PThreadExecutionContext.swift ------------------------------------------------------===//
//Copyright (c) 2016 <NAME> (dileping)
//
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
//===----------------------------------------------------------------------===//

//////////////////////////////////////////////////////////////////////////
//This file is a temporary solution, just until Dispatch will run on Mac//
//////////////////////////////////////////////////////////////////////////
//#if os(Linux)
    
    import Foundation
    import Result
    #if os(Linux)
        import Glibc
    #endif
    
    private func thread_proc(pm: UnsafeMutablePointer<Void>) -> UnsafeMutablePointer<Void> {
        let pthread = Unmanaged<PThread>.fromOpaque(COpaquePointer(pm)).takeRetainedValue()
        pthread.task?()
        return nil
    }

    internal class PThreadKey {
        private var key: pthread_key_t = 0
        init(destructionCallback: (@convention(c) UnsafeMutablePointer<Void> -> Void)! = nil) {
            pthread_key_create(&key, destructionCallback)
        }
        deinit {
            pthread_key_delete(key)
        }
    }

    internal class PThread {
        let thread: UnsafeMutablePointer<pthread_t>
        let task:SafeTask?
        
        init(task:SafeTask? = nil) {
            self.task = task
            self.thread = UnsafeMutablePointer<pthread_t>.alloc(1)
        }
        deinit {
            self.thread.destroy()
            self.thread.dealloc(1)
        }
        
        func start() {
            pthread_create(thread, nil, thread_proc, UnsafeMutablePointer<Void>(Unmanaged.passRetained(self).toOpaque()))
        }
        
        static func getSpecific(key: PThreadKey) -> AnyObject? {
            let val = pthread_getspecific(key.key)
            if val == nil {
                return nil
            }
            return Unmanaged<AnyObject>.fromOpaque(COpaquePointer(val)).takeUnretainedValue()
        }
        
        static func setSpecific(obj: AnyObject?, key: PThreadKey) {
            if obj == nil {
                pthread_setspecific(key.key, nil)
            } else {
                pthread_setspecific(key.key, UnsafePointer<Void>(Unmanaged.passUnretained(obj!).toOpaque()))
            }
        }
        
    }
    
    private class ParallelContext : ExecutionContextBase, ExecutionContextType {
        func async(task:SafeTask) {
            let thread = PThread(task: task)
            thread.start()
        }
        
        func async(after:Double, task:SafeTask) {
            let thread = PThread(task: {
                sleep(after)
                task()
            })
            thread.start()
        }
        
        func sync<ReturnType>(task:() throws -> ReturnType) throws -> ReturnType {
            return try syncThroughAsync(task)
        }
    }
    
    private class SerialContext : ExecutionContextBase, ExecutionContextType {
        private let rl:RunLoop
        
        override init() {
            let runLoop:NSMutableArray = NSMutableArray(capacity: 1)
            let sema = Semaphore()
            
            PThread(task: { [unowned runLoop] in
                runLoop.addObject(RunLoop.currentRunLoop())
                RunLoop.runWithOptions(RunLoop.defaultMode, timeout: 0, once: true)
                sema.signal()
                RunLoop.run()
            }).start()
            
            sema.wait()

            self.rl = runLoop.objectAtIndex(0) as! RunLoop
        }
        
        init(runLoop:RunLoop) {
            rl = runLoop
        }
        
        func async(task:SafeTask) {
            rl.addTask(task)
        }
        
        func async(after:Double, task:SafeTask) {
            rl.addDelay(RunLoopDelay(task, delay: after), mode: RunLoop.defaultMode)
        }
        
        func sync<ReturnType>(task:() throws -> ReturnType) throws -> ReturnType {
            if rl.isCurrent() {
                return try task()
            } else {
                return try syncThroughAsync(task)
            }
        }
    }
    
    public class PThreadExecutionContext : ExecutionContextBase, ExecutionContextType, DefaultExecutionContextType {
        let inner:ExecutionContextType
        
        init(inner:ExecutionContextType) {
            self.inner = inner
        }<commit_msg>Better run loop creation hack<commit_after>//===--- PThreadExecutionContext.swift ------------------------------------------------------===//
//Copyright (c) 2016 <NAME> (dileping)
//
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
//===----------------------------------------------------------------------===//

//////////////////////////////////////////////////////////////////////////
//This file is a temporary solution, just until Dispatch will run on Mac//
//////////////////////////////////////////////////////////////////////////
//#if os(Linux)
    
    import Foundation
    import Result
    #if os(Linux)
        import Glibc
    #endif
    
    private func thread_proc(pm: UnsafeMutablePointer<Void>) -> UnsafeMutablePointer<Void> {
        let pthread = Unmanaged<PThread>.fromOpaque(COpaquePointer(pm)).takeRetainedValue()
        pthread.task?()
        return nil
    }

    internal class PThreadKey {
        private var key: pthread_key_t = 0
        init(destructionCallback: (@convention(c) UnsafeMutablePointer<Void> -> Void)! = nil) {
            pthread_key_create(&key, destructionCallback)
        }
        deinit {
            pthread_key_delete(key)
        }
    }

    internal class PThread {
        let thread: UnsafeMutablePointer<pthread_t>
        let task:SafeTask?
        
        init(task:SafeTask? = nil) {
            self.task = task
            self.thread = UnsafeMutablePointer<pthread_t>.alloc(1)
        }
        deinit {
            self.thread.destroy()
            self.thread.dealloc(1)
        }
        
        func start() {
            pthread_create(thread, nil, thread_proc, UnsafeMutablePointer<Void>(Unmanaged.passRetained(self).toOpaque()))
        }
        
        static func getSpecific(key: PThreadKey) -> AnyObject? {
            let val = pthread_getspecific(key.key)
            if val == nil {
                return nil
            }
            return Unmanaged<AnyObject>.fromOpaque(COpaquePointer(val)).takeUnretainedValue()
        }
        
        static func setSpecific(obj: AnyObject?, key: PThreadKey) {
            if obj == nil {
                pthread_setspecific(key.key, nil)
            } else {
                pthread_setspecific(key.key, UnsafePointer<Void>(Unmanaged.passUnretained(obj!).toOpaque()))
            }
        }
        
    }
    
    private class ParallelContext : ExecutionContextBase, ExecutionContextType {
        func async(task:SafeTask) {
            let thread = PThread(task: task)
            thread.start()
        }
        
        func async(after:Double, task:SafeTask) {
            let thread = PThread(task: {
                sleep(after)
                task()
            })
            thread.start()
        }
        
        func sync<ReturnType>(task:() throws -> ReturnType) throws -> ReturnType {
            return try syncThroughAsync(task)
        }
    }

    // This class is workaround around release cycle in pthread run loop creation. See below in init(). Stupid ARC :(
    private class RunLoopHolder {
        var loop: RunLoop? = nil
    }
    
    private class SerialContext : ExecutionContextBase, ExecutionContextType {
        private let rl:RunLoop
        
        override init() {
            let holder = RunLoopHolder()
            let sema = Semaphore()
            
            PThread(task: { [unowned holder] in
                holder.loop = RunLoop.currentRunLoop()
                sema.signal()
                RunLoop.run()
            }).start()
            
            sema.wait()

            self.rl = holder.loop!
        }
        
        init(runLoop:RunLoop) {
            rl = runLoop
        }
        
        func async(task:SafeTask) {
            rl.addTask(task)
        }
        
        func async(after:Double, task:SafeTask) {
            rl.addDelay(RunLoopDelay(task, delay: after), mode: RunLoop.defaultMode)
        }
        
        func sync<ReturnType>(task:() throws -> ReturnType) throws -> ReturnType {
            if rl.isCurrent() {
                return try task()
            } else {
                return try syncThroughAsync(task)
            }
        }
    }
    
    public class PThreadExecutionContext : ExecutionContextBase, ExecutionContextType, DefaultExecutionContextType {
        let inner:ExecutionContextType
        
        init(inner:ExecutionContextType) {
            self.inner = inner
        }
{'fraction_non_alphanumeric': 0.14478527607361963, 'fraction_numerical': 0.002556237218813906, 'mean_word_length': 1.56988964792433, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '6029550', 'n_tokens_mistral': 2563, 'n_tokens_neox': 2486, 'n_words': 610}