Skip to content

Commit b4f96b8

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 5160d19 commit b4f96b8

File tree

2 files changed

+46
-7
lines changed

2 files changed

+46
-7
lines changed

Diff for: stdlib/public/Concurrency/ExecutorBridge.cpp

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

8585
#if !SWIFT_CONCURRENCY_EMBEDDED
8686
extern "C" SWIFT_CC(swift)
87-
void *swift_createDispatchEvent(void (^handler)()) {
87+
void *swift_createDispatchEventC(void (*handler)(void *), void *context) {
8888
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_OR,
8989
0, 0,
9090
dispatch_get_main_queue());
91-
dispatch_source_set_event_handler(source, handler);
91+
dispatch_source_set_event_handler_f(source, handler);
9292
dispatch_activate(source);
9393

9494
return source;
9595
}
9696

9797
extern "C" SWIFT_CC(swift)
98-
void swift_destroyDispatchEvent(void *event) {
98+
void swift_destroyDispatchEventC(void *event) {
9999
dispatch_source_t source = (dispatch_source_t)event;
100100

101101
dispatch_source_cancel(source);
102102
dispatch_release(source);
103103
}
104104

105+
extern "C" SWIFT_CC(swift)
106+
void *swift_getDispatchEventContext(void *event) {
107+
return dispatch_get_context((dispatch_source_t)event);
108+
}
109+
105110
extern "C" SWIFT_CC(swift)
106111
void swift_signalDispatchEvent(void *event) {
107112
dispatch_source_t source = (dispatch_source_t)event;

Diff for: stdlib/public/Concurrency/ExecutorBridge.swift

+38-4
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,46 @@ internal func _dispatchEnqueueWithDeadline(_ global: CBool,
106106
internal func _dispatchAssertMainQueue()
107107

108108
@available(SwiftStdlib 6.2, *)
109-
@_silgen_name("swift_createDispatchEvent")
110-
internal func _createDispatchEvent(handler: @convention(block) @escaping () -> ()) -> OpaquePointer
109+
@_silgen_name("swift_createDispatchEventC")
110+
internal func _createDispatchEventC(
111+
handler: @convention(c) @escaping (UnsafeMutableRawPointer) -> (),
112+
context: UnsafeMutableRawPointer
113+
) -> OpaquePointer
114+
115+
fileprivate class DispatchEventHandlerBox {
116+
var handler: () -> ()
117+
init(handler: @escaping () -> ()) {
118+
self.handler = handler
119+
}
120+
}
111121

112122
@available(SwiftStdlib 6.2, *)
113-
@_silgen_name("swift_destroyDispatchEvent")
114-
internal func _destroyDispatchEvent(_ event: OpaquePointer)
123+
internal func _createDispatchEvent(handler: @escaping () -> ()) -> OpaquePointer {
124+
let boxed = DispatchEventHandlerBox(handler: handler)
125+
let opaqueHandlerBox = Unmanaged.passRetained(boxed).toOpaque()
126+
return _createDispatchEventC(
127+
handler: { context in
128+
let unmanaged = Unmanaged<DispatchEventHandlerBox>.fromOpaque(context)
129+
unmanaged.takeUnretainedValue().handler()
130+
},
131+
context: opaqueHandlerBox
132+
)
133+
}
134+
135+
@available(SwiftStdlib 6.2, *)
136+
@_silgen_name("swift_destroyDispatchEventC")
137+
internal func _destroyDispatchEventC(_ event: OpaquePointer)
138+
139+
@available(SwiftStdlib 6.2, *)
140+
@_silgen_name("swift_getDispatchEventContext")
141+
internal func _getDispatchEventContext(_ event: OpaquePointer) -> UnsafeMutableRawPointer
142+
143+
@available(SwiftStdlib 6.2, *)
144+
internal func _destroyDispatchEvent(_ event: OpaquePointer) {
145+
let context = _getDispatchEventContext(event)
146+
Unmanaged<DispatchEventHandlerBox>.fromOpaque(context).release()
147+
_destroyDispatchEventC(event)
148+
}
115149

116150
@available(SwiftStdlib 6.2, *)
117151
@_silgen_name("swift_signalDispatchEvent")

0 commit comments

Comments
 (0)