Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-9144] Low-level atomics in Swift #51640

Open
swift-ci opened this issue Oct 30, 2018 · 10 comments
Open

[SR-9144] Low-level atomics in Swift #51640

swift-ci opened this issue Oct 30, 2018 · 10 comments
Assignees
Labels
feature A feature request or implementation standard library Area: Standard library umbrella swift evolution pending discussion Flag → feature: A feature that has a Swift evolution proposal currently in review

Comments

@swift-ci
Copy link
Collaborator

swift-ci commented Oct 30, 2018

Previous ID SR-9144
Radar rdar://17171396
Original Reporter freak4pc (JIRA User)
Type Bug
Environment

Xcode 10 / Swift 4.2 / High Sierra

Additional Detail from JIRA
Votes 1
Component/s Standard Library
Labels Bug
Assignee @lorentey
Priority Medium

md5: b50a38690fc8b14739d06ef73d3de3c8

Issue Description:

Using the following methods:

OSAtomicCompareAndSwap32Barrier
OSAtomicIncrement32Barrier
OSAtomicDecrement32Barrier
OSAtomicOr32OrigBarrier
OSAtomicXor32OrigBarrier

Provides deprecation warnings under Swift 4.2:

'OSAtomicCompareAndSwap32Barrier' was deprecated in watchOS 3.0: Use atomic_compare_exchange_strong() from <stdatomic.h> instead

Unfortunately, there is no Swift interface for stdatomic.h which forces us to use a really icky low-level LLVM implementation instead: https://github.com/ReactiveX/RxSwift/blob/45c85f9fc1ee1a007984cd9a61c098c315c7c9d2/RxAtomic/include/RxAtomic.h#L16-L42 in C.

It seems like a bug to me that there's a deprecation warning with no actual deprecation path. Any thoughts?

@belkadan
Copy link
Contributor

I don't think there are any safe ways to use atomic operations from Swift right now. Even the helpers you've written aren't really safe because nothing stops you (or the compiler) from copying the struct around.

@rjmccall, @airspeedswift, do we have a bug tracking the general request already?

@rjmccall
Copy link
Member

Hmm, maybe not in JIRA.

@swift-ci
Copy link
Collaborator Author

Comment by Krunoslav Zaher (JIRA)

I've wrote unit tests to confirm that the compiler is performing the expected behavior regarding atomic operations.

https://github.com/ReactiveX/RxSwift/blob/master/Tests/RxSwiftTests/AtomicTests.swift

I understand that the compiler doesn't make any guarantees regarding additional copying of the struct, but can anybody provide any reason/rationale why would the Swift compiler decide to perform additional copying of these structs around instead of just passing the pointer to atomic operations?

@swift-ci
Copy link
Collaborator Author

swift-ci commented Oct 31, 2018

Comment by Krunoslav Zaher (JIRA)

Is there any timeline when will the Swift compiler allow using atomic operations equivalent to c11 atomics or to deprecated OSAtomic*?

@rjmccall
Copy link
Member

rjmccall commented Nov 2, 2018

The main thing is that, not knowing that the struct is used as part of an atomic sequence, we reserve the right to rearrange and break up its storage in ways that would defeat atomicity. Forming a pointer to e.g. an Int would require us to reassemble that into the normal ABI, but that guarantee only lasts for the lifetime of that pointer.

@swift-ci
Copy link
Collaborator Author

swift-ci commented Nov 4, 2018

Comment by Krunoslav Zaher (JIRA)

@rjmccall Thank you for taking the time to answer my question.

Let me try to rephrase the question.

I'm aware that Swift compiler could in theory decide to rearrange the Int32 storage in ways that would defeat atomicity and only synthesize valid pointer during the mutating method call, but that doesn't really answer my question in full.

I'm trying to find out is anyone aware of any reasons why would the Swift compiler decide to transform code like this.

 var atomic = AtomicPrimitive()  
DispatchQueue.main.async

{     atomic.fetchOr(0)  }

Atomic definition can be found here.

into something that would defy the atomic operations. E.g. I'm aware that if one has a property in a class that has didSet or willSet then the compiler will perform additional copying.

class A {
  var notAtomic: AtomicInt { didSet {  print("Atomic") } }
}

let a = A()

a.notAtomic.fetchOr(8) // <– fail

@swift-ci
Copy link
Collaborator Author

swift-ci commented Nov 4, 2018

Comment by Krunoslav Zaher (JIRA)

If the Swift compiler makes absolutely no promises, then what is the rationale for adding reduce(into: method into the public API.

This means that my O(n) algorithms could become O(n^2) algorithms at any moment.

@rjmccall
Copy link
Member

rjmccall commented Nov 6, 2018

Swift can make a large number of high-level guarantees (e.g. that a stored property will be modified "directly" without introducing a semantic copy) without having to make fine-grained low-level guarantees like pointer equality.

In general, the exclusivity rules on structs prohibit them from being used to implement a meaningful atomic API: you cannot modify `self` in a non-`mutating` method, and it is illegal for other threads to concurrently call any other method while a `mutating` method is underway.

@lorentey
Copy link
Member

I'm taking this as I'm working on introducing low-level atomic operations.

Atomics require stable memory locations, which are currently achievable by either

  • dynamically allocating storage, or

  • using ManagedBuffer APIs to carve out inline storage inside a class instance.

Therefore, we are building unsafe atomic constructs that specifically fit these two cases. We expect that move-only (or non-movable) types will eventually replace these with memory-safe alternatives, but it makes sense to still add them so that people can start experimenting with concurrency support in Swift.

Swift-evolution pitch: https://gist.github.com/lorentey/cf8703b5974ebe8f85cfb92a6628880d

Forum thread:
https://forums.swift.org/t/low-level-atomic-operations/34683

Implementation:
#30553

@typesanitizer
Copy link

Should we close this since swift-atomics is now available?

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@AnthonyLatsis AnthonyLatsis added feature A feature request or implementation swift evolution proposal needed Flag → feature: A feature that warrants a Swift evolution proposal swift evolution pending discussion Flag → feature: A feature that has a Swift evolution proposal currently in review and removed bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. swift evolution proposal needed Flag → feature: A feature that warrants a Swift evolution proposal labels Oct 25, 2023
@AnthonyLatsis AnthonyLatsis linked a pull request Oct 25, 2023 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature A feature request or implementation standard library Area: Standard library umbrella swift evolution pending discussion Flag → feature: A feature that has a Swift evolution proposal currently in review
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants