iOS - NSLock锁的源码分享

389 阅读3分钟

源码为苹果开源Swift版本的Foundation框架下NSLock.swift 文件

1. NSLock

**open** **class** NSLock: NSObject, NSLocking {

    **internal** **var** mutex = _MutexPointer.allocate(capacity: 1)

#if os(macOS) || os(iOS) || os(Windows)

    **private** **var** timeoutCond = _ConditionVariablePointer.allocate(capacity: 1)

    **private** **var** timeoutMutex = _MutexPointer.allocate(capacity: 1)

#endif

\


    **public** **override** **init**() {

#if os(Windows)

        InitializeSRWLock(mutex)

        InitializeConditionVariable(timeoutCond)

        InitializeSRWLock(timeoutMutex)

#else

        pthread_mutex_init(mutex, **nil**)

#if os(macOS) || os(iOS)

        pthread_cond_init(timeoutCond, **nil**)

        pthread_mutex_init(timeoutMutex, **nil**)

#endif

#endif

    }

    

    **deinit** {

#if os(Windows)

        // SRWLocks do not need to be explicitly destroyed

#else

        pthread_mutex_destroy(mutex)

#endif

        mutex.deinitialize(count: 1)

        mutex.deallocate()

#if os(macOS) || os(iOS) || os(Windows)

        deallocateTimedLockData(cond: timeoutCond, mutex: timeoutMutex)

#endif

    }

    

    **open** **func** lock() {

#if os(Windows)

        AcquireSRWLockExclusive(mutex)

#else

        pthread_mutex_lock(mutex)

#endif

    }

\


    **open** **func** unlock() {

#if os(Windows)

        ReleaseSRWLockExclusive(mutex)

        AcquireSRWLockExclusive(timeoutMutex)

        WakeAllConditionVariable(timeoutCond)

        ReleaseSRWLockExclusive(timeoutMutex)

#else

        pthread_mutex_unlock(mutex)

#if os(macOS) || os(iOS)

        // Wakeup any threads waiting in lock(before:)

        pthread_mutex_lock(timeoutMutex)

        pthread_cond_broadcast(timeoutCond)

        pthread_mutex_unlock(timeoutMutex)

#endif

#endif

    }

\


    **open** **func** `try`() -> Bool {

#if os(Windows)

        **return** TryAcquireSRWLockExclusive(mutex) != 0

#else

        **return** pthread_mutex_trylock(mutex) == 0

#endif

    }

    

    **open** **func** lock(before limit: Date) -> Bool {

#if os(Windows)

        **if** TryAcquireSRWLockExclusive(mutex) != 0 {

          **return** **true**

        }

#else

        **if** pthread_mutex_trylock(mutex) == 0 {

            **return** **true**

        }

#endif

\


#if os(macOS) || os(iOS) || os(Windows)

        **return** timedLock(mutex: mutex, endTime: limit, using: timeoutCond, with: timeoutMutex)

#else

        **guard** **var** endTime = timeSpecFrom(date: limit) **else** {

            **return** **false**

        }

        **return** pthread_mutex_timedlock(mutex, &endTime) == 0

#endif

    }

\


    **open** **var** name: String?

}

**extension** NSLock {

    **internal** **func** synchronized<T>(_ closure: () -> T) -> T {

        **self**.lock()

        **defer** { **self**.unlock() }

        **return** closure()

    }

}

2. NSConditionLock

**open** **class** NSConditionLock : NSObject, NSLocking {

    **internal** **var** _cond = NSCondition()

    **internal** **var** _value: Int

    **internal** **var** _thread: _swift_CFThreadRef?

    

    **public** **convenience** **override** **init**() {

        **self**.init(condition: 0)

    }

    

    **public** **init**(condition: Int) {

        _value = condition

    }

\


    **open** **func** lock() {

        **let** _ = lock(before: Date.distantFuture)

    }

\


    **open** **func** unlock() {

        _cond.lock()

#if os(Windows)

        _thread = INVALID_HANDLE_VALUE

#else

        _thread = **nil**

#endif

        _cond.broadcast()

        _cond.unlock()

    }

    

    **open** **var** condition: Int {

        **return** _value

    }

\


    **open** **func** lock(whenCondition condition: Int) {

        **let** _ = lock(whenCondition: condition, before: Date.distantFuture)

    }

\


    **open** **func** `try`() -> Bool {

        **return** lock(before: Date.distantPast)

    }

    

    **open** **func** tryLock(whenCondition condition: Int) -> Bool {

        **return** lock(whenCondition: condition, before: Date.distantPast)

    }

\


    **open** **func** unlock(withCondition condition: Int) {

        _cond.lock()

#if os(Windows)

        _thread = INVALID_HANDLE_VALUE

#else

        _thread = **nil**

#endif

        _value = condition

        _cond.broadcast()

        _cond.unlock()

    }

\


    **open** **func** lock(before limit: Date) -> Bool {

        _cond.lock()

        **while** _thread != **nil** {

            **if** !_cond.wait(until: limit) {

                _cond.unlock()

                **return** **false**

            }

        }

#if os(Windows)

        _thread = GetCurrentThread()

#else

        _thread = pthread_self()

#endif

        _cond.unlock()

        **return** **true**

    }

    

    **open** **func** lock(whenCondition condition: Int, before limit: Date) -> Bool {

        _cond.lock()

        **while** _thread != **nil** || _value != condition {

            **if** !_cond.wait(until: limit) {

                _cond.unlock()

                **return** **false**

            }

        }

#if os(Windows)

        _thread = GetCurrentThread()

#else

        _thread = pthread_self()

#endif

        _cond.unlock()

        **return** **true**

    }

    

    **open** **var** name: String?

}

3. NSRecursiveLock

**open** **class** NSRecursiveLock: NSObject, NSLocking {

    **internal** **var** mutex = _RecursiveMutexPointer.allocate(capacity: 1)

#if os(macOS) || os(iOS) || os(Windows)

    **private** **var** timeoutCond = _ConditionVariablePointer.allocate(capacity: 1)

    **private** **var** timeoutMutex = _MutexPointer.allocate(capacity: 1)

#endif

\


    **public** **override** **init**() {

        **super**.init()

#if os(Windows)

        InitializeCriticalSection(mutex)

        InitializeConditionVariable(timeoutCond)

        InitializeSRWLock(timeoutMutex)

#else

#if CYGWIN

        **var** attrib : pthread_mutexattr_t? = **nil**

#else

        **var** attrib = pthread_mutexattr_t()

#endif

        withUnsafeMutablePointer(to: &attrib) { attrs **in**

            pthread_mutexattr_init(attrs)

            pthread_mutexattr_settype(attrs, Int32(PTHREAD_MUTEX_RECURSIVE))

            pthread_mutex_init(mutex, attrs)

        }

#if os(macOS) || os(iOS)

        pthread_cond_init(timeoutCond, **nil**)

        pthread_mutex_init(timeoutMutex, **nil**)

#endif

#endif

    }

    

    **deinit** {

#if os(Windows)

        DeleteCriticalSection(mutex)

#else

        pthread_mutex_destroy(mutex)

#endif

        mutex.deinitialize(count: 1)

        mutex.deallocate()

#if os(macOS) || os(iOS) || os(Windows)

        deallocateTimedLockData(cond: timeoutCond, mutex: timeoutMutex)

#endif

    }

    

    **open** **func** lock() {

#if os(Windows)

        EnterCriticalSection(mutex)

#else

        pthread_mutex_lock(mutex)

#endif

    }

    

    **open** **func** unlock() {

#if os(Windows)

        LeaveCriticalSection(mutex)

        AcquireSRWLockExclusive(timeoutMutex)

        WakeAllConditionVariable(timeoutCond)

        ReleaseSRWLockExclusive(timeoutMutex)

#else

        pthread_mutex_unlock(mutex)

#if os(macOS) || os(iOS)

        // Wakeup any threads waiting in lock(before:)

        pthread_mutex_lock(timeoutMutex)

        pthread_cond_broadcast(timeoutCond)

        pthread_mutex_unlock(timeoutMutex)

#endif

#endif

    }

    

    **open** **func** `try`() -> Bool {

#if os(Windows)

        **return** TryEnterCriticalSection(mutex)

#else

        **return** pthread_mutex_trylock(mutex) == 0

#endif

    }

    

    **open** **func** lock(before limit: Date) -> Bool {

#if os(Windows)

        **if** TryEnterCriticalSection(mutex) {

            **return** **true**

        }

#else

        **if** pthread_mutex_trylock(mutex) == 0 {

            **return** **true**

        }

#endif

\


#if os(macOS) || os(iOS) || os(Windows)

        **return** timedLock(mutex: mutex, endTime: limit, using: timeoutCond, with: timeoutMutex)

#else

        **guard** **var** endTime = timeSpecFrom(date: limit) **else** {

            **return** **false**

        }

        **return** pthread_mutex_timedlock(mutex, &endTime) == 0

#endif

    }

\


    **open** **var** name: String?

}

4. NSCondition

**open** **class** NSCondition: NSObject, NSLocking {

    **internal** **var** mutex = _MutexPointer.allocate(capacity: 1)

    **internal** **var** cond = _ConditionVariablePointer.allocate(capacity: 1)

\


    **public** **override** **init**() {

#if os(Windows)

        InitializeSRWLock(mutex)

        InitializeConditionVariable(cond)

#else

        pthread_mutex_init(mutex, **nil**)

        pthread_cond_init(cond, **nil**)

#endif

    }

    

    **deinit** {

#if os(Windows)

        // SRWLock do not need to be explicitly destroyed

#else

        pthread_mutex_destroy(mutex)

        pthread_cond_destroy(cond)

#endif

        mutex.deinitialize(count: 1)

        cond.deinitialize(count: 1)

        mutex.deallocate()

        cond.deallocate()

    }

    

    **open** **func** lock() {

#if os(Windows)

        AcquireSRWLockExclusive(mutex)

#else

        pthread_mutex_lock(mutex)

#endif

    }

    

    **open** **func** unlock() {

#if os(Windows)

        ReleaseSRWLockExclusive(mutex)

#else

        pthread_mutex_unlock(mutex)

#endif

    }

    

    **open** **func** wait() {

#if os(Windows)

        SleepConditionVariableSRW(cond, mutex, WinSDK.INFINITE, 0)

#else

        pthread_cond_wait(cond, mutex)

#endif

    }

\


    **open** **func** wait(until limit: Date) -> Bool {

#if os(Windows)

        **return** SleepConditionVariableSRW(cond, mutex, timeoutFrom(date: limit), 0)

#else

        **guard** **var** timeout = timeSpecFrom(date: limit) **else** {

            **return** **false**

        }

        **return** pthread_cond_timedwait(cond, mutex, &timeout) == 0

#endif

    }

    

    **open** **func** signal() {

#if os(Windows)

        WakeConditionVariable(cond)

#else

        pthread_cond_signal(cond)

#endif

    }

    

    **open** **func** broadcast() {

#if os(Windows)

        WakeAllConditionVariable(cond)

#else

        // 汇编分析 - 猜 (多看多玩)

        pthread_cond_broadcast(cond) // wait  signal

#endif

    }

    

    **open** **var** name: String?

}