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)
}
}
}
@Affaway
Copy link

Affaway commented Nov 10, 2020

Don't really understand any of this. Anyway to break it down in sinple was? Been trying to figure it out for months now but still I am lost. Thanks for your help.

@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