 
 class AsyncTests: XCTestCase
 {
-    let IterationsForDelayedTests   = 10
-    let IterationsPerBarrierStage   = 5
-    let IterationsOfBarrierTest     = 10
+    let iterationsForDelayedTests   = 10
+    let iterationsPerBarrierStage   = 5
+    let iterationsOfBarrierTest     = 10
+    let maxTriesToWaitForCompletion = 10
 
     func testAsyncFunction()
     {

        }
        semaphore.unlock()

        XCTAssertTrue(completed == IterationsForDelayedTests)
    }

    func testAsyncBarrierFunction()
    {
//        print("testAsyncBarrierFunction() @ \(#line) -- entering function")

        var startAsyncWork = false
        var preBarrierStageCompleted = 0
        var inBarrierStageCompleted = 0

        {
            XCTAssertTrue(Thread.isMainThread)  // we expect tests to run on the main thread

            for _ in 0..<iterationsPerBarrierStage {
                async {
                    XCTAssertTrue(!Thread.isMainThread)
                    startingGun.lock()
                    while !startAsyncWork {
                        startingGun.wait()
                    }
                    startingGun.unlock()
                    semaphore.lock()

                    XCTAssertTrue(inBarrierStageCompleted == 0)
                    XCTAssertTrue(postBarrierStageCompleted == 0)

                    preBarrierStageCompleted += 1

                    semaphore.signal()
                    semaphore.unlock()
                }
            }

            for _ in 0..<iterationsPerBarrierStage {
                asyncBarrier {
                    XCTAssertTrue(!Thread.isMainThread)

                    startingGun.lock()
                    while !startAsyncWork {
                        startingGun.wait()
                    }
                    startingGun.unlock()
                    semaphore.lock()

                    XCTAssertTrue(preBarrierStageCompleted == self.iterationsPerBarrierStage)
                    XCTAssertTrue(postBarrierStageCompleted == 0)

                    inBarrierStageCompleted += 1
                    semaphore.signal()
                    semaphore.unlock()
                }
            }
            for _ in 0..<iterationsPerBarrierStage {
                async {
                    XCTAssertTrue(!Thread.isMainThread)
                    startingGun.lock()
                    while !startAsyncWork {
                        startingGun.wait()
                    }
                    startingGun.unlock()

                    semaphore.lock()

                    XCTAssertTrue(preBarrierStageCompleted == self.iterationsPerBarrierStage)
                    XCTAssertTrue(inBarrierStageCompleted == self.iterationsPerBarrierStage)

                    postBarrierStageCompleted += 1
                    semaphore.signal()
                    semaphore.unlock()
                }
            }
        }

        for _ in 0..<iterationsOfBarrierTest {
            let semaphore = NSCondition()
            let startingGun = NSCondition()
            testBarrier(with: semaphore, startingGun: startingGun)

            let waitingFor = iterationsPerBarrierStage * 3  // because there are 3 test stages

            var completed = 0
            var lastCompleted: Int?
            semaphore.lock()

            startingGun.lock()
            startAsyncWork = true
            startingGun.broadcast()
            startingGun.unlock()

            while completed < waitingFor {
                if !semaphore.wait(until: Date().addingTimeInterval(1.0)) {
                    RunLoop.current.run(mode: .commonModes, before: Date().addingTimeInterval(1.0))
                }
                else {
                    completed = preBarrierStageCompleted + inBarrierStageCompleted + postBarrierStageCompleted
                    if let last = lastCompleted {
                        XCTAssertTrue(completed > last)
                    }
                    lastCompleted = completed
                }
            }
            semaphore.unlock()

            XCTAssertTrue(completed == waitingFor)

