Improbable Icon

Forums

Thread safety of worker connection object

api

#1

The docs for all the SDKs note that the worker connection object is not thread-safe, and the Steps for integrating a game engine page specifically notes:

… you need to be aware of that the SpatialOS SDKs do not offer any guarantees of thread safety - so you’ll need to account for that. This may cause the Connection to block your main thread. If you want multiple threads connecting to SpatialOS, you’ll need to coordinate it yourself, and take appropriate safety measures. For example, when you process events, you’ll need to be aware of your threading model, and make sure you’re not calling from the wrong thread.

I’m working on integrating SpatialOS into a game engine, and I’m looking for more information about how to correctly address thread safety for the worker connection object. Note that I’m specifically using the C API via the Rust programming language, but these questions should apply to all the SDKs.

In what ways is the connection object not thread-safe currently? There are differing degrees of thread-safety, for example:

  • Is it safe to access the connection object from different threads, so long as only one thread accesses it at a time? Or does the connection object need to be “pinned” to the thread that created it?
  • Are there any methods that only read from internal state data (which is never modified by other methods)? If so, these methods should be thread-safe. For example, GetWorkerAttributes() notes that “Worker attributes are static and will not change over the lifetime of the connection”, so is there any reason why this method couldn’t be called by two threads at the same time?
  • Does the connection object only ever modify its own internal data? Or does it ever read/modify global or static variables? If it only ever modifies its own internal data, then it can probably be made thread-safe by wrapping it in a mutex.

Any information you can provide about how the worker connection object works would be super helpful in ensuring that I’m using the API correctly :grin:


#2

Hey @randomPoison,

Thanks for taking to the time to post. The docs section you linked is 100% lacking in detail and I’ve made a ticket to provide more clarity. In the meantime, I’ll add some context here.

Currently, we make no guarantees about the thread-safety of the Connection object. Attempting to send component updates or get op lists from different threads could definitely crash your program or corrupt memory. There may be functions such as GetWorkerAttributes() (as you pointed out) that may be thread-safe but that’s a matter of coincidence and not through deliberate design.

From an implementation perspective currently, it does make sense to pin the Connection to a single thread (if your engine design allows that), or wrapping it in a mutex. It doesn’t use global variables, this is to the effect that if you had two Connection objects running on separate threads their behaviour would be defined. Does that make sense / help?

Guaranteeing thread-safety of the SDK is something that’s been looked into recently and design docs have been made, but I’m afraid I can’t guarantee when the work will be delivered.

Cheers and good luck with integration,
Ally


#3

That information is super helpful! Simply noting that it’s safe to share a connection between threads by wrapping it in a mutex provides a ton of clarity. That tells me that it’s safe to share the connection between threads, but it can only be accessed from one thread at a time.

Thanks for the info!