Skip to content

Commit fab17fe

Browse files
authored
Remove outdated thread-safety docs
The Store is now `@MainActor`, so I think we can remove these warnings.
1 parent 49f0323 commit fab17fe

File tree

1 file changed

+0
-49
lines changed

1 file changed

+0
-49
lines changed

Sources/ComposableArchitecture/Store.swift

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -83,55 +83,6 @@ import SwiftUI
8383
/// }
8484
/// ```
8585
///
86-
/// ### Thread safety
87-
///
88-
/// The `Store` class is not thread-safe, and so all interactions with an instance of ``Store``
89-
/// (including all of its child stores) must be done on the same thread the store was created on.
90-
/// Further, if the store is powering a SwiftUI or UIKit view, as is customary, then all
91-
/// interactions must be done on the _main_ thread.
92-
///
93-
/// The reason stores are not thread-safe is due to the fact that when an action is sent to a store,
94-
/// a reducer is run on the current state, and this process cannot be done from multiple threads.
95-
/// It is possible to make this process thread-safe by introducing locks or queues, but this
96-
/// introduces new complications:
97-
///
98-
/// * If done simply with `DispatchQueue.main.async` you will incur a thread hop even when you are
99-
/// already on the main thread. This can lead to unexpected behavior in UIKit and SwiftUI, where
100-
/// sometimes you are required to do work synchronously, such as in animation blocks.
101-
///
102-
/// * It is possible to create a scheduler that performs its work immediately when on the main
103-
/// thread and otherwise uses `DispatchQueue.main.async` (_e.g._, see Combine Schedulers'
104-
/// [UIScheduler][uischeduler]).
105-
///
106-
/// This introduces a lot more complexity, and should probably not be adopted without having a very
107-
/// good reason.
108-
///
109-
/// This is why we require all actions be sent from the same thread. This requirement is in the same
110-
/// spirit of how `URLSession` and other Apple APIs are designed. Those APIs tend to deliver their
111-
/// outputs on whatever thread is most convenient for them, and then it is your responsibility to
112-
/// dispatch back to the main queue if that's what you need. The Composable Architecture makes you
113-
/// responsible for making sure to send actions on the main thread. If you are using an effect that
114-
/// may deliver its output on a non-main thread, you must explicitly perform `.receive(on:)` in
115-
/// order to force it back on the main thread.
116-
///
117-
/// This approach makes the fewest number of assumptions about how effects are created and
118-
/// transformed, and prevents unnecessary thread hops and re-dispatching. It also provides some
119-
/// testing benefits. If your effects are not responsible for their own scheduling, then in tests
120-
/// all of the effects would run synchronously and immediately. You would not be able to test how
121-
/// multiple in-flight effects interleave with each other and affect the state of your application.
122-
/// However, by leaving scheduling out of the ``Store`` we get to test these aspects of our effects
123-
/// if we so desire, or we can ignore if we prefer. We have that flexibility.
124-
///
125-
/// [uischeduler]: https://github.com/pointfreeco/combine-schedulers/blob/main/Sources/CombineSchedulers/UIScheduler.swift
126-
///
127-
/// #### Thread safety checks
128-
///
129-
/// The store performs some basic thread safety checks in order to help catch mistakes. Stores
130-
/// constructed via the initializer ``init(initialState:reducer:withDependencies:)`` are assumed
131-
/// to run only on the main thread, and so a check is executed immediately to make sure that is the
132-
/// case. Further, all actions sent to the store and all scopes (see ``scope(state:action:)-90255``)
133-
/// of the store are also checked to make sure that work is performed on the main thread.
134-
///
13586
/// ### ObservableObject conformance
13687
///
13788
/// The store conforms to `ObservableObject` but is _not_ observable via the `@ObservedObject`

0 commit comments

Comments
 (0)