# Exposing the Memory Locations of Class Instance Variables

**URL:** <https://forums.swift.org/t/exposing-the-memory-locations-of-class-instance-variables/30584>\
**Category:** Pitches\
**Created:** [November 8, 2019, 2:27am UTC](https://forums.swift.org/t/exposing-the-memory-locations-of-class-instance-variables/30584 "2019-11-08T02:27:40Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![lorentey](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lorentey/32/1299_2.png) [@lorentey](https://forums.swift.org/u/lorentey)\
**Post date:** [November 8, 2019, 2:27am UTC](https://forums.swift.org/t/exposing-the-memory-locations-of-class-instance-variables/30584/1 "2019-11-08T02:27:40Z")

</div>

Dear Swift folks,

Here is a pitch to plug a small hole in the stdlib API by providing a reliable method to retrieve the address for any directly addressable stored property inside a class instance. The need to work with such addresses comes up particularly often when we try to use synchronization tools to manage concurrency, and it's especially desirable when working with atomic primitives.

This pitch is the first in a series, hopefully culminating in a draft for a memory model for Swift programs that would allow people to start building low-level synchronization tools and some concurrent data structures in pure Swift code. (People interested in peeking at what lies ahead are welcome to check out the work-in-progress atomics implementation at [[DO NOT MERGE] Atomic experiments by lorentey · Pull Request #27229 · swiftlang/swift · GitHub](https://github.com/apple/swift/pull/27229). That PR is mostly concentrating on API design work -- drafting a memory model will happen elsewhere, most likely in a separate topic on this forum.)

* * *

# Exposing the Memory Location of Class Instance Variables

## Introduction

We propose to enable Swift code to retrieve the memory location of any directly addressable stored property in a class instance as an `UnsafeMutablePointer` value.

- [Motivation](#motivation)
- [Proposed Solution](#proposed-solution)
- [Efficiency Requirements](#efficiency-requirements)
- [Detailed Design](#detailed-design)
- [Source Compatibility](#source-compatibility)
- [Effect on ABI Stability](#effect-on-abi-stability)
- [Effect on API Resilience](#effect-on-api-resilience)
- [Alternatives Considered](#alternatives-considered)
  - [Generalizing offset(of:)](#generalizing-offsetof)
  - [Closure-Based API](#closure-based-api)

The initial implementation of the `MemoryLayout` API introduced in this document is available at the following URL: [https://github.com/apple/swift/pull/28144](https://github.com/apple/swift/pull/28144)

An up-to-date copy of this document (with a revision history) is available at [[pitch] Exposing the memory locations of class instance variables · GitHub](https://gist.github.com/lorentey/71981897bb8637cb060255837730e5d8).

## Motivation

For Swift to be successful as a systems programming language, it needs to allow efficient use of the synchronization facilities provided by the underlying computer architecture and operating system, such as primitive atomic types or higher-level synchronization tools like `pthread_mutex_t` or `os_unfair_lock`. Such constructs typically require us to provide a stable memory location for the values they operate on.

Swift provides a number of language and runtime constructs that are guaranteed to have a stable memory location. (Incidentally, concurrent access to shared mutable state is only possible through memory locations such as these.) For example:

- **Dynamic variables** manually created by Swift code (such as through `allocate`/`initialize` methods on unsafe pointer types, or `ManagedBuffer` APIs) inherently have a stable memory location.

- **Class instances** get allocated a stable memory location during initialization; the location gets deallocated when the instance is deinitialized. Individual instance variables (ivars) get specific locations within this storage, using Swift's class layout algorithms.

- **Global variables** and **static variables** always get associated with a stable memory location to implement their storage. This storage may be lazily initialized on first access, but once that's done, it remains valid for the entire duration of the Swift program.

- **Variables captured by an (escaping) closure** get moved to a stable memory location as part of the capture. The location remains stable until the closure value is destroyed.

- The stdlib provides APIs (such as **`withUnsafePointer(to:_:)`**) to pin specific values to some known memory location for the duration of a closure call. This sometimes reuses the existing storage location for the value (e.g., if these APIs are called on a directly accessible global variable), but this isn't guaranteed -- if the existing storage happens to not be directly available, these APIs silently fall back to creating a temporary location, typically on the stack.

However, Swift does not currently provide ways to reliably retrieve the address of the memory location backing these variables -- with the exception of dynamic variables, where all access is done through an explicit unsafe pointer whose value is (obviously) known to the code that performs the access.

Therefore, in current Swift, constructs that need to be backed by a known memory location can only be stored in dynamically allocated memory. For example, here is a simple "thread-safe" integer counter that uses the Darwin-provided `os_unfair_lock` construct to synchronize access:

(We can wrap POSIX Thread mutexes in a similar manner; we chose `os_unfair_lock` for this demonstration to minimize the need for error handling.)

```swift
class Counter {
    private var _lock: UnsafeMutablePointer<os_unfair_lock_s>
    private var _value: Int = 0
    
    init() {
        _lock = .allocate(capacity: 1)
        _lock.initialize(to: os_unfair_lock_s())
    }
    
    deinit {
        _lock.deinitialize(count: 1)
        _lock.deallocate()
    }
    
    private func synchronized<R>(_ body: () throws -> R) rethrows -> R {
        os_unfair_lock_lock(_lock)
        defer { os_unfair_lock_unlock(_lock) }
        return try body()
    }
    
    func increment() {
        synchronized { _value += 1}
    }
    
    func load() -> Int {
        synchronized { _value }
    }
}

```

Having to manually allocate/deallocate memory for such constructs is cumbersome, error-prone and inefficient. We should rather allow Swift code to use inline instance storage for this purpose.

To enable interoperability with C, the Swift Standard Library already provides APIs to retrieve the memory location of a class instance as an untyped `UnsafeRawPointer` value:

```swift
class Foo {
    var value = 42
}

let foo = Foo()
let unmanaged = Unmanaged.passRetained(foo)
let address = unmanaged.toOpaque()
print("foo is located at \(address)") // ⟹ foo is located at 0x0000000100500340
unmanaged.release()

```

However, there is currently no way to _ **reliably** _ retrieve the memory location for individual stored variables within this storage.

[SE-0210](https://github.com/apple/swift-evolution/blob/master/proposals/0210-key-path-offset.md) introduced a `MemoryLayout.offset(of:)` method that can be used to determine the layout offset of a stored variable inside a struct value. While this method doesn't work for classes, we can use it to guide the design of new API that does.

## Proposed Solution

We propose to add an API that returns an `UnsafeMutablePointer` to the storage behind a directly addressable, mutable stored property within a class instance:

```swift
extension MemoryLayout where T: AnyObject {
  static func unsafeAddress<Value>(
    of key: ReferenceWritableKeyPath<T, Value>,
    in root: T
  ) -> UnsafeMutablePointer<Value>?
}

```

If the given `key` refers to a stored property within the in-memory representation of `root`, and the property is directly addressable (in the sense of [SE-0210](https://github.com/apple/swift-evolution/blob/master/proposals/0210-key-path-offset.md#detailed-design)), then the return value is a direct pointer to the memory location implementing its storage.

Accessing the `pointee` property on the returned pointer is equivalent to the same access of the instance property itself (which is in turn equivalent to access through the corresponding key path):

```swift
class Foo {
    var value = 42
}

let foo = Foo()

// The following groups of statements all perform the same accesses
// on `foo`'s instance variable:

print(foo.value) // read
foo.value = 23 // assignment
foo.value += 1 // modification

print(foo[keyPath: \.value]) // read
foo[keyPath: \.value] = 23 // assignment
foo[keyPath: \.value] += 1 // modification

withExtendedLifetime(foo) {
  let p = MemoryLayout.unsafeAddress(of: \.value, in: foo)!
  print(p.pointee) // read
  p.pointee = 23 // assignment
  p.pointee += 1 // modification
}

```

Note the use of `withExtendedLifetime` to make sure `foo` is kept alive while we're accessing its storage. To rule out use-after-free errors, it is crucial to prevent the surrounding object from being deallocated while we're working with the returned pointer. (This is why this new API needs to be explicitly tainted with the `unsafe` prefix.)

Note also that the [Law of Exclusivity](https://github.com/apple/swift-evolution/blob/master/proposals/0176-enforce-exclusive-access-to-memory.md) still applies to accesses through the pointer returned from `unsafeAddress(of:in:)`. Accesses to the same instance variable (no matter how they're implemented) aren't allowed to overlap unless all overlapping accesses are reads. (This includes concurrent access from different threads of execution as well as overlapping access within the same thread -- see [SE-0176](https://github.com/apple/swift-evolution/blob/master/proposals/0176-enforce-exclusive-access-to-memory.md) for details. The compiler and runtime environment may not always be able to diagnose conflicting access through a direct pointer; however, it is still an error to perform such access.)

We can use this new API to simplify the implementation of the previous `Counter` class:

```swift
final class Counter {
    private var _lock = os_unfair_lock_s()
    private var _value: Int = 0
    
    init() {}
    
    private func synchronized<R>(_ body: () throws -> R) rethrows -> R {
        let lock = MemoryLayout<Counter>.unsafeAddress(of: \._lock, in: self)!
        os_unfair_lock_lock(lock)
        defer { os_unfair_lock_unlock(lock) }
        return withExtendedLifetime(self) { try body() }
    }
    
    func increment() {
        synchronized { value += 1}
    }
    
    func load() -> Int {
        synchronized { value }
    }
}

```

(Note that the functions `os_unfair_lock_lock`/`os_unfair_lock_unlock` cannot currently be implemented in Swift, because we haven't formally adopted a memory model yet. Concurrent mutating access to `_lock` within Swift code will run afoul of the Law of Exclusivity. Carving out a memory model that assigns well-defined semantics for certain kinds of concurrent access is a separate task, deferred for future proposals. For now, we can state that Swift's memory model must be compatible with that of C/C++, because Swift code is _already_ heavily relying on the ability to use synchronization primitives implemented in these languages.)

## Efficiency Requirements

To make practical use of this new API, we need to ensure that the `unsafeAddress(of:in:)` invocation is guaranteed to compile down to a direct call to the builtin primitive that retrieves the address of the corresponding ivar whenever the supplied `key` is a constant-evaluable key path expression. (Ideally this should work even in unoptimized `-Onone` builds.) Creating a full key path object and iterating through its components at runtime on each and every access would be prohibitively expensive for the high-performance synchronization constructs that we expect to be the primary use case for this new API.

This optimization isn't currently implemented in our prototype PR, but we expect it will be done as part of the process of integrating the new API into an actual Swift release.

For now, to enable performance testing, we recommend caching the ivar pointers in (e.g.) lazy stored properties:

```swift
final class Counter {
  private var _lockStorage = os_unfair_lock_s()
  private var _value: Int = 0

  private lazy var _lock: UnsafeMutablePointer<os_unfair_lock_s> =
    MemoryLayout<Counter>.unsafeAddress(of: \._lockStorage, in: self)!

  private func synchronized<R>(_ body: () throws -> R) rethrows -> R {
    os_unfair_lock_lock(_lock)
    defer { os_unfair_lock_unlock(_lock) }
    return try withExtendedLifetime(self) { try body() }
  }

  func increment() {
    synchronized { _value += 1}
  }

  func load() -> Int {
    synchronized { _value }
  }
}

```

This wastes some memory, but has performance comparable to the eventual implementation.

## Detailed Design

```swift
extension MemoryLayout where T: AnyObject {
  /// Return an unsafe mutable pointer to the memory location of
  /// the stored property referred to by `key` within a class instance.
  ///
  /// The memory location is available only if the given key refers to directly
  /// addressable storage within the in-memory representation of `T`, which must
  /// be a class type.
  ///
  /// A class instance property has directly addressable storage when it is a
  /// stored property for which no additional work is required to extract or set
  /// the value. Properties are not directly accessible if they are potentially
  /// overridable, trigger any `didSet` or `willSet` accessors, perform any
  /// representation changes such as bridging or closure reabstraction, or mask
  /// the value out of overlapping storage as for packed bitfields.
  ///
  /// For example, in the `ProductCategory` class defined here, only
  /// `\.updateCounter`, `\.identifier`, and `\.identifier.name` refer to
  /// properties with inline, directly addressable storage:
  ///
  /// final class ProductCategory {
  /// struct Identifier {
  /// var name: String // addressable
  /// }
  ///
  /// var identifier: Identifier // addressable
  /// var updateCounter: Int // addressable
  /// var products: [Product] { // not addressable: didSet handler
  /// didSet { updateCounter += 1 }
  /// }
  /// var productCount: Int { // not addressable: computed property
  /// return products.count
  /// }
  /// var parent: ProductCategory? // addressable
  /// }
  ///
  /// When the return value of this method is non-`nil`, then accessing the
  /// value by key path or via the returned pointer are equivalent. For example:
  ///
  /// let category: ProductCategory = ...
  /// category[keyPath: \.identifier.name] = "Cereal"
  ///
  /// withExtendedLifetime(category) {
  /// let p = MemoryLayout.unsafeAddress(of: \.identifier.name, in: category)!
  /// p.pointee = "Cereal"
  /// }
  ///
  /// `unsafeAddress(of:in:)` returns nil if the supplied key path has directly
  /// accessible storage but it's outside of the instance storage of the
  /// specified `root` object. For example, this can happen with key paths that
  /// have components with reference semantics, such as the `parent` field
  /// above:
  ///
  /// MemoryLayout.unsafeAddress(of: \.parent, in: category) // non-nil
  /// MemoryLayout.unsafeAddress(of: \.parent.name, in: category) // nil
  ///
  /// - Warning: The returned pointer is only valid until the root object gets
  /// deallocated. It is the responsibility of the caller to ensure that the
  /// object stays alive while it is using the pointer. (The
  /// `withExtendedLifetime` call above is one example of how this can be
  /// done.)
  ///
  /// Additionally, the Law of Exclusivity still applies: the caller must
  /// ensure that any access of the instance variable through the returned
  /// pointer will not overlap with any other access to the same variable,
  /// unless both accesses are reads.
  @available(/* to be determined */)
  public static func unsafeAddress<Value>(
    of key: ReferenceWritableKeyPath<T, Value>,
    in root: T
  ) -> UnsafeMutablePointer<Value>?
}

```

## Source Compatibility

This is an additive change to the Standard Library, with minimal source compatibility implications.

## Effect on ABI Stability

Key path objects already encode the information necessary to implement the new API. However, this information isn't exposed through the ABI of the stdlib as currently defined. This implies that the new runtime functionality defined here needs to rely on newly exported entry points, so it won't be back-deployable to any previous stdlib release.

## Effect on API Resilience

As in [SE-0210](https://github.com/apple/swift-evolution/blob/master/proposals/0210-key-path-offset.md), clients of an API could potentially use this functionality to dynamically observe whether a public property is implemented as a stored property from outside of the module. If a client assumes that a property will always be stored by force-unwrapping the optional result of `unsafeAddress(of:in:)`, that could lead to compatibility problems if the library author changes the property to computed in a future library version. Client code using offsets should be careful not to rely on the stored-ness of properties in types they don't control.

## Alternatives Considered

While we could have added the new API as an extension of `ReferenceWritableKeyPath`, the addition of the `root` parameter makes that option even less obvious than it was for `offset(of:)`. We agree with [SE-0210](https://github.com/apple/swift-evolution/blob/master/proposals/0210-key-path-offset.md) that `MemoryLayout` is the natural place for this sort of API.

### Generalizing `offset(of:)`

We considered extending the existing `offset(of:)` method to allow it to return an offset within class instances. However, the means of converting an offset to an actual pointer differ between struct and class values, and using the same API for both is likely to lead to confusion.

```swift
let foo = Foo()
let offset = MemoryLayout<Foo>.offset(of: \.value)!

// if Foo is a struct:
withUnsafeBytes(of: foo) { buffer in 
    let raw = buffer.baseAddress! + offset
    let p = raw.assumingMemoryBound(to: Int.self)
    print(p.pointee) 
}

// if Foo is a class:
withExtendedLifetime(foo) { 
    let raw = Unmanaged.passUnretained(foo).toOpaque() + offset
    let p = raw.assumingMemoryBound(to: Int.self)
    print(p.pointee)
}

```

We also do not like the idea of requiring developers to perform fragile raw pointer arithmetic just to access ivar pointers. The proposed API abstracts away these details.

### Closure-Based API

Elsewhere in the Standard Library, we prefer to expose unsafe "inner" pointers through APIs that take a closure. For example, [SE-0237](https://github.com/apple/swift-evolution/blob/master/proposals/0237-contiguous-collection.md) added the following customization point to `Sequence`:

```swift
protocol Sequence {
  public mutating func withContiguousMutableStorageIfAvailable<R>(
    _ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
  ) rethrows -> R?
}

```

At first glance, this looks very similar to the ivar case. In both cases, we're exposing a pointer that has limited lifetime, and arranging the client code into a closure helps avoiding lifetime issues.

It would definitely be possible to define a similar API here, too:

```swift
extension MemoryLayout where T: AnyObject {
  public static func withUnsafeMutablePointer<Value, Result>(
    to key: ReferenceWritableKeyPath<T, Value>,
    in root: T,
    _ body: (UnsafeMutablePointer<Value>) throws -> Result
  ) rethrows -> Result?
}

```

However, the ivar usecase is something of a special case that makes this approach suboptimal.

In the `Sequence.withContiguousMutableStorageIfAvailable` case, it is strictly illegal to save the pointer for later access outside the closure -- `Sequence` implementations are allowed to e.g. create a temporary memory location for the duration of the closure, then immediately destroy it when the closure returns. There is no way to (reliably) hold on to the storage buffer.

In contrast, the memory location (if any) of a class ivar is guaranteed to remain valid as long as there is at least one strong reference to the surrounding object. There is no need to artifically restrict the use of the ivar pointer outside the duration of a closure -- indeed, we believe that the guaranteed ability to "escape" the pointer will be crucially important when we start building abstractions on top of this API.

In the primary usecase we foresee, the pointer would get packaged up with a strong reference to its object into a standalone construct that can fully guarantee the validity of the pointer. Given that this usecase is deliberately escaping the pointer, it seems counter-productive to force access through a closure-based API that discourages such things.

---

<div class="post-metadata">

**Author:** ![ktoso](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ktoso/32/44526_2.png) [@ktoso](https://forums.swift.org/u/ktoso)\
**Post date:** [November 8, 2019, 3:01am UTC](https://forums.swift.org/t/exposing-the-memory-locations-of-class-instance-variables/30584/2 "2019-11-08T03:01:17Z")

</div>

This is fan-tas-tic, Karoy! 👏

Unlocks all the future use cases (that you nicely preview in 27229, can't wait for those 🙂) we have in mind... Needless to say, great addition to the language and esp. for server use cases once the follow-ups land.

I like the design, spelling as well as putting it onto `MemoryLayout` as well, very natural fit and reads very well.

> [@lorentey](#):
>
> (Ideally this should work even in unoptimized `-Onone` builds.)

I'd like to +1 that it would indeed be nice to _always_ have the keypath dance avoided in runtime. For the types of structures we'd like to build with these things the keypaths are likely (though would need to verify) painful overhead even in debug builds.

---

<div class="post-metadata">

**Author:** ![ddunbar](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ddunbar/32/1933_2.png) [@ddunbar](https://forums.swift.org/u/ddunbar)\
**Post date:** [November 8, 2019, 3:35am UTC](https://forums.swift.org/t/exposing-the-memory-locations-of-class-instance-variables/30584/3 "2019-11-08T03:35:34Z")

</div>

Yay! 🙂

---

<div class="post-metadata">

**Author:** ![mattrips](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mattrips/32/4079_2.png) [@mattrips](https://forums.swift.org/u/mattrips)\
**Post date:** [November 8, 2019, 4:18am UTC](https://forums.swift.org/t/exposing-the-memory-locations-of-class-instance-variables/30584/4 "2019-11-08T04:18:02Z")

</div>

Great presentation of the concepts.

Well-conceived substance.

Well-considered alternatives.

I like that the API differs between classes and structs. At first, I thought unification would be better, but they are different animals.

Thank you.

---

<div class="post-metadata">

**Author:** ![Chris\_Lattner3](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/chris_lattner3/32/348_2.png) [@Chris\_Lattner3](https://forums.swift.org/u/Chris_Lattner3)\
**Post date:** [November 8, 2019, 6:37am UTC](https://forums.swift.org/t/exposing-the-memory-locations-of-class-instance-variables/30584/5 "2019-11-08T06:37:30Z")

</div>

This is really awesome, I love the approach - thank you for tackling this!

---

<div class="post-metadata">

**Author:** ![lukasa](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lukasa/32/1232_2.png) [@lukasa](https://forums.swift.org/u/lukasa)\
**Post date:** [November 8, 2019, 2:26pm UTC](https://forums.swift.org/t/exposing-the-memory-locations-of-class-instance-variables/30584/6 "2019-11-08T14:26:11Z")

</div>

This is great, @lorentey, I love this proposal. I have one question:

> [@lorentey](#):
>
> For now, to enable performance testing, we recommend caching the ivar pointers in (e.g.) lazy stored properties:

I have a vague recollection that lazy ivars are not thread safe. It seems like storing the pointer to the storage in such an ivar is not good practice, even though in this context it may behave as intended. Perhaps the recommendation should be to compute this in the initializer?

---

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [November 8, 2019, 4:29pm UTC](https://forums.swift.org/t/exposing-the-memory-locations-of-class-instance-variables/30584/7 "2019-11-08T16:29:32Z")

</div>

It's exciting to see work in this direction happening! Thank you @lorentey!

---

<div class="post-metadata">

**Author:** ![kylebrowning](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/kylebrowning/32/9837_2.png) [@kylebrowning](https://forums.swift.org/u/kylebrowning)\
**Post date:** [November 8, 2019, 5:03pm UTC](https://forums.swift.org/t/exposing-the-memory-locations-of-class-instance-variables/30584/8 "2019-11-08T17:03:19Z")

</div>

+1

---

<div class="post-metadata">

**Author:** ![beccadax](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/beccadax/32/34217_2.png) [@beccadax](https://forums.swift.org/u/beccadax)\
**Post date:** [November 8, 2019, 5:22pm UTC](https://forums.swift.org/t/exposing-the-memory-locations-of-class-instance-variables/30584/9 "2019-11-08T17:22:49Z")

</div>

I’ve thought we needed something in this space for a long, long time. Bravo.

But...

> [@lorentey](#):
>
> In the primary usecase we foresee, the pointer would get packaged up with a strong reference to its object into a standalone construct that can fully guarantee the validity of the pointer.

Why not implement this safely-packaged version of the functionality ourselves? Or implement the `with*` version of it while documenting that it’s okay to escape the pointer as long as you keep the base alive? An unsafe-by-default API seems like it’s inviting mistakes.

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [November 8, 2019, 5:41pm UTC](https://forums.swift.org/t/exposing-the-memory-locations-of-class-instance-variables/30584/10 "2019-11-08T17:41:34Z")

</div>

Thanks for addressing this important problem! I don't think this is quite the right approach, though, because fundamentally the storage you want to allocate _isn't_ a property from Swift's perspective. The exclusivity expectations are fundamentally at odds with concurrency primitives like locks. And in what little memory model Swift does have, it is not allowed to mix formal accesses with accesses through pointers; our existing escapes like `withUnsafe*Pointer` must be used mutually exclusively with the property that's "locked" by the `with`. This means that, if you need raw memory inline in a class instance, and you allocated that storage using a property, it would pretty much always always a bug to access that property directly. In other words, in:

```swift
final class Counter {
    private var _lock = os_unfair_lock_s()
}

```

It would never be correct to access `self._lock`, because it might copy, and it would assert exclusive access on the storage and interleave formal accesses with raw pointer accesses.

I think it would be better to expose raw storage inside a class instance as just that, raw storage, and make the pointer the primary interface to the storage, since that's what you want anyway. We could express this as something that looks like a property wrapper, maybe:

```swift
final class Counter {
    @RawStorage private var _lock: UnsafeMutablePointer<os_unfair_lock_s>
}

```

That makes it much harder to misuse, because there's no way to accidentally access the storage as a property, and also means we don't have to expose similarly brittle APIs for getting pointers to arbitrary class properties. We can also relax the requirements on backing storage allocated this way so that it isn't subject to interference by exclusivity semantics, making it more appropriate for building low-level primitives or interfacing with existing ones.

---

<div class="post-metadata">

**Author:** ![johannesweiss](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/johannesweiss/32/38183_2.png) [@johannesweiss](https://forums.swift.org/u/johannesweiss)\
**Post date:** [November 8, 2019, 6:49pm UTC](https://forums.swift.org/t/exposing-the-memory-locations-of-class-instance-variables/30584/11 "2019-11-08T18:49:31Z")

</div>

Thanks so much @lorentey, I'm very strongly +1 on this. And for me, often doing some low-level, performance focussed programming, this is one of the most important proposals ever.

---

<div class="post-metadata">

**Author:** ![lorentey](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lorentey/32/1299_2.png) [@lorentey](https://forums.swift.org/u/lorentey)\
**Post date:** [November 8, 2019, 7:53pm UTC](https://forums.swift.org/t/exposing-the-memory-locations-of-class-instance-variables/30584/12 "2019-11-08T19:53:20Z")

</div>

> [@beccadax](#):
>
> Why not implement this safely-packaged version of the functionality ourselves?

That's exactly the plan -- but I felt important to first introduce the primitive on which the safe(r) construct would be built on. The `@Anchoring` property wrapper is going to be running into some pretty hard limits on what's reasonably achievable in this area on the library level; I expect (hope!) it will spur people to design something better.

This pitch highlights some lower-level issues that deserve serious consideration, and I don't want to distract attention from those by introducing them at the same time as a brand new, somewhat shaky abstraction.

If the followup abstraction is successful enough, we may well end up not needing to expose this API as public. (I think that would in fact be the outcome I prefer.)

> [@beccadax](#):
>
> Or implement the `with*` version of it while documenting that it’s okay to escape the pointer as long as you keep the base alive? An unsafe-by-default API seems like it’s inviting mistakes.

I was wrestling with this very question for days. What put me over the edge is that I think it would be unwise to teach people that it's sometimes okay to escape pointers out of closure-scoped pointer APIs. I prefer to add one unsafe API instead of slightly weakening a general pattern.

* * *

We could in theory have the new `MemoryLayout` API return a "safe" pointer:

```swift
struct AnchoredPointer<Pointee> {
  private let _anchor: AnyObject
  private let _pointer: UnsafeMutablePointer<Pointee>

  init(_ pointer: UnsafeMutablePointer<Pointee>, in anchor: AnyObject) {
    self._anchor = anchor
    self._pointer = pointer
  }

  func withScopedAddress<Result>(
    _ body: (UnsafeMutablePointer<Pointee>) throws -> Result
  ) rethrows -> Result {
    try withExtendedLifetime { 
      try body(_pointer)
    }
  }
}

extension MemoryLayout where T: AnyObject {
  func anchoredPointer<Value>(
    to key: ReferenceWritableKeyPath<T, Value>,
    in root: AnyObject
  ) -> AnchoredPointer<Value> { ... }

```

But this doesn't seem like particularly useful API _on its own_. (It would need to be wrapped into constructs that give it the high-level operations that are actually useful.) I'm especially worried about the retain/release traffic around `_anchor` -- which would clearly be unacceptable for atomic operations. I have a hare-brained scheme to try eliminating this overhead in the upcoming `@Anchoring` pitch, but I don't think we can reasonably do that if the underlying primitive insists on returning a strong reference.

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [November 8, 2019, 9:05pm UTC](https://forums.swift.org/t/exposing-the-memory-locations-of-class-instance-variables/30584/13 "2019-11-08T21:05:13Z")

</div>

> [@lorentey](#):
>
> I'm especially worried about the retain/release traffic around `_anchor` -- which would clearly be unacceptable for atomic operations. I have a hare-brained scheme to try eliminating this overhead in the upcoming `@Anchoring` pitch, but I don't think we can reasonably do that if the underlying primitive insists on returning a strong reference.

This is the sort of thing that it'd be nice to have explicit invocation of accessor coroutines for. If you were forced/strongly encouraged to access the property in a scoped access, using strawman syntax like this:

```swift
with lockAddr = self.anchoredProperty {
  use(lockAddr)
}

```

where `anchoredProperty` would be implemented using a `read` coroutine, and `with` would force the body of the `with` statement to be run during the coroutine access, then that should naturally establish a lifetime relationship between `self` and the pointer provided by `anchoredProperty` without explicit retain/release traffic.

Without coroutines, it seems like a `with*`-style higher order function could still manage this, maybe exploiting coroutines under the surface.

SIL does have an instruction for introducing ad-hoc lifetime dependencies between values. Another possibility could be that we expose that to the standard library as a builtin, to increase the likelihood that naive uses of the storage pointer are bound to the lifetime of the containing object. The effectiveness of that approach would be limited by how far the optimizer inlines, though, so you'd still need `withExtendedLifetime` if you're returning the pointer up the callstack.

---

<div class="post-metadata">

**Author:** ![drexin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/drexin/32/7573_2.png) [@drexin](https://forums.swift.org/u/drexin)\
**Post date:** [November 8, 2019, 9:51pm UTC](https://forums.swift.org/t/exposing-the-memory-locations-of-class-instance-variables/30584/14 "2019-11-08T21:51:55Z")

</div>

@lorentey Thanks so much for putting this together. Very happy to see the development in this area and very much looking forward to the nice things we can build on top.

---

<div class="post-metadata">

**Author:** ![lorentey](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lorentey/32/1299_2.png) [@lorentey](https://forums.swift.org/u/lorentey)\
**Post date:** [November 8, 2019, 11:19pm UTC](https://forums.swift.org/t/exposing-the-memory-locations-of-class-instance-variables/30584/15 "2019-11-08T23:19:28Z")

</div>

> [@Joe\_Groff](#):
>
> I don't think this is quite the right approach, though, because fundamentally the storage you want to allocate _isn't_ a property from Swift's perspective. The exclusivity expectations are fundamentally at odds with concurrency primitives like locks.

Agreed. However, the Law of Exclusivity, as introduced in [SE-0176](https://github.com/apple/swift-evolution/blob/master/proposals/0176-enforce-exclusive-access-to-memory.md), doesn't care what form an access takes, or what sort of variable it touches -- overlapping mutating access is currently strictly verboten in Swift. Restricting such access to dynamic variables doesn't keep us out of jail at all -- they too are illegal under the Law.

Obviously, this cannot stand; we need to be able to deal with concurrently mutable shared state in Swift, even if we'd only use this to provide a higher-level concurrency model (such as actors) to Swift applications. In order to do this, we need to punch carefully shaped holes into the Law of Exclusivity; specifically, we need to seriously start talking about variables, memory locations, atomic operations and memory orderings.

Swift code is _already_ using instance/global/static/captured/dynamic variables to represent mutable state shared across concurrent threads of execution -- it calls out to C & C++ code (such as Dispatch) to try escaping the Law, but this practice arguably still violates it. To wit, it implicitly assumes that C++'s memory orderings also apply to Swift code. (We need to explicitly state that this is indeed the case. The first step to doing that is that we need to admit that certain language constructs are mapped to specific memory locations, so that we can understand how to apply memory orderings to them. This pitch is really just an excuse to start talking about this.)

The holes we need to punch into the Law of Exclusivity will need to include allowances for overlapping calls to certain primitive atomic operations (i.e., we'll need to add a new "atomic" access to go with the current "read"/"assign"/"modify" set). I would find it weirdly asymmetric if this new access would be artificially restricted to dynamic variables, while the existing ones are defined on all sorts.

> [@Joe\_Groff](#):
>
> And in what little memory model Swift does have, it is not allowed to mix formal accesses with accesses through pointers; our existing escapes like `withUnsafe*Pointer` must be used mutually exclusively with the property that's "locked" by the `with` .

I may be missing something here, but as I understand it, overlapping read accesses are explicitly okay, no matter what form they take. So this code is perfectly fine:

```swift
class Foo { var value: Int = 42}

let foo = Foo()

// thread A
print(foo.value)

// thread B
print(foo[keyPath: \.value])

// thread C
withUnsafePointer(to: foo.value) { print($0.pointee) }

```

(Even assuming `withUnsafePointer` would provide the actual address of the ivar.)

> [@Joe\_Groff](#):
>
> This means that, if you need raw memory inline in a class instance, and you allocated that storage using a property, it would pretty much always always a bug to access that property directly. In other words, in:
> 
> ```swift
> final class Counter {
> private var _lock = os_unfair_lock_s()
> }
> 
> ```
> 
> It would never be correct to access `self._lock` , because it might copy, and it would assert exclusive access on the storage and interleave formal accesses with raw pointer accesses.

Objection, your honor! There are two places in particular where access through the property syntax is not just correct, but also highly desirable: during `init` and `deinit`.

These are guaranteed to be outside of any overlapping access, and in fact going through the usual exclusivity checks _may_ provide an extra layer of protection against lifetime issues. (If nothing else, TSAN could use the exclusivity assertion as an input signal.)

> [@Joe\_Groff](#):
>
> I think it would be better to expose raw storage inside a class instance as just that, raw storage, and make the pointer the primary interface to the storage, since that's what you want anyway. We could express this as something that looks like a property wrapper, maybe:
> 
> ```swift
> final class Counter {
> @RawStorage private var _lock: UnsafeMutablePointer<os_unfair_lock_s>
> }
> 
> ```
> 
> That makes it much harder to misuse, because there's no way to accidentally access the storage as a property, and also means we don't have to expose similarly brittle APIs for getting pointers to arbitrary class properties. We can also relax the requirements on backing storage allocated this way so that it isn't subject to interference by exclusivity semantics, making it more appropriate for building low-level primitives or interfacing with existing ones.

I did seriously consider this approach, but I found it raises more questions than it answers.

- How would this storage get initialized? We don't want to lose the statically enforced guarantee that all ivars must get created before `init` returns.
- How would this storage get deinitialized? Some synchronization constructs will definitely include strong references, and these should really just behave like regular strong references when it comes to deinitialization. (We'll introduce an atomically initializable lazy reference in the first batch, and I'm pretty sure we'll also build a full `AtomicReference` type when we add double-wide atomics. )
- How would `@RawStorage` compose into other language features? How would it enable us to provide an _ergonomic but lightweight_ `UnsafeLock` construct in the stdlib (or some concurrency module)?

The last point is essential -- we do not want to force developers to carefully manage initialization/deinitialization of every single synchronization construct, or to litter unsafe pointers throughout their code.

APIs like `pthread_mutex_destroy` will cause problems anyway, since property wrappers cannot currently hook into class deinitialization. However, there is a large swath of constructs that can be modeled with a general-purpose property wrapper built around `unsafeAddress(of:in:)`.

> [@Joe\_Groff](#):
>
> This is the sort of thing that it'd be nice to have explicit invocation of accessor coroutines for.

Yes yes yes! If I understand correctly, [my hare-brained scheme](https://github.com/apple/swift/blob/5264dd2126fbfd33388bde691e88bf6a645a4e54/stdlib/public/core/Anchored.swift) is going to try doing something very much like that.

```swift
class Foo {
  @Anchoring var counter: AtomicInt
}

let foo = Foo()

foo.counter.wrappingIncrement()
print("Current value: \(foo.counter.load())")

```

The `@Anchoring` property wrapper would yield (not return) the `AtomicInt` struct (which would effectively be a wrapper around `AnchoredPointer`), and this would _hopefully_ be a constrained enough setup that we could add an optimization that gets rid of the retain/release in the common case where the yielded value doesn't escape the coroutine, and the operation doesn't call `isKnownUniquelyReferenced()`. (As long as everything is fully `@inlinable` and `@frozen`).

We'd still rely on the strong reference inside the `AtomicInt` struct (in its full retain/release glory) in case someone copies the value into, say, a local variable (which we cannot practically prevent in today's Swift).

```swift
let myQuestionableCopy = foo.counter

myQuestionableCopy.wrappingIncrement() // This needs to be safe

```

I'm working on formalizing the `@Anchoring` pitch as quickly as I can. (As always, writing these things is exquisite agony.)

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [November 9, 2019, 12:04am UTC](https://forums.swift.org/t/exposing-the-memory-locations-of-class-instance-variables/30584/16 "2019-11-09T00:04:58Z")

</div>

> [@lorentey](#):
>
> Agreed. However, the Law of Exclusivity, as introduced in [SE-0176](https://github.com/apple/swift-evolution/blob/master/proposals/0176-enforce-exclusive-access-to-memory.md), doesn't care what form an access takes, or what sort of variable it touches -- overlapping mutating access is currently strictly verboten in Swift. Restricting such access to dynamic variables doesn't keep us out of jail at all -- they too are illegal under the Law.

The Law of Exclusivity only governs operations that fall under its formal model, like properties and variables. Things like raw memory accesses are mostly outside of the model, and don't rest on the semantics of any language-managed storage, which is why you can get away with putting locks in raw allocated memory, doing atomic operations on them, etc., and why things like `withUnsafePointer` are so restricted in how they allow managed things to be temporarily treated like raw memory. I think we should avoid involving the mechanics of regular stored properties in this mechanism as much as we possibly can, because it leads to a much more understandable semantic model—you just have the "usual" pitfalls of raw memory access, without an additional layer of higher-level semantic guarantees.

> [@lorentey](#):
>
> Swift code is _already_ using instance/global/static/captured/dynamic variables to represent mutable state shared across concurrent threads of execution -- it calls out to C & C++ code (such as Dispatch) to try escaping the Law, but this practice arguably still violates it. To wit, it implicitly assumes that C++'s memory orderings also apply to Swift code.

This is of a different nature to what you're proposing, though; the sequencing semantics we're getting by calling out to C happen _around_ Swift formal accesses, and synchronize on entities that are not managed by Swift's semantics such as queues or locks stored on raw memory.

> [@lorentey](#):
>
> We need to explicitly state that this is indeed the case. The first step to doing that is that we need to admit that certain language constructs are mapped to specific memory locations, so that we can understand how to apply memory orderings to them. This pitch is really just an excuse to start talking about this.

We try really hard _not_ to saddle regular high-level code with unnecessary low-level semantics that are irrelevant to most people by default. We don't want to fall into the trap C and C++ have where they try to have their low-level cake and eat their high-level optimizations too with rules that are overly complex and satisfy nobody. By all means, objects are already effectively tied to a memory address, and it makes sense to be able to allocate unmanaged storage with a similarly-fixed address inline inside objects, but I think getting that sort of raw storage ought to be something opt-in on the storage and not something that potentially any property can be turned into.

> [@lorentey](#):
>
> The holes we need to punch into the Law of Exclusivity will need to include allowances for overlapping calls to certain primitive atomic operations (i.e., we'll need to add a new "atomic" access to go with the current "read"/"assign"/"modify" set). I would find it weirdly asymmetric if this new access would be artificially restricted to dynamic variables, while the existing ones are defined on all sorts.

When we get move-only types, atomic accesses should slot into the existing model naturally like they do in Rust, where atomic mutation operations apply to nonexclusively `read`-borrowed references.

> [@lorentey](#):
>
> I may be missing something here, but as I understand it, overlapping read accesses are explicitly okay, no matter what form they take. So this code is perfectly fine:
> 
> ```swift
> class Foo { var value: Int = 42}
> 
> let foo = Foo()
> 
> // thread A
> print(foo.value)
> 
> // thread B
> print(foo[keyPath: \.value])
> 
> // thread C
> withUnsafePointer(to: foo.value) { print($0.pointee) }
> 
> ```
> 
> (Even assuming `withUnsafePointer` would provide the actual address of the ivar.)

Well-typed nonatomic reads are probably practically fine, but you would need more than that for anything where you'd want to use this feature. It's a bit tricky, though, because the compiler can generally copy its way out of situations where formal accesses might interfere with reads. We're more than likely going to copy `foo.value` to a temporary in this example so that we don't block off writes to `foo.value` during the `withUnsafePointer` block.

> [@lorentey](#):
>
> Objection, your honor! There are two places in particular where access through the property syntax is not just correct, but also highly desirable: during `init` and `deinit` .
> 
> These are guaranteed to be outside of any overlapping access, and in fact going through the usual exclusivity checks _may_ provide an extra layer of protection against lifetime issues. (If nothing else, TSAN could use the exclusivity assertion as an input signal.)

I think there are valid arguments in the other direction, that you want to be able to initialize/deinitialize the storage on your own terms in init/deinit without the usual restrictions on initializing properties. There could be other use cases for this feature where the object wants to allocate some raw storage that it leaves uninitialized in some conditions. Ideally we could obsolete at least some uses of `ManagedBuffer` for that purpose with this feature.

> [@lorentey](#):
>
> I did seriously consider this approach, but I found it raises more questions than it answers.
> 
> - How would this storage get initialized? We don't want to lose the statically enforced guarantee that all ivars must get created before `init` returns.
> - How would this storage get deinitialized? Some synchronization constructs will definitely include strong references, and these should really just behave like regular strong references when it comes to deinitialization. (We'll introduce an atomically initializable lazy reference in the first batch, and I'm pretty sure we'll also build a full `AtomicReference` type when we add double-wide atomics. )

If you have a pointer to the storage, you can still use `UnsafeMutablePointer`'s `.initialize()`/`.destroy()` methods to initialize and destroy the storage as if it were a regular property.

> [@lorentey](#):
>
> How would `@RawStorage` compose into other language features? How would it enable us to provide an _ergonomic but lightweight_ `UnsafeLock` construct in the stdlib (or some concurrency module)?
> 
> The last point is essential -- we do not want to force developers to carefully manage initialization/deinitialization of every single synchronization construct, or to litter unsafe pointers throughout their code.

I don't think you can get there until we get move-only types. But it seems like you could associate `RawStorage` with a protocol for initializing types from pointers, like:

```swift
protocol PointerToStorage {
  associatedtype Storage

  init(storage: UnsafeMutablePointer<Storage>)
}

struct UnsafeLock: PointerToStorage {
  var storage: UnsafeMutablePointer<pthread_mutex_t>
}

```

It would also make sense to me to allow `RawStorage` inside structs, and have the same guarantees about the raw storage inside the struct when the struct itself is transitively allocated in `RawStorage`, which would allow you to compose other wrappers around it.

---

<div class="post-metadata">

**Author:** ![lorentey](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lorentey/32/1299_2.png) [@lorentey](https://forums.swift.org/u/lorentey)\
**Post date:** [November 9, 2019, 5:43am UTC](https://forums.swift.org/t/exposing-the-memory-locations-of-class-instance-variables/30584/17 "2019-11-09T05:43:34Z")

</div>

> [@Joe\_Groff](#):
>
> The Law of Exclusivity only governs operations that fall under its formal model, like properties and variables. Things like raw memory accesses are mostly outside of the model, and don't rest on the semantics of any language-managed storage, which is why you can get away with putting locks in raw allocated memory, doing atomic operations on them, etc., and why things like `withUnsafePointer` are so restricted in how they allow managed things to be temporarily treated like raw memory.

I argue that a dynamic variable created by allocating and initializing storage through an `UnsafeMutablePointer` isn't any less a variable than an ivar -- it must have just as well-defined semantics. The Law of Exclusivity must necessarily apply to it, like it does to all variables:

> [@SE-0176](#):
>
> We should add a rule to Swift that two accesses to the same variable are not allowed to overlap unless both accesses are reads. By "variable", we mean any kind of mutable memory: global variables, local variables, class and struct properties, and so on.

`UnsafeMutablePointer.pointee` is mutable memory. `Array.subscript`'s addressor returns mutable memory. There is nothing truly _raw_ about these -- it's true they have their own unique flow for creation/destruction, but so does every other form of variable.

(It's also true that exclusivity violations through unsafe pointers typically won't get diagnosed in regular production use. I don't see how this is a problem: these pointers are marked unsafe for a reason.)

There is a distinction to be made between variables that are backed with a stable memory location and variables that aren't. (E.g., the latter inherently cannot participate in any concurrent access.)

> [@Joe\_Groff](#):
>
> We try really hard _not_ to saddle regular high-level code with unnecessary low-level semantics that are irrelevant to most people by default. We don't want to fall into the trap C and C++ have where they try to have their low-level cake and eat their high-level optimizations too with rules that are overly complex and satisfy nobody.

My point is that sadly this ship has already sailed. Swift encourages people to synchronize access on shared mutable state using C and C++ constructs, so Swift has de facto adopted the C++ concurrency model, including the scary bits about _dependency-ordered-before_ this and _inter-thread-happens-before_ that. We just neglected to specify exactly what this means -- which is a standing invitation to concurrency bugs.

How can `os_unfair_lock`s or dispatch queues (or indeed, the existing internal atomic operations in the stdlib) be safe to use in Swift code without specifying how (say) a regular assignment to an everyday Swift closure capture variable interacts with a subsequent releasing store to an `os_unfair_lock`?

I don't think it's viable for us to keep being coy about how sharable variables (such as class ivars) work. By merely observing that Swift apps have been able to successfully use locks like os\_unfair\_lock to synchronize access to shared data stored in these language constructs, and knowing _nothing whatsoever_ about the inner workings of the Swift compiler, we can already deduct that

1. Shared variables must be associated with a memory location (because addressable memory is the only way to share mutable state across threads).
2. All participating threads agree on the location of this memory (or it wouldn't behave like a shared variable at all).
3. The last value assigned to a shared variable that precedes an `unlock` operation on the lock is guaranteed to get translated to a corresponding store to its known memory location, and that store is guaranteed to get executed _before_ the `unlock` operation issues its releasing atomic store on the mutex variable. (Otherwise locks wouldn't work.)
4. The first read of any shared variable that follows a `lock` operation (which we know issues an acquiring load on the mutex variable) must be translated into a regular load operation on the variable's memory location. (Otherwise locks wouldn't work.)

So class ivars, closure captures, global variables, etc. _evidently_ do all have stable addresses and their accesses must be following a sensible memory model that is compatible with the memory orderings defined by all those smart people in C++ land. Again, all this follows from the mere fact that locks imported from C APIs demonstrably work in Swift.

I sincerely hope none of this is surprising or controversial!

(...is it?) 😟

> [@Joe\_Groff](#):
>
> By all means, objects are already effectively tied to a memory address, and it makes sense to be able to allocate unmanaged storage with a similarly-fixed address inline inside objects, but I think getting that sort of raw storage ought to be something opt-in on the storage and not something that potentially any property can be turned into.

I wholeheartedly agree with this last part. Let's make the ivar thing opt-in, as long as we can agree on a nice way to implement it. (The API in this pitch is not critical to make public -- I have no objection to limiting its (direct) use to the stdlib, as long as we provide safer abstractions that provide the same benefits. We do badly need to access specific ivar locations within the stdlib.)

But I really _really_ wouldn't want to treat synchronization constructs as unmanaged raw storage. These things aren't built out of special artisanal bits that are only meaningful to C++ code: they contain regular everyday types that we already model in the stdlib. They should be _(and already are!)_ initialized/destroyed as regular Swift values. `os_unfair_lock_s` is imported as a boring struct holding an integer ivar; it's no more special than, say, `NSRange` is.

The only thing that makes these types special is the operations they expose for use between their init/deinit. Given that Swift is a "high-performance system programming language", my expectation is that I should be able to implement these operations directly in Swift, and if anything, this should be less difficult than it is in C++. Requiring people to mess around with raw pointers is definitely not the right direction for that.

I agree that non-copyable types would be the appropriate abstraction to represent these constructs. Unfortunately, we aren't currently modeling them in Swift. On the other hand, just as unfortunately, we're badly overdue for adding usable atomics, and I think it would be a mistake to delay it further.

---

<div class="post-metadata">

**Author:** ![Jean-Daniel](https://avatars.discourse-cdn.com/v4/letter/j/977dab/32.png) [@Jean-Daniel](https://forums.swift.org/u/Jean-Daniel)\
**Post date:** [November 9, 2019, 10:56am UTC](https://forums.swift.org/t/exposing-the-memory-locations-of-class-instance-variables/30584/19 "2019-11-09T10:56:59Z")

</div>

> [@lorentey](#):
>
> Let's make the ivar thing opt-in, as long as we can agree on a nice way to implement it.

One benefit of having this opt-in and explicit is that it would be possible to clearly define its "API resilience", and not relying of having the user of such field guess if it will work and have to check for every usages.

> [@lorentey](#):
>
> I agree that non-copyable types would be the appropriate abstraction to represent these constructs. Unfortunately, we aren't currently modeling them in Swift. On the other hand, just as unfortunately, we're badly overdue for adding usable atomics, and I think it would be a mistake to delay it further.

If this pitch is only about workaround current Swift limitation, I prefer this API to remain private, so we can replace it by the proper construct later.

---

<div class="post-metadata">

**Author:** ![glessard](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/glessard/32/409_2.png) [@glessard](https://forums.swift.org/u/glessard)\
**Post date:** [November 9, 2019, 12:48pm UTC](https://forums.swift.org/t/exposing-the-memory-locations-of-class-instance-variables/30584/20 "2019-11-09T12:48:36Z")

</div>

I have assumed for a couple years now that native atomics would _only_ happen after move-only types arrived. @lorentey and @Joe_Groff appear to agree that move-only types would be the better model.

This raises the question: do we have an idea how far away are move-only types?

What are other uses for the functionality pitched here? I personally have only wanted/needed this for atomics.

---

<div class="post-metadata">

**Author:** ![glessard](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/glessard/32/409_2.png) [@glessard](https://forums.swift.org/u/glessard)\
**Post date:** [November 9, 2019, 8:28pm UTC](https://forums.swift.org/t/exposing-the-memory-locations-of-class-instance-variables/30584/21 "2019-11-09T20:28:04Z")

</div>

> [@Jean-Daniel](#):
>
> If this pitch is only about workaround current Swift limitation, I prefer this API to remain private, so we can replace it by the proper construct later.

Another question, especially to Karol and Joe: if this is "only" about a workaround and it were to go through as an API private to the standard library, would it prevent a public atomics implementation from landing in the standard library? If not, would such an implementation be hamstrung later on?

[Next page](https://forums.swift.org/t/exposing-the-memory-locations-of-class-instance-variables/30584.md?page=2)
