1
1
mirror of https://github.com/qvacua/vimr.git synced 2024-11-28 11:35:35 +03:00

GH-264 Use OSSpinLock

This commit is contained in:
Tae Won Ha 2016-09-06 18:45:15 +02:00
parent 122b14f2a2
commit 673e8677e3
No known key found for this signature in database
GPG Key ID: E40743465B5B8B44
7 changed files with 22 additions and 146 deletions

View File

@ -11,8 +11,6 @@
1929B10DD8CD7EE0B8BE529F /* Scorer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9D510177918080BE39B /* Scorer.swift */; };
1929B165820D7177743B537A /* Component.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B39DA7AC4A9B62D7CD39 /* Component.swift */; };
1929B1E05C116514C1D3A384 /* CocoaCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = 1929B5C3F2F1CA4113DABFFD /* CocoaCategories.m */; };
1929B2ADD407219BADBD5A70 /* CwlUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B0DD7AE34C049D26DA8C /* CwlUtils.swift */; };
1929B2B6F571129EB8D231C5 /* CwlUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B0DD7AE34C049D26DA8C /* CwlUtils.swift */; };
1929B2E1A64297B8E05BB64A /* FileUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BA8AC40B901B20F20B71 /* FileUtils.swift */; };
1929B3BF1DB87B57559DC27D /* Matcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BEEB33113B0E33C3830F /* Matcher.swift */; };
1929B3F5743967125F357C9F /* Matcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BEEB33113B0E33C3830F /* Matcher.swift */; };
@ -204,7 +202,6 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1929B0DD7AE34C049D26DA8C /* CwlUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlUtils.swift; sourceTree = "<group>"; };
1929B15B7EDC9B0F40E5E95C /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Logging.h; sourceTree = "<group>"; };
1929B1A51F076E088EF4CCA4 /* server_globals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = server_globals.h; sourceTree = "<group>"; };
1929B39DA7AC4A9B62D7CD39 /* Component.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Component.swift; sourceTree = "<group>"; };
@ -499,7 +496,6 @@
isa = PBXGroup;
children = (
4B6A70931D60E04200E12030 /* AppKitCommons.swift */,
1929B0DD7AE34C049D26DA8C /* CwlUtils.swift */,
1929BA8AC40B901B20F20B71 /* FileUtils.swift */,
1929B9AF20D7BD6E5C975128 /* FoundationCommons.swift */,
1929BEEB33113B0E33C3830F /* Matcher.swift */,
@ -869,7 +865,6 @@
1929B165820D7177743B537A /* Component.swift in Sources */,
1929B93DBAD09835E428F610 /* PrefPane.swift in Sources */,
4BDF501B1D77596500D8FBC3 /* OpenQuicklyWindowManager.swift in Sources */,
1929B2ADD407219BADBD5A70 /* CwlUtils.swift in Sources */,
1929B462CD4935AFF6D69457 /* FileItem.swift in Sources */,
1929B6388EAF16C190B82955 /* FileItemIgnorePattern.swift in Sources */,
1929B73E5EC0B108B83F82EB /* FileItemService.swift in Sources */,
@ -886,7 +881,6 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1929B2B6F571129EB8D231C5 /* CwlUtils.swift in Sources */,
1929B43FBA7A31F39D294CD0 /* FileItem.swift in Sources */,
1929B741C4E58EEDAF901353 /* FileItemIgnorePattern.swift in Sources */,
1929B7C981A0EFCC8D631E3F /* FileItemService.swift in Sources */,

View File

@ -57,11 +57,6 @@ By:
{\field{\*\fldinst{HYPERLINK "https://github.com/eonil/FileSystemEvents"}}{\fldrslt https://github.com/eonil/FileSystemEvents}}\
\
\b CwlUtils
\b0 \
{\field{\*\fldinst{HYPERLINK "https://github.com/mattgallagher/CwlUtils"}}{\fldrslt https://github.com/mattgallagher/CwlUtils}}\
\
\b Nimble
\b0 \
{\field{\*\fldinst{HYPERLINK "https://github.com/Quick/Nimble"}}{\fldrslt https://github.com/Quick/Nimble}}\

View File

@ -1,124 +0,0 @@
//
// CwlMutex.swift
// CwlUtils
//
// Created by Matt Gallagher on 2015/02/03.
// Copyright © 2015 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// Slightly modified by Tae Won Ha
import Foundation
/// A basic wrapper around the "NORMAL" and "RECURSIVE" pthread mutex types. This type is a "class" type to take advantage of the "deinit" method.
final class PThreadMutex {
// Non-recursive "PTHREAD_MUTEX_NORMAL" and recursive "PTHREAD_MUTEX_RECURSIVE" mutex types.
enum PThreadMutexType {
case Normal
case Recursive
}
/// Exposed as an "unsafe" public property so non-scoped patterns can be implemented, if required.
private(set) var unsafeMutex = pthread_mutex_t()
/// Default constructs as ".Normal" or ".Recursive" on request.
init(type: PThreadMutexType = .Normal) {
var attr = pthread_mutexattr_t()
guard pthread_mutexattr_init(&attr) == 0 else {
preconditionFailure()
}
switch type {
case .Normal:
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL)
case .Recursive:
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)
}
guard pthread_mutex_init(&unsafeMutex, &attr) == 0 else {
preconditionFailure()
}
}
deinit {
pthread_mutex_destroy(&unsafeMutex)
}
/* RECOMMENDATION: Don't use the `slowsync` function if you care about performance. Instead, copy this extension into your file and call it:
extension PThreadMutex {
private func sync<R>(@noescape f: () throws -> R) rethrows -> R {
pthread_mutex_lock(&unsafeMutex)
defer { pthread_mutex_unlock(&unsafeMutex) }
return try f()
}
}
*/
func sync<R>(@noescape f: () throws -> R) rethrows -> R {
pthread_mutex_lock(&unsafeMutex)
defer { pthread_mutex_unlock(&unsafeMutex) }
return try f()
}
/* RECOMMENDATION: Don't use the `trySlowsync` function if you care about performance. Instead, copy this extension into your file and call it:
extension PThreadMutex {
private func trySync<R>(@noescape f: () throws -> R) rethrows -> R? {
guard pthread_mutex_trylock(&unsafeMutex) == 0 else { return nil }
defer { pthread_mutex_unlock(&unsafeMutex) }
return try f()
}
}
*/
func trySlowsync<R>(@noescape f: () throws -> R) rethrows -> R? {
guard pthread_mutex_trylock(&unsafeMutex) == 0 else { return nil }
defer { pthread_mutex_unlock(&unsafeMutex) }
return try f()
}
}
#if PERFORMANCE_TESTS
/// A basic scoped mutex wrapper around a `dispatch_semaphore_t`.
/// For maximum performance, it is recommended that you copy this entire type into the same compilation unit as your code that uses it to ensure inlining.
public struct DispatchSemaphore {
let s = dispatch_semaphore_create(1)
public init() {}
public func sync<R>(@noescape f: () throws -> R) rethrows -> R {
_ = dispatch_semaphore_wait(s, DISPATCH_TIME_FOREVER)
defer { _ = dispatch_semaphore_signal(s) }
return try f()
}
}
extension PThreadMutex {
public func sync_2<T>(inout param: T, @noescape f: (inout T) throws -> Void) rethrows -> Void {
pthread_mutex_lock(&unsafeMutex)
defer { pthread_mutex_unlock(&unsafeMutex) }
try f(&param)
}
public func sync_3<T, R>(inout param: T, @noescape f: (inout T) throws -> R) rethrows -> R {
pthread_mutex_lock(&unsafeMutex)
defer { pthread_mutex_unlock(&unsafeMutex) }
return try f(&param)
}
public func sync_4<T, U>(inout param1: T, inout _ param2: U, @noescape f: (inout T, inout U) throws -> Void) rethrows -> Void {
pthread_mutex_lock(&unsafeMutex)
defer { pthread_mutex_unlock(&unsafeMutex) }
return try f(&param1, &param2)
}
}
#endif

View File

@ -7,8 +7,6 @@ import Foundation
class FileItem : CustomStringConvertible {
let mutex = PThreadMutex()
let url: NSURL
let dir: Bool
let hidden: Bool

View File

@ -37,6 +37,8 @@ class FileItemService {
private let workspace = NSWorkspace.sharedWorkspace()
private let iconsCache = NSCache()
private var spinLock = OS_SPINLOCK_INIT
init() {
self.iconsCache.countLimit = 2000
@ -208,7 +210,8 @@ class FileItemService {
}
let child = FileItem(childUrl)
parent.mutex.sync { parent.children.append(child) }
self.syncAddChildren { parent.children.append(child) }
return child
}
@ -216,8 +219,16 @@ class FileItemService {
}
private func scanChildren(item: FileItem) {
item.mutex.sync { item.children = FileUtils.directDescendants(item.url).map(FileItem.init) }
let children = FileUtils.directDescendants(item.url).map(FileItem.init)
self.syncAddChildren { item.children = children }
item.childrenScanned = true
item.needsScanChildren = false
}
private func syncAddChildren(@noescape fn: () -> Void) {
OSSpinLockLock(&self.spinLock)
fn()
OSSpinLockUnlock(&self.spinLock)
}
}

View File

@ -60,14 +60,17 @@ extension Array {
let chunkedCount = Int(ceil(Float(count) / Float(chunk)))
var result: [[R]] = []
let mutex = PThreadMutex()
var spinLock = OS_SPINLOCK_INIT
dispatch_apply(chunkedCount, queue) { idx in
let startIndex = min(idx * chunk, count)
let endIndex = min(startIndex + chunk, count)
let mappedChunk = self[startIndex..<endIndex].map(transform)
mutex.sync { result.append(mappedChunk) }
OSSpinLockLock(&spinLock)
result.append(mappedChunk)
OSSpinLockUnlock(&spinLock)
}
return result.flatMap { $0 }

View File

@ -15,8 +15,6 @@ class OpenQuicklyFilterOperation: NSOperation {
private let flatFileItems: [FileItem]
private let cwd: NSURL
private var spinLock: OSSpinLock = OS_SPINLOCK_INIT
init(forOpenQuicklyWindow openQuicklyWindow: OpenQuicklyWindowComponent) {
self.openQuicklyWindow = openQuicklyWindow
self.pattern = openQuicklyWindow.pattern
@ -53,6 +51,7 @@ class OpenQuicklyFilterOperation: NSOperation {
let cwdPath = self.cwd.path! + "/"
var result = [ScoredFileItem]()
var spinLock = OS_SPINLOCK_INIT
dispatch_apply(chunksCount, dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) { [unowned self] idx in
if self.cancelled {
return
@ -78,9 +77,9 @@ class OpenQuicklyFilterOperation: NSOperation {
return
}
OSSpinLockLock(&self.spinLock)
OSSpinLockLock(&spinLock)
result.appendContentsOf(chunkedResult)
OSSpinLockUnlock(&self.spinLock)
OSSpinLockUnlock(&spinLock)
}
if self.cancelled {