Skip to content
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-14110] Allowing generics on @convention(c) functions #56496

Closed
swift-ci opened this issue Jan 26, 2021 · 4 comments
Closed

[SR-14110] Allowing generics on @convention(c) functions #56496

swift-ci opened this issue Jan 26, 2021 · 4 comments
Labels
attributes Feature: Declaration and type attributes c interop Feature: Interoperability with C compiler The Swift compiler in itself @convention Feature → attributes: the @convention attribute feature A feature request or implementation will not do Resolution: Will not be worked on

Comments

@swift-ci
Copy link
Collaborator

swift-ci commented Jan 26, 2021

Previous ID SR-14110
Radar rdar://problem/73742487
Original Reporter dead_bug (JIRA User)
Type New Feature
Status Resolved
Resolution Won't Do
Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels New Feature
Assignee None
Priority Medium

md5: 2adde8221da0f95bd9b4e43d48094398

Issue Description:

I have code that could use some threading to speed things up. None of existing primitives on osx seems sufficient for my task, except for POSIX threads, because this mechanism provides a fork-join model. To my great disappointment and surprise, I cannot pass anything polymorphic into a @convention(c) function. Could this be improved, please? I kinda need it asap, thanks.

This roughly how my original code looks like.

final class MyThing<Result> {
  var thread: pthread_t?
  var result: Result? = nil
     final class ThreadArgs {
      let target: Async<Result>
      let fn: () -> Result
      init(target:Async<Result>,fn:@escaping () -> Result) {
         self.target = target
         self.fn = fn
      }
   }
  init (_ block: @escaping () -> Result){
    let work: @convention(c) (UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? = { input in
      let args = input.load(as: ThreadArgs.self)
         args.target.result = args.fn ()
         return nil
    }
  }
  func await () -> Result {
    if result == nil {
      _ = pthread_join(thread!, nil)
    }
    return result!
}

The error is:

A C function pointer cannot be formed from a local closure that captures generic parameters
@typesanitizer
Copy link

@swift-ci create

@typesanitizer
Copy link

typesanitizer commented Jan 28, 2021

I understand being frustrated with a limitation in the language, but I feel that echoing it in a dramatic fashion such as "To my great disappointment and surprise, I cannot pass anything polymorphic into a @convention(c) function. Could this be improved, please? I kinda need it asap, thanks." is not very productive, especially given the fact that there is an active effort on concurrency going on right now.

@typesanitizer
Copy link

Also, your code example seems to be incomplete, it is missing some field definitions such as args, and it's not clear where you're trying to use work. If you can fix the code, we can try to figure out a workaround, as it is possible to create @convention(c) functions from ordinary functions in limited cases by avoiding captures.

@kavon
Copy link
Contributor

kavon commented Feb 10, 2021

I don't think it is possible to allow C convention functions to capture free variables or rely on other dynamic information (so as to be generic) without a change in its calling convention or dynamic compilation. But we can't change the C calling convention.

Until Swift's upcoming concurrency features make it into a release, my strong suggestion is that you try using a DispatchGroup that is instantiated with a concurrent DispatchQueue to implement a fork-join pattern, or to implement this future / promise type. You may also find this talk to be helpful: https://developer.apple.com/videos/play/wwdc2017/706/

Alternatively, you could implement that type using Swift's Thread instead of using pthread through a C foreign-function interface. This way, you can avoid the need for @convention(c) functions to implement your futures / promises library. Though I think you would run into limitations on the number of spawnable threads (just as you would for pthread) unless if you had some sort of thread pool.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@AnthonyLatsis AnthonyLatsis added feature A feature request or implementation attributes Feature: Declaration and type attributes c interop Feature: Interoperability with C @convention Feature → attributes: the @convention attribute will not do Resolution: Will not be worked on and removed new feature labels Feb 25, 2023
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
attributes Feature: Declaration and type attributes c interop Feature: Interoperability with C compiler The Swift compiler in itself @convention Feature → attributes: the @convention attribute feature A feature request or implementation will not do Resolution: Will not be worked on
Projects
None yet
Development

No branches or pull requests

4 participants