Skip to content

Commit c1afdcb

Browse files
committed
Initial Swift3 wrapping overlay for libdispatch
A useful checkpoint along the way to a complete implementation of the Swift3 overlay for libdispatch on non-Objective C platforms. The overlay code builds successfully and simple example programs using queues and timers work as expected. The basic approach is to wrap the C libdispatch objects in Swift objects and make the C dispatch APIs available internally via the CDispatch module. A few pieces (marked with FIXME) are ifdefed out to avoid compilation problems (will get back to them in later commits) or still need to be implemented (release on deinit). Although the installed libdispatch can be used in Swift programs via 'import Dispatch', the swiftc command for the client program currently needs to pass additional command line flags (to be fixed later). For example: swiftc -Xcc -fblocks -Xcc -D__DISPATCH_BUILDING_SWIFT_MODULE__=1 Forever.swift
1 parent 045f499 commit c1afdcb

15 files changed

+610
-305
lines changed

dispatch/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@ dispatch_HEADERS= \
2424
time.h
2525

2626
if HAVE_SWIFT
27-
dispatch_HEADERS+=module.map
27+
dispatch_HEADERS+=module.modulemap
2828
endif

dispatch/module.map

Lines changed: 0 additions & 7 deletions
This file was deleted.

dispatch/module.modulemap

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
1-
module Dispatch [system] [extern_c] {
2-
umbrella header "dispatch.h"
3-
module * { export * }
1+
module Dispatch {
2+
requires blocks
43
export *
4+
link "dispatch"
5+
link "BlocksRuntime"
56
}
67

78
module DispatchIntrospection [system] [extern_c] {
89
header "introspection.h"
910
export *
1011
}
12+
13+
module CDispatch [system] [extern_c] {
14+
umbrella header "dispatch.h"
15+
module * { export * }
16+
export *
17+
requires blocks
18+
link "dispatch"
19+
link "BlocksRuntime"
20+
}

src/Makefile.am

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -114,43 +114,62 @@ DTRACE_SOURCES=provider.h
114114
endif
115115

116116
if HAVE_SWIFT
117-
libdispatch_la_SOURCES+=swift/Dispatch.mm
118-
EXTRA_libdispatch_la_SOURCES+= \
119-
swift/Dispatch.swift \
117+
SWIFT_SRC_FILES=\
120118
swift/Block.swift \
121119
swift/Data.swift \
122120
swift/Dispatch.swift \
123121
swift/IO.swift \
124122
swift/Private.swift \
125123
swift/Queue.swift \
126124
swift/Source.swift \
127-
swift/Time.swift
128-
129-
EXTRA_libdispatch_la_DEPENDENCIES+=$(abs_builddir)/Dispatch.o $(abs_builddir)/Dispatch.swiftmodule
130-
libdispatch_la_LIBADD+=$(abs_builddir)/Dispatch.o
131-
132-
SWIFT_OBJECTS= \
133-
$(abs_builddir)/Dispatch.swiftmodule \
134-
$(abs_builddir)/Dispatch.swiftdoc \
135-
$(abs_builddir)/Dispatch.o
136-
137-
SWIFTC_FLAGS = -Xcc -D__DISPATCH_BUILDING_SWIFT_MODULE__=1 -Xcc -fmodule-map-file=$(abs_top_srcdir)/dispatch/module.map -I$(abs_top_srcdir) -parse-as-library -Xcc -fblocks
138-
139-
$(abs_builddir)/Dispatch.o: $(abs_srcdir)/swift/Dispatch.swift
140-
$(SWIFTC) $(SWIFTC_FLAGS) -c -o $@ $<
141-
142-
$(abs_builddir)/Dispatch.swiftmodule: $(abs_srcdir)/swift/Dispatch.swift
143-
$(SWIFTC) $(SWIFTC_FLAGS) -emit-module -emit-module-path $@ $<
125+
swift/Time.swift \
126+
swift/Wrapper.swift
127+
128+
SWIFT_ABS_SRC_FILES = $(SWIFT_SRC_FILES:%=$(abs_srcdir)/%)
129+
SWIFT_OBJ_FILES = $(SWIFT_SRC_FILES:%.swift=$(abs_builddir)/%.o)
130+
131+
libdispatch_la_SOURCES+=swift/DispatchStubs.cc
132+
EXTRA_libdispatch_la_SOURCES+=$(SWIFT_SRC_FILES)
133+
134+
EXTRA_libdispatch_la_DEPENDENCIES+=$(SWIFT_OBJ_FILES) $(abs_builddir)/swift/Dispatch.swiftmodule
135+
libdispatch_la_LIBADD+=$(SWIFT_OBJ_FILES)
136+
137+
SWIFT_GEN_FILES= \
138+
$(abs_builddir)/swift/Dispatch.swiftmodule \
139+
$(abs_builddir)/swift/Dispatch.swiftdoc \
140+
$(SWIFT_OBJ_FILES) \
141+
$(SWIFT_OBJ_FILES:%=%.d) \
142+
$(SWIFT_OBJ_FILES:%=%.swiftdeps) \
143+
$(SWIFT_OBJ_FILES:%=%.~partial.swiftmodule) \
144+
$(SWIFT_OBJ_FILES:%=%.~partial.swiftdoc) \
145+
$(SWIFT_OBJ_FILES:%=%.~partial.swiftdeps)
146+
147+
SWIFTC_FLAGS = -Xcc -D__DISPATCH_BUILDING_SWIFT_MODULE__=1 -Xcc -fmodule-map-file=$(abs_top_srcdir)/dispatch/module.modulemap -I$(abs_top_srcdir) -Xcc -fblocks
148+
149+
$(abs_builddir)/swift/%.o: $(abs_srcdir)/swift/%.swift
150+
$(SWIFTC) -frontend -c $(SWIFT_ABS_SRC_FILES) -primary-file $< \
151+
$(SWIFTC_FLAGS) -module-name Dispatch -module-link-name dispatch \
152+
-o $@ -emit-module-path $@.~partial.swiftmodule \
153+
-emit-module-doc-path $@.~partial.swiftdoc -emit-dependencies-path $@.d \
154+
-emit-reference-dependencies-path $@.swiftdeps \
155+
-module-cache-path $(top_builddir)
156+
157+
$(abs_builddir)/swift/Dispatch.swiftmodule: $(SWIFT_ABS_SRC_FILES)
158+
$(SWIFTC) -frontend -emit-module $(SWIFT_OBJ_FILES:%=%.~partial.swiftmodule) \
159+
$(SWIFTC_FLAGS) -module-cache-path $(top_builddir) -module-link-name dispatch \
160+
-o $@ -emit-module-doc-path $(@:%.swiftmodule=%.swiftdoc)
144161

145162
if HAVE_SWIFT
146163
swiftmoddir=${prefix}/lib/swift/linux/${build_cpu}
147-
swiftmod_HEADERS=$(abs_builddir)/Dispatch.swiftmodule $(abs_builddir)/Dispatch.swiftdoc
164+
swiftmod_HEADERS=\
165+
$(abs_builddir)/swift/Dispatch.swiftmodule \
166+
$(abs_builddir)/swift/Dispatch.swiftdoc
148167
endif
149168

150169
endif
151170

152171
BUILT_SOURCES=$(MIG_SOURCES) $(DTRACE_SOURCES)
153172
nodist_libdispatch_la_SOURCES=$(BUILT_SOURCES)
154-
CLEANFILES=$(BUILT_SOURCES) $(SWIFT_OBJECTS)
173+
CLEANFILES=$(BUILT_SOURCES) $(SWIFT_GEN_FILES)
155174
DISTCLEANFILES=pthread_machdep.h pthread System mach objc
156175

src/data.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ const dispatch_block_t _dispatch_data_destructor_none = ^{
108108
DISPATCH_INTERNAL_CRASH(0, "none destructor called");
109109
};
110110

111+
const dispatch_block_t _dispatch_data_destructor_munmap = ^{
112+
DISPATCH_INTERNAL_CRASH(0, "munmap destructor called");
113+
};
114+
111115
const dispatch_block_t _dispatch_data_destructor_vm_deallocate = ^{
112116
DISPATCH_INTERNAL_CRASH(0, "vmdeallocate destructor called");
113117
};

src/swift/Block.swift

Lines changed: 16 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
import CDispatch
14+
1315
public struct DispatchWorkItemFlags : OptionSet, RawRepresentable {
1416
public let rawValue: UInt
1517
public init(rawValue: UInt) { self.rawValue = rawValue }
@@ -38,14 +40,14 @@ public class DispatchWorkItem {
3840
internal var _group: DispatchGroup?
3941

4042
public init(group: DispatchGroup? = nil, qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], block: @convention(block) () -> ()) {
41-
_block = _swift_dispatch_block_create_with_qos_class(__dispatch_block_flags_t(flags.rawValue),
42-
qos.qosClass.rawValue, Int32(qos.relativePriority), block)
43+
_block = dispatch_block_create_with_qos_class(dispatch_block_flags_t(flags.rawValue),
44+
qos.qosClass.rawValue.rawValue, Int32(qos.relativePriority), block)
4345
}
4446

4547
// Used by DispatchQueue.synchronously<T> to provide a @noescape path through
4648
// dispatch_block_t, as we know the lifetime of the block in question.
4749
internal init(flags: DispatchWorkItemFlags = [], noescapeBlock: @noescape () -> ()) {
48-
_block = _swift_dispatch_block_create_noescape(__dispatch_block_flags_t(flags.rawValue), noescapeBlock)
50+
_block = _swift_dispatch_block_create_noescape(dispatch_block_flags_t(flags.rawValue), noescapeBlock)
4951
}
5052

5153
public func perform() {
@@ -57,36 +59,36 @@ public class DispatchWorkItem {
5759
}
5860

5961
public func wait() {
60-
_ = _swift_dispatch_block_wait(_block, DispatchTime.distantFuture.rawValue)
62+
_ = dispatch_block_wait(_block, DispatchTime.distantFuture.rawValue)
6163
}
6264

6365
public func wait(timeout: DispatchTime) -> DispatchTimeoutResult {
64-
return _swift_dispatch_block_wait(_block, timeout.rawValue) == 0 ? .Success : .TimedOut
66+
return dispatch_block_wait(_block, timeout.rawValue) == 0 ? .Success : .TimedOut
6567
}
6668

6769
public func wait(wallTimeout: DispatchWallTime) -> DispatchTimeoutResult {
68-
return _swift_dispatch_block_wait(_block, wallTimeout.rawValue) == 0 ? .Success : .TimedOut
70+
return dispatch_block_wait(_block, wallTimeout.rawValue) == 0 ? .Success : .TimedOut
6971
}
7072

7173
public func notify(qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], queue: DispatchQueue, execute: @convention(block) () -> Void) {
7274
if qos != .unspecified || !flags.isEmpty {
7375
let item = DispatchWorkItem(qos: qos, flags: flags, block: execute)
74-
_swift_dispatch_block_notify(_block, queue, item._block)
76+
dispatch_block_notify(_block, queue.__wrapped, item._block)
7577
} else {
76-
_swift_dispatch_block_notify(_block, queue, execute)
78+
dispatch_block_notify(_block, queue.__wrapped, execute)
7779
}
7880
}
7981

8082
public func notify(queue: DispatchQueue, execute: DispatchWorkItem) {
81-
_swift_dispatch_block_notify(_block, queue, execute._block)
83+
dispatch_block_notify(_block, queue.__wrapped, execute._block)
8284
}
8385

8486
public func cancel() {
85-
_swift_dispatch_block_cancel(_block)
87+
dispatch_block_cancel(_block)
8688
}
8789

8890
public var isCancelled: Bool {
89-
return _swift_dispatch_block_testcancel(_block) != 0
91+
return dispatch_block_testcancel(_block) != 0
9092
}
9193
}
9294

@@ -96,7 +98,7 @@ public extension DispatchWorkItem {
9698
public func wait(timeout: DispatchWallTime) -> Int {
9799
switch wait(wallTimeout: timeout) {
98100
case .Success: return 0
99-
case .TimedOut: return Int(KERN_OPERATION_TIMED_OUT)
101+
case .TimedOut: return DispatchTimeoutResult.KERN_OPERATION_TIMED_OUT
100102
}
101103
}
102104
}
@@ -106,26 +108,7 @@ public extension DispatchWorkItem {
106108
/// C blocks and Swift closures, which interferes with dispatch APIs that depend
107109
/// on the referential identity of a block. Particularly, dispatch_block_create.
108110
internal typealias _DispatchBlock = @convention(block) () -> Void
109-
110-
/// APINotes also removes the old dispatch_block_t typedef from the Dispatch module
111-
/// completely. In doing so it causes the dispatch_block_* API to lose their
112-
/// @convention(block) attributes. As such, all of the entry points are shimmed
113-
//// through Dispatch.mm with _DispatchBlock types.
114-
@_silgen_name("_swift_dispatch_block_create_with_qos_class")
115-
internal func _swift_dispatch_block_create_with_qos_class(_ flags: __dispatch_block_flags_t, _ qos: qos_class_t, _ relativePriority: Int32, _ block: _DispatchBlock) -> _DispatchBlock
111+
internal typealias dispatch_block_t = @convention(block) () -> Void
116112

117113
@_silgen_name("_swift_dispatch_block_create_noescape")
118-
internal func _swift_dispatch_block_create_noescape(_ flags: __dispatch_block_flags_t, _ block: @noescape () -> ()) -> _DispatchBlock
119-
120-
@_silgen_name("_swift_dispatch_block_wait")
121-
internal func _swift_dispatch_block_wait(_ block: _DispatchBlock, _ timeout: UInt64) -> Int
122-
123-
@_silgen_name("_swift_dispatch_block_notify")
124-
internal func _swift_dispatch_block_notify(_ block: _DispatchBlock, _ queue: DispatchQueue, _ notifier: _DispatchBlock)
125-
126-
@_silgen_name("_swift_dispatch_block_cancel")
127-
internal func _swift_dispatch_block_cancel(_ block: _DispatchBlock)
128-
129-
@_silgen_name("_swift_dispatch_block_testcancel")
130-
internal func _swift_dispatch_block_testcancel(_ block: _DispatchBlock) -> Int
131-
114+
internal func _swift_dispatch_block_create_noescape(_ flags: dispatch_block_flags_t, _ block: @noescape () -> ()) -> _DispatchBlock

0 commit comments

Comments
 (0)