//
//  TuskerTests.swift
//  TuskerTests
//
//  Created by Shadowfacts on 8/15/18.
//  Copyright © 2018 Shadowfacts. All rights reserved.
//

import XCTest
@testable import Tusker

class TuskerTests: XCTestCase {

    override func setUp() {
        // Put setup code here. This method is called before the invocation of each test method in the class.
    }

    override func tearDown() {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
    }

    func testExample() {
        // This is an example of a functional test case.
        // Use XCTAssert and related functions to verify your tests produce the correct results.
    }

    func testPerformanceExample() {
        // This is an example of a performance test case.
        self.measure {
            // Put the code you want to measure the time of here.
        }
    }
    
    
    func testFuckingLock() {
        let lock = MutexLock<[Int: Bool]>(initialState: [:])
        for i in 0..<100 {
            Thread.detachNewThread {
                for j in 0..<50_000 {
                    lock.withLock {
                        $0[i * 50_000 + j] = true
                    }
                }
            }
        }
        while true {
            if lock.withLock({ $0.count }) == 5_000_000 {
                break
            }
        }
        lock.withLock({ _ in
            print("WHAT THE FUUUUUUUUUUUUCK")
        })
    }

}

fileprivate class MutexLock<State> {
    private var state: State
    private var lock = NSLock()
    
    init(initialState: State) {
        self.state = initialState
    }
    
    func withLock<R>(_ body: @Sendable (inout State) throws -> R) rethrows -> R where R : Sendable {
        if !lock.lock(before: Date(timeIntervalSinceNow: 1)) {
            // if we can't acquire the lock after 1 second, something has gone catastrophically wrong
            fatalError()
        }
        defer { lock.unlock() }
        return try body(&state)
    }
}
