6

EDIT3: Recreating the error from RDerik's code

I originally started with code I modified from RDerik. Now, others might recreate the error, I am running unmodified code from RDerik cloned from here.

When I run RDerik's code I get the following errors(same errors I noted in EDIT: below):

error: value of optional type 'pthread_t?' (aka 'Optional') must be unwrapped to a value of type 'pthread_t' (aka 'UInt')

note: force-unwrap using ! to abort execution if the optional value contains nil

error: cannot convert value of type '(UnsafeMutableRawPointer) -> UnsafeMutableRawPointer?' to expected argument type '@convention(c) (UnsafeMutableRawPointer?) -> UnsafeMutableRawPointer?' let result = pthread_create(&myThread, nil, threadedFunction, pThreadParameter)

I solved this last error by changing the function header of threadedFunction() to:

func threadedFunction(pointer: UnsafeMutableRawPointer!) -> UnsafeMutableRawPointer? 

ORIGINAL POST:

I know this question has been answered before but I haven't been able to find a fix compatable with Swift 5.3. The C function I need to call has this signature:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg)

Line 5 below is my Swift attempt at calling pthread_create(). Specifically my problem is with the first parameter: &myThread.

MY CODE: (modified from here)

var myThread: pthread_t! = nil
var threadParameter  = _ThreadParameter(threadIdentifier: _ThreadIdentifier(id: ""), pxT: self)
var pThreadParameter = UnsafeMutablePointer<_ThreadParameter>.allocate(capacity:1)
pThreadParameter.pointee = threadParameter
let result = pthread_create(&myThread, nil, __threadedFunction, pThreadParameter)

ERROR:

When calling pthread_create the myThread parameter throws the following error: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value, line 5

EDIT:

Other things I've tried:

If I use a ? instead of ! for pthread like this:

    var myThread: pthread_t? = nil

I get compile errors:

error: value of optional type 'pthread_t?' (aka 'Optional') must be unwrapped to a value of type 'pthread_t' (aka 'UInt')

note: force-unwrap using '!' to abort execution if the optional value contains 'nil'

EDIT2:

Also tried:

    let result = pthread_create(&myThread, 0, __threadedFunction, pThreadParameter)

ERROR: cannot convert value of type 'Int' to expected argument type 'UnsafePointer<pthread_attr_t>?'

jnpdx
  • 45,847
  • 6
  • 64
  • 94
CodeKat
  • 61
  • 3
  • 1
    Good thread, with helpful links: https://stackoverflow.com/a/63332736/421195 – paulsm4 May 24 '21 at 21:20
  • 2
    Out of curiosity, why do you need to call `pthread_create` specifically, as opposed to using one of the other concurrency paradigms available to Swift (e.g. Dispatch)? – Itai Ferber May 24 '21 at 21:44
  • Thank you @paulsm4, this helped but didn't solve the problem on calling pthread_create(). I've updated my original post with an edit on my new code and new errors. – CodeKat May 25 '21 at 17:04
  • @ItaiFerber, the short answer to your question is that we need multiple platform compatibility and we already have the logic worked out for pthreads. – CodeKat May 25 '21 at 17:08
  • 2
    ADDITIONAL SUGGESTION: In situations like this, I've often found it EXTREMELY helpful to create a small "test case". A bit of extra work up-front ... but can save a LOT of time getting the solution you need. Try this: 1) Download this project: https://github.com/rderik/rdknitting 2) Work through the corresponding tutorial: https://rderik.com/blog/multithreading-with-pthreads-in-swift/. 3) Once you get the test case working, adopt the solution into your actual project. 4) Post new SO questions if you encounter problems with RDerick's code in your environment. – paulsm4 May 25 '21 at 17:38
  • 1
    ALSO: Did you try wired's [suggestion](https://stackoverflow.com/a/67685553/421195): `let result = pthread_create(&myThread, 0, __threadedFunction, pThreadParameter)`? What happened? – paulsm4 May 25 '21 at 17:45
  • 1
    Great suggestion @paulsm4. I frequently work with a small test case like this. I have been working off rderik's tutorial and I agree that it's best to work from there and post a new question. Not only does it give everyone a common starting point but also next person looking for an update on this tutorial has a solution. Thanks again! P.S. I also updated EDIT2 with results of wired's suggestion. – CodeKat May 25 '21 at 18:59
  • 2
    I can't reproduce this given the code you've posted, but I had to make a lot of guesses about how your code differs from the code you link to (for example, you've put underscores in various places that they aren't in the original code, and your ThreadParameter is different). Can you post a full example that reproduces it? – Rob Napier May 25 '21 at 20:32
  • Thank you @RobNapier. I posted EDIT3 in the original post at the top on how to recreate the error starting with RDerik's code. – CodeKat May 25 '21 at 21:09
  • 1
    "When I run RDerik's code I get the following errors." The error you post is a compiler error, not a runtime error. Is that what you meant? (I downloaded this and it compiles without error in Xcode 12.5.) I do get a crash at line 22 (assigning pThreadParameter.pointee), but I expect that's because the memory management looks wrong (nothing retains threadParameter) – Rob Napier May 25 '21 at 21:32
  • 1
    I cannot reproduce the errors you describe in EDIT3. On which environment are you testing? – OOPer May 25 '21 at 21:32
  • 1
    I'm a bit confused by the article you've linked, BTW. I'm willing to grant that for some reason you absolutely must use pthreads, bizarre as that is, but the article is definitely wrong about a lot of things "To use threads directly in Swift, we need to interoperate with C code." That's not true. There's a perfectly good Swift interface to native threads (that you should almost never use, but it's useful when you need to). https://developer.apple.com/documentation/foundation/thread Much of the article seems to ignore ARC and memory management. – Rob Napier May 25 '21 at 21:42
  • @RobNapier, I have tried many revisions to RDerik's code, sometimes getting a compile time error. I can modify RDerik's code so that I get a runtime error described in the original post by declaring var myThread: pthread_t! = nil instead of var myThread: pthread_t? = nil. – CodeKat May 25 '21 at 21:54
  • 1
    What version of Xcode are you using? I can't get a compiler error. I can get runtime crashes. I just cloned it. Ran "xed ." Selected "My Mac" and Cmd-R. Also just tried "swift run" in the cloned directory, and it compiles fine. (and then crashes) – Rob Napier May 25 '21 at 21:56
  • I am on Linux Mint 20 using a text editor and Terminal to run the Swift compiler. I don't have access to a reliable Mac so would like to test out as much code as possible from Linux. I am working on a source-to-source compiler that builds apps for a platform in it's native language eg. Swift for MacOS and iOS, Java for Android, C++ for Linux and Windows. My understanding of Swift Thread is that it doesn't have a way to wait for a thread to end, whereas pthreads has the join command, which we need. – CodeKat May 25 '21 at 22:11
  • 1
    What version of Swift (swift --version). You should make sure this is 5.4. It's very surprising that you're seeing syntax errors on that repository if you've made zero changes to it. – Rob Napier May 25 '21 at 22:30
  • 1
    Note that this line is wrong: `pThreadParameter.pointee = threadParameter`. You haven't initialized memory yet (and `threadParameter` is not primitive), you've only allocated it. You mean `pThreadParameter.initialize(to: threadParameter)`. This code is also full of race conditions in how it accesses and manipulates `clients`. – Rob Napier May 25 '21 at 22:50
  • 1
    @RobNapier, I upgraded to Swift 5.4.1 on Mint and it didn't fix the issue. I also borrowed a Mac and ran RDeric's code no problem. I guess my next step is to look at the source code for Swift 5.4.1 on Linux. There I have found where Swift class thread{} is calling pthread_create(), this should help me work out a solution. Your right about the race conditions, we are only using his code as an example of how to use pthreads. – CodeKat May 26 '21 at 19:13
  • 1
    Best of luck. The Swift team does care a lot about Linux, but also Linux is not their primary focus. So if you find bugs there, those are very welcome in the bug tracker. – Rob Napier May 26 '21 at 19:15

1 Answers1

0

I dont know swift. However the corresponding to NIL is NULL in c.NULL again is a macro, depending on the compiler. So it can either be defined as #define NULL ((char *)0) or simply #define NULL 0. So what happens if you pass pthread_create(&myThread, 0, ... instead of nil?

  • Thank you @wired. I tried your suggestion and posted the results under EDIT2 in my original post. – CodeKat May 25 '21 at 18:21
  • 1
    As said, I dont know swift, but this link may help, cos it handles a) swift & pthreads b) unsafe pointers https://stackoverflow.com/questions/26449990/pthread-create-swift-sample –  May 25 '21 at 18:31
  • 4
    Swift's nil is not the same thing as C's NULL. In ObjC, this is basically true, but not in Swift. `nil` is the same as `Optional.none`. When bridged to C (via ObjC), it can be translated to 0, but you can't just replace it this way in Swift. – Rob Napier May 25 '21 at 20:37