<commit_before>//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

import CNIOLinux

private typealias ThreadBoxValue = (body: (Thread) -> Void, name: String?)
private typealias ThreadBox = Box<ThreadBoxValue>


#if os(Linux)
private let sys_pthread_getname_np = CNIOLinux_pthread_getname_np
private let sys_pthread_setname_np = CNIOLinux_pthread_setname_np
#else
private let sys_pthread_getname_np = pthread_getname_np
// Emulate the same method signature as pthread_setname_np on Linux.
private func sys_pthread_setname_np(_ p: pthread_t, _ pointer: UnsafePointer<Int8>) -> Int32 {
    assert(pthread_equal(pthread_self(), p) != 0)
    pthread_setname_np(pointer)
    // Will never fail on macOS so just return 0 which will be used on linux to signal it not failed.
    return 0
}
#endif

/// A Thread that executes some runnable block.
///
/// All methods exposed are thread-safe.
final class Thread {

    /// The pthread_t used by this instance.
    private let pthread: pthread_t

    /// Create a new instance
    ///
    /// - arguments:
    ///     - pthread: The `pthread_t` that is wrapped and used by the `Thread`.
    private init(pthread: pthread_t) {
        self.pthread = pthread
    }

    /// Execute the given body with the `pthread_t` that is used by this `Thread` as argument.
    ///
    /// - warning: Do not escape `pthread_t` from the closure for later use.
    ///
    /// - parameters:
    ///     - body: The closure that will accept the `pthread_t`.
    /// - returns: The value returned by `fn`.
    func withUnsafePthread<T>(_ body: (pthread_t) throws -> T) rethrows -> T {
        return try body(self.pthread)
    }

    /// Get current name of the `Thread` or `nil` if not set.
    var name: String? {
        get {
            // 64 bytes should be good enough as on linux the limit is usually 16 and its very unlikely a user will ever set something longer anyway.
            var chars: [CChar] = Array(repeating: 0, count: 64)
            guard sys_pthread_getname_np(pthread, &chars, chars.count) == 0 else {
                return nil
            }
            return String(cString: chars)
        }
    }

    /// Spawns and runs some task in a `Thread`.
    ///
    /// - arguments:
    ///     - name: The name of the `Thread` or `nil` if no specific name should be set.
    ///     - body: The function to execute within the spawned `Thread`.
    static func spawnAndRun(name: String? = nil, body: @escaping (Thread) -> Void) {
        // Unfortunally the pthread_create method take a different first argument depending on if its on linux or macOS, so ensure we use the correct one.
        #if os(Linux)
            var pt: pthread_t = pthread_t()
        #else
            var pt: pthread_t? = nil
        #endif

        // Store everything we want to pass into the c function in a Box so we can hand-over the reference.
        let tuple: ThreadBoxValue = (body: body, name: name)
        let box = ThreadBox(tuple)
        let res = pthread_create(&pt, nil, { p in
            // Cast to UnsafeMutableRawPointer? and force unwrap to make the same code work on macOS and Linux.
            let b = Unmanaged<ThreadBox>.fromOpaque((p as UnsafeMutableRawPointer?)!.assumingMemoryBound(to: ThreadBox.self)).takeRetainedValue()

            let body = b.value.body
            let name = b.value.name

            let pt = pthread_self()

            if let threadName = name {
                let res = sys_pthread_setname_np(pt, threadName)
                // This should only happen in case of a too-long name.
                precondition(res == 0, "pthread_setname_np failed for '\(threadName)': \(res)")
            }

            body(Thread(pthread: pt))
            return nil
        }, Unmanaged.passRetained(box).toOpaque())

        precondition(res == 0, "Unable to create thread: \(res)")

        let detachError = pthread_detach((pt as pthread_t?)!)
        precondition(detachError == 0, "pthread_detach failed with error \(detachError)")
    }

    /// Returns `true` if the calling thread is the same as this one.
    var isCurrent: Bool {
        return pthread_equal(pthread, pthread_self()) != 0
    }

    /// Returns the current running `Thread`.
    static var current: Thread {
        return Thread(pthread: pthread_self())
    }
}

/// A `ThreadSpecificVariable` is a variable that can be read and set like a normal variable except that it holds
/// different variables per thread.
///
/// `ThreadSpecificVariable` is thread-safe so it can be used with multiple threads at the same time but the value
/// returned by `currentValue` is defined per thread.
///
/// - note: `ThreadSpecificVariable` has reference semantics.
internal struct ThreadSpecificVariable<T: AnyObject> {
    private let key: pthread_key_t<commit_msg>Declare ThreadSpecificVariable public (#102)<commit_after>//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

import CNIOLinux

private typealias ThreadBoxValue = (body: (Thread) -> Void, name: String?)
private typealias ThreadBox = Box<ThreadBoxValue>


#if os(Linux)
private let sys_pthread_getname_np = CNIOLinux_pthread_getname_np
private let sys_pthread_setname_np = CNIOLinux_pthread_setname_np
#else
private let sys_pthread_getname_np = pthread_getname_np
// Emulate the same method signature as pthread_setname_np on Linux.
private func sys_pthread_setname_np(_ p: pthread_t, _ pointer: UnsafePointer<Int8>) -> Int32 {
    assert(pthread_equal(pthread_self(), p) != 0)
    pthread_setname_np(pointer)
    // Will never fail on macOS so just return 0 which will be used on linux to signal it not failed.
    return 0
}
#endif

/// A Thread that executes some runnable block.
///
/// All methods exposed are thread-safe.
final class Thread {

    /// The pthread_t used by this instance.
    private let pthread: pthread_t

    /// Create a new instance
    ///
    /// - arguments:
    ///     - pthread: The `pthread_t` that is wrapped and used by the `Thread`.
    private init(pthread: pthread_t) {
        self.pthread = pthread
    }

    /// Execute the given body with the `pthread_t` that is used by this `Thread` as argument.
    ///
    /// - warning: Do not escape `pthread_t` from the closure for later use.
    ///
    /// - parameters:
    ///     - body: The closure that will accept the `pthread_t`.
    /// - returns: The value returned by `fn`.
    func withUnsafePthread<T>(_ body: (pthread_t) throws -> T) rethrows -> T {
        return try body(self.pthread)
    }

    /// Get current name of the `Thread` or `nil` if not set.
    var name: String? {
        get {
            // 64 bytes should be good enough as on linux the limit is usually 16 and its very unlikely a user will ever set something longer anyway.
            var chars: [CChar] = Array(repeating: 0, count: 64)
            guard sys_pthread_getname_np(pthread, &chars, chars.count) == 0 else {
                return nil
            }
            return String(cString: chars)
        }
    }

    /// Spawns and runs some task in a `Thread`.
    ///
    /// - arguments:
    ///     - name: The name of the `Thread` or `nil` if no specific name should be set.
    ///     - body: The function to execute within the spawned `Thread`.
    static func spawnAndRun(name: String? = nil, body: @escaping (Thread) -> Void) {
        // Unfortunally the pthread_create method take a different first argument depending on if its on linux or macOS, so ensure we use the correct one.
        #if os(Linux)
            var pt: pthread_t = pthread_t()
        #else
            var pt: pthread_t? = nil
        #endif

        // Store everything we want to pass into the c function in a Box so we can hand-over the reference.
        let tuple: ThreadBoxValue = (body: body, name: name)
        let box = ThreadBox(tuple)
        let res = pthread_create(&pt, nil, { p in
            // Cast to UnsafeMutableRawPointer? and force unwrap to make the same code work on macOS and Linux.
            let b = Unmanaged<ThreadBox>.fromOpaque((p as UnsafeMutableRawPointer?)!.assumingMemoryBound(to: ThreadBox.self)).takeRetainedValue()

            let body = b.value.body
            let name = b.value.name

            let pt = pthread_self()

            if let threadName = name {
                let res = sys_pthread_setname_np(pt, threadName)
                // This should only happen in case of a too-long name.
                precondition(res == 0, "pthread_setname_np failed for '\(threadName)': \(res)")
            }

            body(Thread(pthread: pt))
            return nil
        }, Unmanaged.passRetained(box).toOpaque())

        precondition(res == 0, "Unable to create thread: \(res)")

        let detachError = pthread_detach((pt as pthread_t?)!)
        precondition(detachError == 0, "pthread_detach failed with error \(detachError)")
    }

    /// Returns `true` if the calling thread is the same as this one.
    var isCurrent: Bool {
        return pthread_equal(pthread, pthread_self()) != 0
    }

    /// Returns the current running `Thread`.
    static var current: Thread {
        return Thread(pthread: pthread_self())
    }
}

/// A `ThreadSpecificVariable` is a variable that can be read and set like a normal variable except that it holds
/// different variables per thread.
///
/// `ThreadSpecificVariable` is thread-safe so it can be used with multiple threads at the same time but the value
/// returned by `currentValue` is defined per thread.
///
/// - note: `ThreadSpecificVariable` has reference semantics.
public struct ThreadSpecificVariable<T: AnyObject> {
    private let key: pthread_key_t
{'fraction_non_alphanumeric': 0.12280034243317797, 'fraction_numerical': 0.005992580614477314, 'mean_word_length': 2.2733499377334994, 'pattern_counts': {'":': 0, '<': 13, '<?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': '887609', 'n_tokens_mistral': 3077, 'n_tokens_neox': 2925, 'n_words': 1118}