Skip to content

Commit 428ee8c

Browse files
committed
[Concurrency] Don't use blocks.
We can't use blocks, because Swift doesn't support them on Linux or Windows. Instead, use a C function pointer, and box up the handler. rdar://141348916
1 parent bcfef22 commit 428ee8c

File tree

2 files changed

+46
-7
lines changed

2 files changed

+46
-7
lines changed

stdlib/public/Concurrency/ExecutorBridge.cpp

+8-3
Original file line numberDiff line numberDiff line change
@@ -120,24 +120,29 @@ void *swift_job_getExecutorPrivateData(Job *job) {
120120

121121
#if !SWIFT_CONCURRENCY_EMBEDDED
122122
extern "C" SWIFT_CC(swift)
123-
void *swift_createDispatchEvent(void (^handler)()) {
123+
void *swift_createDispatchEventC(void (*handler)(void *), void *context) {
124124
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_OR,
125125
0, 0,
126126
dispatch_get_main_queue());
127-
dispatch_source_set_event_handler(source, handler);
127+
dispatch_source_set_event_handler_f(source, handler);
128128
dispatch_activate(source);
129129

130130
return source;
131131
}
132132

133133
extern "C" SWIFT_CC(swift)
134-
void swift_destroyDispatchEvent(void *event) {
134+
void swift_destroyDispatchEventC(void *event) {
135135
dispatch_source_t source = (dispatch_source_t)event;
136136

137137
dispatch_source_cancel(source);
138138
dispatch_release(source);
139139
}
140140

141+
extern "C" SWIFT_CC(swift)
142+
void *swift_getDispatchEventContext(void *event) {
143+
return dispatch_get_context((dispatch_source_t)event);
144+
}
145+
141146
extern "C" SWIFT_CC(swift)
142147
void swift_signalDispatchEvent(void *event) {
143148
dispatch_source_t source = (dispatch_source_t)event;

stdlib/public/Concurrency/ExecutorBridge.swift

+38-4
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,46 @@ internal func _dispatchEnqueueWithDeadline(_ global: CBool,
114114
internal func _dispatchAssertMainQueue()
115115

116116
@available(SwiftStdlib 6.2, *)
117-
@_silgen_name("swift_createDispatchEvent")
118-
internal func _createDispatchEvent(handler: @convention(block) @escaping () -> ()) -> OpaquePointer
117+
@_silgen_name("swift_createDispatchEventC")
118+
internal func _createDispatchEventC(
119+
handler: @convention(c) @escaping (UnsafeMutableRawPointer) -> (),
120+
context: UnsafeMutableRawPointer
121+
) -> OpaquePointer
122+
123+
fileprivate class DispatchEventHandlerBox {
124+
var handler: () -> ()
125+
init(handler: @escaping () -> ()) {
126+
self.handler = handler
127+
}
128+
}
119129

120130
@available(SwiftStdlib 6.2, *)
121-
@_silgen_name("swift_destroyDispatchEvent")
122-
internal func _destroyDispatchEvent(_ event: OpaquePointer)
131+
internal func _createDispatchEvent(handler: @escaping () -> ()) -> OpaquePointer {
132+
let boxed = DispatchEventHandlerBox(handler: handler)
133+
let opaqueHandlerBox = Unmanaged.passRetained(boxed).toOpaque()
134+
return _createDispatchEventC(
135+
handler: { context in
136+
let unmanaged = Unmanaged<DispatchEventHandlerBox>.fromOpaque(context)
137+
unmanaged.takeUnretainedValue().handler()
138+
},
139+
context: opaqueHandlerBox
140+
)
141+
}
142+
143+
@available(SwiftStdlib 6.2, *)
144+
@_silgen_name("swift_destroyDispatchEventC")
145+
internal func _destroyDispatchEventC(_ event: OpaquePointer)
146+
147+
@available(SwiftStdlib 6.2, *)
148+
@_silgen_name("swift_getDispatchEventContext")
149+
internal func _getDispatchEventContext(_ event: OpaquePointer) -> UnsafeMutableRawPointer
150+
151+
@available(SwiftStdlib 6.2, *)
152+
internal func _destroyDispatchEvent(_ event: OpaquePointer) {
153+
let context = _getDispatchEventContext(event)
154+
Unmanaged<DispatchEventHandlerBox>.fromOpaque(context).release()
155+
_destroyDispatchEventC(event)
156+
}
123157

124158
@available(SwiftStdlib 6.2, *)
125159
@_silgen_name("swift_signalDispatchEvent")

0 commit comments

Comments
 (0)