|
|
Subscribe / Log in / New account

Swift concurrency

Swift concurrency

Posted Sep 19, 2024 14:38 UTC (Thu) by tshow (subscriber, #6411)
In reply to: Swift concurrency by geofft
Parent article: Swift 6 released

Having used Swift professionally for several years on Apple platforms, it's an interesting language and may have potential, but there are some fairly severe caveats.

The primary caveat is that Swift is actually two things in practice; a language, and the surrounding platform ecosystem. If you aren't inside Apple's walled garden, you don't get the platform ecosystem part, and the platform ecosystem has a lot of the functionality. A lot of the documentation is written either by Apple or by people within the walled garden who don't realize the split exists. I'm not sure how much the community beyond the walls has stepped up to build the modern GNUStep equivalent.

Some of the ecosystem stuff is (relatively) obvious; I'm pretty sure you don't get SwiftUI or any of the UIKit/AppKit (GUI) stuff. A lot is less obvious; I'm not sure, for instance, if any of the run queue stuff (that is, for scheduling async tasks) is available outside the wall. It might be? Likewise, I'm not sure if the schemes for versioning/deprecation (`@available`, `#available`...) are capable of useful operation outside the wall.

The next caveat is that the language is still evolving. They're getting better about breaking changes, but any web search for "how I mine for fish in swift" is going to lead you inevitably to stackoverflow archaeology where you'll find a page that starts with a question and a few answers. As you read down, the answers become "That doesn't work in Swift 2, new solution:", and then "No longer works in Swift 3, now you...", with the same for Swift 4, Swift 5, and presumably shortly Swift 6.

Some (well, a lot...) of the breakage is ecosystem-related, so may not apply to work outside the wall; someone at Apple seems to have an absolute mania for cosmetic changes to function signatures. Many breaking changes are things like `doFoo(foo: thing, withBar: other)` becoming `do(foo foo: thing, with bar: other)`; same arguments, just screwing around with the function signature to make it more englishy.

The last caveat (at least for this message) is: I'd argue that Swift is a "systems programming language" only in the most blurry, expansive sense. You might be able to roll your own memory allocator, for instance, but anything that uses it will probably result in a lot of call site boilerplate. I think it's potentially a decent language for writing tools and apps, but I'd be hesitant about writing an OS in Swift. It's worth noting that under the hood, ios and macos are still essentially FreeBSD (mostly C) with some C++ hardware drivers. Some of that is legacy, but some of it is also essentially unsolved problems with the ObjC/Swift model.

As an example, you can't unload a shared library that contains ObjC or Swift once it has been loaded. There may be multiple reasons for this, but at least one is that ObjC/Swift allow extensions to objects; you can runtime patch methods into an object. This means if you load a shared library, it might (say) extend `Data` (a buffer object, basically) with a `base64decode()` method. There doesn't appear to be any mechanism for removing that extension at runtime, so if you could unload the shared library, `base64decode()` would presumably become a stale pointer to who knows what. So they don't allow that.

None of this is to say that Swift is a bad language (although some of the syntax choices... `guard let foo = foo else {return}`), particularly if you're writing something that isn't going to be doing system level stuff. But there are definitely things to be aware of.

https://www.swift.org/documentation/ has more info, and if you want to learn the language:
https://docs.swift.org/swift-book/documentation/the-swift...

For the LWN editors: A "Current State of Swift in Linux: What Can You Actually Do With It?" article would be appreciated.


to post comments

Swift concurrency

Posted Sep 19, 2024 14:42 UTC (Thu) by daroc (editor, #160859) [Link]

I haven't worked with Swift at all, but I do like learning about new programming languages and their approaches; I'll put it in our potential topic list for after we finish the current round of conference articles.

Swift concurrency

Posted Sep 19, 2024 23:47 UTC (Thu) by thoughtpolice (subscriber, #87455) [Link] (2 responses)

I was looking into it and the Foundation situation is interesting. My understanding is that:

- swift-foundation is a shared library now used on all operating systems to provide absolute essentials of the Foundations library. That's stuff like dates, UUIDs, JSON, Locale support, I18N, etc: https://github.com/apple/swift-foundation
- swift-corelibs-foundation builds on top of that, and provides some missing APIs in Foundation for the non-Apple platforms. For example, the networking/URL library is implemented here in terms of libcurl: https://github.com/apple/swift-corelibs-foundation

So, you need both but it looks like all the fundamentals work everywhere now. Swift 6 uses swift-foundation on all platforms including macOS and iOS, so that should be pretty well tested.

> As an example, you can't unload a shared library that contains ObjC or Swift once it has been loaded.

I know what you're trying to get at here, but in this particular case, unloading shared libraries in the modern world (especially in the presence of multithreading) is basically broken, no matter what the language is. You can't rely on it at all. On Linux it literally may not work at all, actually; musl doesn't even implement a real dlclose, and there are many bugs that exist in common libraries that will prevent reloading the library anyway with something like glibc (e.g. pthread keys), or you can even force permanence with -z nodelete or whatnot. All of these can also be problems in dependencies of your dependencies. It's too fragile as a global invariant to rely on, anymore. You need to assume a library will never unload.

The more interesting case study here is Embedded Swift. That's what interests me. The core language, once you throw away all the libraries, is actually quite good and can be written pretty efficiently. It has move/reference/borrowing/copy semantics, notions of sendable/mutable data for async tasks, etc. The runtime ABI/compilation model choices for desktop are smart, but inappropriate for embedded. And I could very much see myself throwing away all the libraries and just using a subset of the language that uses whole-program compilation + specialization, as they designed it to, to write firmware. This is stuff where you really do just want a clear and easy to use language to write robust control plane logic most of the time and just trigger some interrupts and IOs. So, features like excellent C/C++ interop, type safety, clear move/reference semantics, etc are all very welcome. I mean half the time you use C just because that's what the vendor provides you, so just being able to import a header file and link to a library alone already makes it a viable alternative. And if you can do async/actors inside Embedded Swift, that might be quite wonderful.

In fact it seems like you could think of Embedded Swift as a kind of alternative to no_std Rust, even. You could write desktop software libraries with it, why not? I think that's a very interesting point in the design space to take, actually.

Swift concurrency

Posted Sep 20, 2024 1:31 UTC (Fri) by khim (subscriber, #9252) [Link] (1 responses)

> You could write desktop software libraries with it, why not?

One thing that Swift brings to the mix over Rust is the ability to write nice, backward-compatible, shared libraries with nice AP. But still…

Current state: Swift is, certainly, a very interesting language, but it's not clear if it would go anywhere (outside of Apple's walled garden, that is). That's the language which Apple uses as weapon. Which is why Google tried it and then decided not to bother and switched to Rust.

Would open-source community be brave enough to adopt it? That remains to be seen.

Swift concurrency

Posted Sep 22, 2024 21:36 UTC (Sun) by jmalcolm (subscriber, #8876) [Link]

The Ladybird browser project has said that it wants to move to Swift as their core language. Everything is written in C++ currently.

On the one hand, Ladybird is a bit fringe at the moment. On the other hand, it represents an incredibly broad code base and problem domain that will really test and certainly demonstrate the capability of Swift outside of the Apple ecosystem. So it is one to watch.

Swift concurrency

Posted Sep 24, 2024 16:50 UTC (Tue) by mathstuf (subscriber, #69389) [Link]

> As an example, you can't unload a shared library that contains ObjC or Swift once it has been loaded.

Beyond the other comment, this is a macOS-ism. *Any* use of thread-local storage will restrict unloading the associated binary on macOS. I imagine it is similar on the other Apple platforms.

Swift concurrency

Posted Oct 7, 2024 22:44 UTC (Mon) by ssokolow (guest, #94568) [Link]

I'd argue that Swift is a "systems programming language" only in the most blurry, expansive sense. You might be able to roll your own memory allocator, for instance, but anything that uses it will probably result in a lot of call site boilerplate
That's more of a terminological confusion.

By the original definition of "systems programming", Java, Go, Swift, and Rust all can lay equal claim to the "systems language" moniker because the original definition is about suitability for building infrastructural components (eg. network services, in Go's case) and a focus on keeping the project maintainable over long lifespans with changing team membership. It was coined in contrast to "scripting language" and the part about systems languages being suitable for low-level work is just an artifact of what "infrastructural components" unavoidably were in the 1970s.

As an example, you can't unload a shared library that contains ObjC or Swift once it has been loaded. There may be multiple reasons for this, but at least one is that ObjC/Swift allow extensions to objects; you can runtime patch methods into an object. This means if you load a shared library, it might (say) extend `Data` (a buffer object, basically) with a `base64decode()` method. There doesn't appear to be any mechanism for removing that extension at runtime, so if you could unload the shared library, `base64decode()` would presumably become a stale pointer to who knows what. So they don't allow that.
Funny thing there. It actually goes so far as to dlopen a second time behind your back to try to protect you from yourself.


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds