Skip to content

Instantly share code, notes, and snippets.

@steipete
Forked from RomanTruba/Synchronization_test_iOS_SDK10
Last active August 29, 2023 08:47
Show Gist options
  • Save steipete/36350a8a60693d440954b95ea6cbbafc to your computer and use it in GitHub Desktop.
Save steipete/36350a8a60693d440954b95ea6cbbafc to your computer and use it in GitHub Desktop.
Updated for Xcode 8, Swift 3; added os_unfair_lock
//
// SpinlockTestTests.swift
// SpinlockTestTests
//
// Created by Peter Steinberger on 04/10/2016.
// Copyright © 2016 PSPDFKit GmbH. All rights reserved.
//
import XCTest
final class LockingTests: XCTestCase {
func testSpinLock() {
var spinLock = OS_SPINLOCK_INIT
executeLockTest { (block) in
OSSpinLockLock(&spinLock)
block()
OSSpinLockUnlock(&spinLock)
}
}
func testUnfairLock() {
var unfairLock = os_unfair_lock_s()
executeLockTest { (block) in
os_unfair_lock_lock(&unfairLock)
block()
os_unfair_lock_unlock(&unfairLock)
}
}
func testDispatchSemaphore() {
let sem = DispatchSemaphore(value: 1)
executeLockTest { (block) in
_ = sem.wait(timeout: DispatchTime.distantFuture)
block()
sem.signal()
}
}
func testNSLock() {
let lock = NSLock()
executeLockTest { (block) in
lock.lock()
block()
lock.unlock()
}
}
func testPthreadMutex() {
var mutex = pthread_mutex_t()
pthread_mutex_init(&mutex, nil)
executeLockTest{ (block) in
pthread_mutex_lock(&mutex)
block()
pthread_mutex_unlock(&mutex)
}
pthread_mutex_destroy(&mutex);
}
func testSyncronized() {
let obj = NSObject()
executeLockTest{ (block) in
objc_sync_enter(obj)
block()
objc_sync_exit(obj)
}
}
func testQueue() {
let lockQueue = DispatchQueue.init(label: "com.test.LockQueue")
executeLockTest{ (block) in
lockQueue.sync() {
block()
}
}
}
func disabled_testNoLock() {
executeLockTest { (block) in
block()
}
}
private func executeLockTest(performBlock:@escaping (_ block:() -> Void) -> Void) {
let dispatchBlockCount = 16
let iterationCountPerBlock = 100_000
// This is an example of a performance test case.
let queues = [
DispatchQueue.global(qos: DispatchQoS.QoSClass.userInteractive),
DispatchQueue.global(qos: DispatchQoS.QoSClass.default),
DispatchQueue.global(qos: DispatchQoS.QoSClass.utility),
]
var value = 0
self.measure {
let group = DispatchGroup.init()
for block in 0..<dispatchBlockCount {
group.enter()
let queue = queues[block % queues.count]
queue.async(execute: {
for _ in 0..<iterationCountPerBlock {
performBlock({
value = value + 2
value = value - 1
})
}
group.leave()
})
}
_ = group.wait(timeout: DispatchTime.distantFuture)
}
}
}
@kikeenrique
Copy link

I won't recommend to use os_unfair_lock_s as in this code, PLEASE, read this before http://www.russbishop.net/the-law.
In short, in swift you must use

    var unfairLock: UnsafeMutablePointer<os_unfair_lock>
...
init
    unfairLock = UnsafeMutablePointer<os_unfair_lock>.allocate(capacity: 1)
    unfairLock.initialize(to: os_unfair_lock())
deinit
     unfairLock.deallocate()

instead of

   var unfairLock = os_unfair_lock_s()
...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment