# How the Swift concurrency interacts with thread requirements for graphics libraries?

**URL:** <https://forums.swift.org/t/how-the-swift-concurrency-interacts-with-thread-requirements-for-graphics-libraries/77188>\
**Category:** Using Swift\
**Tags:** concurrency, gaming, graphics\
**Created:** [January 14, 2025, 12:46am UTC](https://forums.swift.org/t/how-the-swift-concurrency-interacts-with-thread-requirements-for-graphics-libraries/77188 "2025-01-14T00:46:20Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![sirlan](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/sirlan/32/37690_2.png) [@sirlan](https://forums.swift.org/u/sirlan)\
**Post date:** [January 14, 2025, 12:46am UTC](https://forums.swift.org/t/how-the-swift-concurrency-interacts-with-thread-requirements-for-graphics-libraries/77188/1 "2025-01-14T00:46:20Z")

</div>

So, I made [a little project to test using swift with raylib](https://codeberg.org/sirlan/game-of-life_swift_raylib/src/branch/main/Sources/gameOfLife/main.swift) some time ago, it sure is very naive and all, but was quite neat to just learn how to put the two together

The thing is, how is said in lines [250 to 256](https://codeberg.org/sirlan/game-of-life_swift_raylib/src/commit/2b14f8098427f8c1a8d34bae61ac57c3c7a92400/Sources/gameOfLife/main.swift#L250), that if I don't have that call to the Board actor's method, GLFW (being used by raylib) complains about not running in the current context when swapping buffers (this occurs also even if there's no async call in the drawing loop)

And I'm just confused as to how should I properly make this program work, without hacks, and specifically why (including why does that hacky call make the program work, also thinking back why those input/draw calls on the actor seem to work fine as technically they're not in the same context?)

Other things I've tried is changing this from top level code to an entry point struct with `@MainActor`, and it doesn't seem to change the behaviour

I've also tried wrapping the loop and window setup functions in `DispatchQueue.main.async`, and the behaviour is that if I just wrap the window creation functions, the program runs without error (at least from my testing, but I'm still not sure this is the proper way to do it), though also trying to wrap the drawing loop, it doesn't run at all

I've tried searching around but at least couldn't find specifically about the interaction between Swift programs with concurrency and external libraries that care about which threads they're run on

Last tested this program in Swift 6.0.1

---

<div class="post-metadata">

**Author:** ![KeithBauerANZ](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/keithbaueranz/32/27897_2.png) [@KeithBauerANZ](https://forums.swift.org/u/KeithBauerANZ)\
**Post date:** [January 14, 2025, 2:05am UTC](https://forums.swift.org/t/how-the-swift-concurrency-interacts-with-thread-requirements-for-graphics-libraries/77188/2 "2025-01-14T02:05:27Z")

</div>

GLFW requires you to call most functions from the main thread. This is fine (use `@MainActor).

But OpenGL maintains a current context per-thread, and you can use `glfwMakeContextCurrent` (read the docs! there are caveats!) to set the current context.

Since Swift concurrency doesn't guarantee what _thread_ anything runs on, the tl;dr is "poorly"

---

<div class="post-metadata">

**Author:** ![AlexanderM](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/alexanderm/32/9781_2.png) [@AlexanderM](https://forums.swift.org/u/AlexanderM)\
**Post date:** [January 14, 2025, 2:33am UTC](https://forums.swift.org/t/how-the-swift-concurrency-interacts-with-thread-requirements-for-graphics-libraries/77188/3 "2025-01-14T02:33:57Z")

</div>

> [@KeithBauerANZ](#):
>
> Since Swift concurrency doesn't guarantee what _thread_ anything runs on, the tl;dr is "poorly"

You can use a custom executor to tie an actor to a particular thread, but I haven't tried it myself yet. [swift-evolution/proposals/0392-custom-actor-executors.md at main · swiftlang/swift-evolution · GitHub](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0392-custom-actor-executors.md)

---

<div class="post-metadata">

**Author:** ![mattie](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mattie/32/13267_2.png) [@mattie](https://forums.swift.org/u/mattie)\
**Post date:** [January 14, 2025, 11:13am UTC](https://forums.swift.org/t/how-the-swift-concurrency-interacts-with-thread-requirements-for-graphics-libraries/77188/4 "2025-01-14T11:13:01Z")

</div>

Yeah this _is_ possible to pull off, but is quite hard. I did it by using a thread + runloop and a few unsafe opt-outs.

(“It” being an actor backed by a single dedicated thread.)

---

<div class="post-metadata">

**Author:** ![sirlan](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/sirlan/32/37690_2.png) [@sirlan](https://forums.swift.org/u/sirlan)\
**Post date:** [January 14, 2025, 12:46pm UTC](https://forums.swift.org/t/how-the-swift-concurrency-interacts-with-thread-requirements-for-graphics-libraries/77188/5 "2025-01-14T12:46:28Z")

</div>

The thing is I'm not sure about either of these options

As I've already tried having either the render part, or the program entry point and loop be a `@MainActor func`, and it didn't really seem to change the behaviour

And using `glfwMakeContextCurrent` seems to be not an option when using raylib specifically as it encapsulates the render context from the user (even importing glfw and using it directly seems to not really be able to get the context)

Also as I've said, apparently putting a `DispatchQueue.main.async` around just the window initialisation calls seems to work (putting it on the render loop seems to make it not run), but I don't think that's the right way, as it still would not make sure the render loop (more specifically the 'EndDrawing') is running on main, so would still be a flimsy hack?
