New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SR-737] [dispatch] dispatch_queue_create has wrong return type #755
Comments
cc: dgrove-oss (JIRA User) |
Comment by David Grove (JIRA) This is a general problem on Linux right now because of the lack of objective C. The importer appears to not understand the transparent union type dispatch_object_t, so none of the API functions that take dispatch_object_t currently work from Swift. Need to figure out if it is practical to get the importer to understand the transparent union, or if we need to add a whole slew of wrapper functions to do the translations. |
It's not specifically the transparent_union that's the problem, but the fact that none of these types have definitions. Swift currently doesn't have a good way to represent a pointer to a forward-declared struct/union/enum; it doesn't just pretend they're empty because you might import the definition later on in your REPL session. We definitely need a better answer than that, though. |
Comment by David Grove (JIRA) Thanks for the correction Jordan. I did some quick greps to try to scope the problem. There are fewer API functions that use dispatch_object_t than I'd guessed before looking. All of these functions only take 1 parameter of type dispatch_object_t (so no combinatorial explosion). So perhaps working around it via some overloaded functions in the Linux overlay isn't totally impractical. In the public .h files, dispatch_object_t only shows up in introspection.h (3 functions: dispatch_introspection_hook_queue_item_enqueue, dispatch_introspection_hook_queue_item_dequeue, dispatch_introspection_hook_queue_item_complete) queue.h (1 function: dispatch_set_target_queue), and object.h (8 non-deprecated functions: dispatch_retain, dispatch_release, dispatch_get_context, dispatch_set_context, dispatch_set_finalizer_f, dispatch_suspend, dispatch_resume, dispatch_notify). @belkadan Do you think working around by defining a bunch of wrapper functions in the overlay is the way to tackle it (at least for now), or do you have another suggestion? thanks! |
Comment by David Grove (JIRA) I took a cut at fixing this by adding some overloaded functions to Dispatch.swift backed by C functions in swift_wrappers.c It almost works, but there is something I'm not understanding about the dialect of Swift that needs to be used in Dispatch.swift or in how the types are being imported. In particular, I would like to write a set of overloaded functions like: public func dispatch_resume(obj:dispatch_queue_t) {
_swift_dispatch_resume_for_queue(obj)
}
public func dispatch_resume(obj:dispatch_source_t) {
_swift_dispatch_resume_for_source(obj)
} If I import Dispatch to get dispatch_queue_t and dispatch_object_t, then swiftc rejects the code saying:
If I don't import Dispatch and provide dummy definitions public class dispatch_queue_t { }
public class dispatch_source_t { } then the overloaded functions compile just fine (no complaint about redeclaring dispatch_resume). Is the problem that we can't overload on COpaquePointer (no matter what name it was given)? Is there some annotation or pragma that would help? Note that if I don't overload (for example, just define for dispatch_queue_t), then libdispatch builds successfully and programs linked against it can call dispatch_suspend and dispatch_resume on a dispatch_queue_t. Code is sitting on a branch if looking at it helps suggest an approach I should try: https://github.com/dgrove-oss/swift-corelibs-libdispatch/tree/SR-737 |
Right now on Linux, ...since the typealias was erased, the function signature becomes You're correct that when you declare e.g. Whether or not it will run is a different story. I expect something bad will happen if you try to bridge (e.g., via pointer) a Swift object and whatever the implementation of My suggestion would be to try and vend our own wrapper class in Swift-land, along the lines of class dispatch_object_t {
private var linuxImplementation: COpaquePointer
dealloc() {
dispatch_release(linuxImplementation)
}
}
class dispatch_queue_t : dispatch_object_t { }
func dispatch_resume(obj: dispatch_queue_t) {
_underlying_c_libdispatch_resume(obj.linuxImplementation)
} etc. The big idea here is that a "real" Swift class would be refcountable by the Swift runtime, so it would behave to clients exactly as they expect from Darwin/ObjC. However, we would have to wrap the dispatch_functions as well, to pull out the COpaquePointer from inside the wrapper. I think something along these lines would cleanly solve SR-740 as well. One thing I don't know is how to make sure clients see the wrapper functions, and not the C functions being wrapped. I assume there's an annotation for this, but I don't actually know. |
Context for COpaquePointer: if you're in the REPL, you might import one module that has an incomplete struct type, do something with it, and then import another module that has the definition. We definitely don't want to be updating existing types in your session, so we had to pick a different type. Replacing COpaquePointer with some kind of OpaquePointer<T> (or just UnsafePointer<T> with a zero-sized type, which shouldn't be able to do any harm) is definitely something to look into, but we'd need to be careful how it interacts with the REPL. Literally every other context (libraries, scripts, playgrounds) is compiled all at once, though, so the REPL solution doesn't have to be perfect. |
Comment by David Grove (JIRA) I'll explore some options next week. I think we want a final solution that doesn't require wrapping for efficiency. We have complete control over the "shape" of the C dispatch objects on Linux, so we should be able to give them headers that are compatible with Swift objects. Right now they are given headers that are compatible with objective C (even though they are not objective C objects). Similarly, we can redirect dispatch_retain/release functions to the Swift impls. @belkadan, where would I look to find the canonical definition of a Swift object header? Ideally there would be a .h file somewhere I could include into libdispatch when building it with Swift support (libdispatch has an autoconf flag for Swift already that could be used to guard the include). |
That's a fascinating approach. Unfortunately I don't know enough about Swift internals to be a lot of help here. I do have some other unrelated cases where I'm interested in "spoofing" Swift objects, so I am fascinated to follow what goes on here. |
Comment by David Grove (JIRA) After quite a bit of exploring alternatives, I decided that changing libdispatch to implement the Swift object model was too invasive a change to libdispatch. So, I went back to the straightforward vending approach and submitted #61 which fixes this issue. |
Comment by David Grove (JIRA) made obsolete by Swift 3 dispatch overlay changes. |
Environment
Linux x64
swift-DEVELOPMENT-SNAPSHOT-2016-02-08-a
Additional Detail from JIRA
md5: e7691fb73226e77e3cd6b0d9ebce19d7
Issue Description:
dispatch_queue_create
on Linux has return type ofCOpaquePointer
whereas a return type ofdispatch_queue_t!
is expected.To reproduce in my Docker image:
Expected results: success
Actual results:
The text was updated successfully, but these errors were encountered: