SE-0282: Low-Level Atomic Operations

The review for SE-0282 Atomics ran from April 14 to April 24, 2020. The core team has decided to return this proposal for revision. During the review, support was nearly unanimous for the memory model the proposal establishes, bringing Swift in line with the model standardized by C. The core team concurs with the review discussion on this subject, and would like to see a revised proposal that focuses on specifying the memory model. Guaranteeing a C-compatible memory model allows developers that currently wrap atomic primitives written in C and import them into Swift to rely on this continuing to work. This would also provide stable ground for building atomics packages outside of the standard library for experimentation and use by early adopters. The Swift project itself plans to develop one of these packages.

The most intense review discussion on SE-0282 centered on the best paradigm in which to expose these atomic operations in Swift, both now and in the future. The core team would like to see the community develop more implementation experience before committing to a standard library API for exposing atomics. There is general agreement that a move-only Atomic type should be the ultimate goal, similar to what has successfully been implemented in Rust; however, the best we can hope to implement in Swift as it exists today without fundamental overhead is something that performs atomic operations on unmanaged memory through pointers. The proposal manifests this as an UnsafeAtomic<T> type, which wraps a pointer, along with AtomicProtocol and AtomicInteger protocols with implementation-defined requirements to which eligible types conform. The review discussion raised concerns about this approach:

  • The naming of UnsafeAtomic does not make the pointer-like nature of the type apparent.
  • The UnsafeAtomic type is proposed to have create and destroy methods, which combine dynamic allocation of storage and initialization for an atomic value. The convenience of these APIs suggests they may be the primary intended API for working with the type, further adding to confusion about the nature of the type, and adding indirection that is likely to be an unacceptable overhead for the sorts of performance-bound applications that require atomics.
  • Since the requirements of the AtomicProtocol are hidden, it isn't clear what guarantees it provides for generic code, or how generic code should work with types constrained by the protocol. Without further implementation experience it also isn't clear that the implementation-detail protocol is adequate for future expansion to double-wide types or other extensions in the future.

Other design paradigms that were explored in the review and pitch thread include:

  • Exposing the atomic operations as free functions, static methods, or instance methods taking values of the existing Unsafe*Pointer types. This makes the pointer-based nature of the operations clear, but also invites mixing and matching atomic and nonatomic operations on the same pointer.
  • Creating a safe class AtomicReference<T> that manages the lifetime of the atomic storage. This would present a mostly safe interface to atomics, since classes allow shared references to a common resource and provide the necessary lifetime management facilities via deinit to manage atomic storage. However, classes would have the problem of added indirection, along with potential added overhead and interference from ARC reference counting operations, making this an inefficient approach.

All of these approaches have serious shortcomings, and they're likely to be quickly superseded by move-only atomics in the future. How far that future is from the present is an open question, and having some sort of low-level API for atomic primitives could still have a small niche for advanced users even with move-only atomics as the primary interface. The core team will keep an eye on the package ecosystem to see what's needed and what works well in practice in this space.

Thanks to everyone who participated in the review!

24 Likes