ManagedCriticalState and Sendable

Quick question about ManagedCriticalState: How come it is only sendable when the wrapped value itself is sendable? Since all access to the wrapped state is protected by a lock I would expect no problems with sharing one of those across threads. What am I missing there? In which case would it be unsafe to send a ManagedCriticalState to another thread?

It cannot be unconditionally Sendable right now because of two reasons. First, you are passing the state into the init of ManagedCriticialState. You could be passing a reference type in here which you might be accessing outside of the withCriticalRegion closure. The first problem could be solved with future language extension where the init is taking the State parameter; however, even then the State might contain a reference type which you could escape the reference out through the withCriticalRegion method. So the safest approach here really is to only make this Sendable if the State itself is Sendable.

There is a similar type in NIO that expresses the same constraints: swift-nio/NIOLockedValueBox.swift at main · apple/swift-nio · GitHub

1 Like

Makes sense. So it can be safe to use this with a type that is not Sendable, if we make sure the value is not shared. We just don’t have any tools in the language yet to prevent the value from being shared.

You need to make sure that the value and any stored properties that have reference semantics are not shared. It is the same as a Lock basically where you can make a type Sendable by correctly using the Lock; however, the compiler can't help you with the correctly part :smiley:

1 Like