Skip to content

Commit 0d9628a

Browse files
dgrove-ossparkera
authored andcommitted
port to Swift3 Dispatch API (#434)
Swift code compiles against current master branch of Dispatch with Swift3 wrapping overlay and CF runloop support from PR#101.
1 parent 8ae84af commit 0d9628a

File tree

3 files changed

+50
-51
lines changed

3 files changed

+50
-51
lines changed

CoreFoundation/RunLoop.subproj/CFRunLoop.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,12 @@ extern void _dispatch_main_queue_callback_4CF(mach_msg_header_t *msg);
6161
#elif DEPLOYMENT_TARGET_WINDOWS
6262
#include <process.h>
6363
DISPATCH_EXPORT HANDLE _dispatch_get_main_queue_handle_4CF(void);
64-
DISPATCH_EXPORT void _dispatch_main_queue_callback_4CF(void);
64+
DISPATCH_EXPORT void _dispatch_main_queue_callback_4CF(void*);
6565

6666
#define MACH_PORT_NULL 0
6767
#define mach_port_name_t HANDLE
6868
#define mach_port_t HANDLE
6969
#define _dispatch_get_main_queue_port_4CF _dispatch_get_main_queue_handle_4CF
70-
#define _dispatch_main_queue_callback_4CF(x) _dispatch_main_queue_callback_4CF()
7170

7271
#define AbsoluteTime LARGE_INTEGER
7372

@@ -78,8 +77,7 @@ DISPATCH_EXPORT void _dispatch_main_queue_callback_4CF(void);
7877
#include <sys/eventfd.h>
7978
#include <sys/timerfd.h>
8079

81-
#define _dispatch_get_main_queue_port_4CF dispatch_get_main_queue_eventfd_4CF
82-
#define _dispatch_main_queue_callback_4CF(x) dispatch_main_queue_drain_4CF()
80+
#define _dispatch_get_main_queue_port_4CF _dispatch_get_main_queue_handle_4CF
8381
#endif
8482

8583
#if DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_IPHONESIMULATOR || DEPLOYMENT_TARGET_LINUX

Foundation/NSOperation.swift

Lines changed: 47 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,24 @@ public class Operation: NSObject {
2626
internal var _ready = false
2727
internal var _dependencies = Set<Operation>()
2828
#if DEPLOYMENT_ENABLE_LIBDISPATCH
29-
internal var _group = dispatch_group_create()
30-
internal var _depGroup = dispatch_group_create()
31-
internal var _groups = [dispatch_group_t]()
29+
internal var _group = DispatchGroup()
30+
internal var _depGroup = DispatchGroup()
31+
internal var _groups = [DispatchGroup]()
3232
#endif
3333

3434
public override init() {
3535
super.init()
3636
#if DEPLOYMENT_ENABLE_LIBDISPATCH
37-
dispatch_group_enter(_group)
37+
_group.enter()
3838
#endif
3939
}
4040

4141
internal func _leaveGroups() {
4242
// assumes lock is taken
4343
#if DEPLOYMENT_ENABLE_LIBDISPATCH
44-
_groups.forEach() { dispatch_group_leave($0) }
44+
_groups.forEach() { $0.leave() }
4545
_groups.removeAll()
46-
dispatch_group_leave(_group)
46+
_group.leave()
4747
#endif
4848
}
4949

@@ -65,7 +65,7 @@ public class Operation: NSObject {
6565
// The completion block property is a bit cagey and can not be executed locally on the queue due to thread exhaust potentials.
6666
// This sets up for some strange behavior of finishing operations since the handler will be executed on a different queue
6767
if let completion = completionBlock {
68-
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) { () -> Void in
68+
DispatchQueue.global(attributes: .qosBackground).async { () -> Void in
6969
completion()
7070
}
7171
}
@@ -107,7 +107,7 @@ public class Operation: NSObject {
107107
_dependencies.insert(op)
108108
op.lock.lock()
109109
#if DEPLOYMENT_ENABLE_LIBDISPATCH
110-
dispatch_group_enter(_depGroup)
110+
_depGroup.enter()
111111
op._groups.append(_depGroup)
112112
#endif
113113
op.lock.unlock()
@@ -122,7 +122,7 @@ public class Operation: NSObject {
122122
let groupIndex = op._groups.index(where: { $0 === self._depGroup })
123123
if let idx = groupIndex {
124124
let group = op._groups.remove(at: idx)
125-
dispatch_group_leave(group)
125+
group.leave()
126126
}
127127
#endif
128128
op.lock.unlock()
@@ -140,7 +140,7 @@ public class Operation: NSObject {
140140
public var completionBlock: (() -> Void)?
141141
public func waitUntilFinished() {
142142
#if DEPLOYMENT_ENABLE_LIBDISPATCH
143-
dispatch_group_wait(_group, DISPATCH_TIME_FOREVER)
143+
_group.wait()
144144
#endif
145145
}
146146

@@ -153,7 +153,7 @@ public class Operation: NSObject {
153153

154154
internal func _waitUntilReady() {
155155
#if DEPLOYMENT_ENABLE_LIBDISPATCH
156-
dispatch_group_wait(_depGroup, DISPATCH_TIME_FOREVER)
156+
_depGroup.wait()
157157
#endif
158158
_ready = true
159159
}
@@ -296,14 +296,14 @@ internal struct _OperationList {
296296
public class OperationQueue: NSObject {
297297
let lock = Lock()
298298
#if DEPLOYMENT_ENABLE_LIBDISPATCH
299-
var __concurrencyGate: dispatch_semaphore_t?
300-
var __underlyingQueue: dispatch_queue_t?
301-
let queueGroup = dispatch_group_create()
299+
var __concurrencyGate: DispatchSemaphore?
300+
var __underlyingQueue: DispatchQueue?
301+
let queueGroup = DispatchGroup()
302302
#endif
303303

304304
var _operations = _OperationList()
305305
#if DEPLOYMENT_ENABLE_LIBDISPATCH
306-
internal var _concurrencyGate: dispatch_semaphore_t? {
306+
internal var _concurrencyGate: DispatchSemaphore? {
307307
get {
308308
lock.lock()
309309
let val = __concurrencyGate
@@ -314,7 +314,7 @@ public class OperationQueue: NSObject {
314314

315315
// This is NOT the behavior of the objective-c variant; it will never re-use a queue and instead for every operation it will create a new one.
316316
// However this is considerably faster and probably more effecient.
317-
internal var _underlyingQueue: dispatch_queue_t {
317+
internal var _underlyingQueue: DispatchQueue {
318318
lock.lock()
319319
if let queue = __underlyingQueue {
320320
lock.unlock()
@@ -326,18 +326,18 @@ public class OperationQueue: NSObject {
326326
} else {
327327
effectiveName = "NSOperationQueue::\(unsafeAddress(of: self))"
328328
}
329-
let attr: dispatch_queue_attr_t?
329+
let attr: DispatchQueueAttributes
330330
if maxConcurrentOperationCount == 1 {
331-
attr = DISPATCH_QUEUE_SERIAL
331+
attr = .serial
332332
} else {
333-
attr = DISPATCH_QUEUE_CONCURRENT
333+
attr = .concurrent
334334
if maxConcurrentOperationCount != NSOperationQueueDefaultMaxConcurrentOperationCount {
335-
__concurrencyGate = dispatch_semaphore_create(maxConcurrentOperationCount)
335+
__concurrencyGate = DispatchSemaphore(value:maxConcurrentOperationCount)
336336
}
337337
}
338-
let queue = dispatch_queue_create(effectiveName, attr)
338+
let queue = DispatchQueue(label: effectiveName, attributes: attr)
339339
if _suspended {
340-
dispatch_suspend(queue)
340+
queue.suspend()
341341
}
342342
__underlyingQueue = queue
343343
lock.unlock()
@@ -351,12 +351,11 @@ public class OperationQueue: NSObject {
351351
}
352352

353353
#if DEPLOYMENT_ENABLE_LIBDISPATCH
354-
internal init(_queue queue: dispatch_queue_t, maxConcurrentOperations: Int = NSOperationQueueDefaultMaxConcurrentOperationCount) {
354+
internal init(_queue queue: DispatchQueue, maxConcurrentOperations: Int = NSOperationQueueDefaultMaxConcurrentOperationCount) {
355355
__underlyingQueue = queue
356356
maxConcurrentOperationCount = maxConcurrentOperations
357357
super.init()
358-
dispatch_queue_set_specific(queue, OperationQueue.OperationQueueKey, unsafeBitCast(Unmanaged.passUnretained(self), to: UnsafeMutablePointer<Void>.self), nil)
359-
358+
queue.setSpecific(key: OperationQueue.OperationQueueKey, value: Unmanaged.passUnretained(self))
360359
}
361360
#endif
362361

@@ -384,9 +383,9 @@ public class OperationQueue: NSObject {
384383

385384
public func addOperations(_ ops: [Operation], waitUntilFinished wait: Bool) {
386385
#if DEPLOYMENT_ENABLE_LIBDISPATCH
387-
var waitGroup: dispatch_group_t?
386+
var waitGroup: DispatchGroup?
388387
if wait {
389-
waitGroup = dispatch_group_create()
388+
waitGroup = DispatchGroup()
390389
}
391390
#endif
392391
/*
@@ -406,27 +405,27 @@ public class OperationQueue: NSObject {
406405
lock.unlock()
407406
#if DEPLOYMENT_ENABLE_LIBDISPATCH
408407
if let group = waitGroup {
409-
dispatch_group_enter(group)
408+
group.enter()
410409
}
411-
412-
let block = dispatch_block_create(DISPATCH_BLOCK_ENFORCE_QOS_CLASS) { () -> Void in
410+
411+
let block = DispatchWorkItem(group: queueGroup, flags: .enforceQoS) { () -> Void in
413412
if let sema = self._concurrencyGate {
414-
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER)
413+
sema.wait()
415414
self._runOperation()
416-
dispatch_semaphore_signal(sema)
415+
sema.signal()
417416
} else {
418417
self._runOperation()
419418
}
420419
if let group = waitGroup {
421-
dispatch_group_leave(group)
420+
group.leave()
422421
}
423422
}
424-
dispatch_group_async(queueGroup, _underlyingQueue, block)
423+
_underlyingQueue.async(execute: block)
425424
#endif
426425
}
427426
#if DEPLOYMENT_ENABLE_LIBDISPATCH
428427
if let group = waitGroup {
429-
dispatch_group_wait(group, DISPATCH_TIME_FOREVER)
428+
group.wait()
430429
}
431430
#endif
432431
}
@@ -474,9 +473,9 @@ public class OperationQueue: NSObject {
474473
#if DEPLOYMENT_ENABLE_LIBDISPATCH
475474
if let queue = __underlyingQueue {
476475
if newValue {
477-
dispatch_suspend(queue)
476+
queue.suspend()
478477
} else {
479-
dispatch_resume(queue)
478+
queue.resume()
480479
}
481480
}
482481
#endif
@@ -507,7 +506,7 @@ public class OperationQueue: NSObject {
507506
#if DEPLOYMENT_ENABLE_LIBDISPATCH
508507
// Note: this will return non nil whereas the objective-c version will only return non nil when it has been set.
509508
// it uses a target queue assignment instead of returning the actual underlying queue.
510-
public var underlyingQueue: dispatch_queue_t? {
509+
public var underlyingQueue: DispatchQueue? {
511510
get {
512511
lock.lock()
513512
let queue = __underlyingQueue
@@ -531,23 +530,25 @@ public class OperationQueue: NSObject {
531530

532531
public func waitUntilAllOperationsAreFinished() {
533532
#if DEPLOYMENT_ENABLE_LIBDISPATCH
534-
dispatch_group_wait(queueGroup, DISPATCH_TIME_FOREVER)
533+
queueGroup.wait()
535534
#endif
536535
}
537536

538-
static let OperationQueueKey = UnsafePointer<Void>(UnsafeMutablePointer<Void>(allocatingCapacity: 1))
539-
537+
#if DEPLOYMENT_ENABLE_LIBDISPATCH
538+
static let OperationQueueKey = DispatchSpecificKey<Unmanaged<OperationQueue>>()
539+
#endif
540+
540541
public class func currentQueue() -> OperationQueue? {
541542
#if DEPLOYMENT_ENABLE_LIBDISPATCH
542-
let specific = dispatch_get_specific(OperationQueue.OperationQueueKey)
543+
let specific = DispatchQueue.getSpecific(key: OperationQueue.OperationQueueKey)
543544
if specific == nil {
544545
if pthread_main_np() == 1 {
545546
return OperationQueue.mainQueue()
546547
} else {
547548
return nil
548549
}
549550
} else {
550-
return Unmanaged<OperationQueue>.fromOpaque(unsafeBitCast(specific, to: UnsafePointer<Void>.self)).takeUnretainedValue()
551+
return specific!.takeUnretainedValue()
551552
}
552553
#else
553554
return nil
@@ -556,11 +557,11 @@ public class OperationQueue: NSObject {
556557

557558
public class func mainQueue() -> OperationQueue {
558559
#if DEPLOYMENT_ENABLE_LIBDISPATCH
559-
let specific = dispatch_queue_get_specific(dispatch_get_main_queue(), OperationQueue.OperationQueueKey)
560+
let specific = DispatchQueue.main.getSpecific(key: OperationQueue.OperationQueueKey)
560561
if specific == nil {
561-
return OperationQueue(_queue: dispatch_get_main_queue(), maxConcurrentOperations: 1)
562+
return OperationQueue(_queue: DispatchQueue.main, maxConcurrentOperations: 1)
562563
} else {
563-
return Unmanaged<OperationQueue>.fromOpaque(unsafeBitCast(specific, to: UnsafePointer<Void>.self)).takeUnretainedValue()
564+
return specific!.takeUnretainedValue()
564565
}
565566
#else
566567
fatalError("NSOperationQueue requires libdispatch")

build.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@
7777
swift_cflags += ([
7878
'-DDEPLOYMENT_ENABLE_LIBDISPATCH',
7979
'-I'+Configuration.current.variables["LIBDISPATCH_SOURCE_DIR"],
80-
'-I'+Configuration.current.variables["LIBDISPATCH_BUILD_DIR"]+'/src',
80+
'-I'+Configuration.current.variables["LIBDISPATCH_BUILD_DIR"]+'/src/swift',
8181
'-Xcc -fblocks'
8282
])
8383
foundation.LDFLAGS += '-ldispatch -L'+Configuration.current.variables["LIBDISPATCH_BUILD_DIR"]+'/src/.libs -rpath \$$ORIGIN '

0 commit comments

Comments
 (0)