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

Fix Atomic#swap with reference types #6428

Merged
merged 1 commit into from Jul 28, 2018
Merged

Fix Atomic#swap with reference types #6428

merged 1 commit into from Jul 28, 2018

Conversation

JacobUb
Copy link
Contributor

@JacobUb JacobUb commented Jul 22, 2018

Previously the compiler crashed with "Module validation failed: atomicrmw operand must have integer type!".
(followed the example of #compare_and_set)

@RX14
Copy link
Contributor

RX14 commented Jul 22, 2018

Do all the other operations work?

@JacobUb
Copy link
Contributor Author

JacobUb commented Jul 22, 2018

add sub and nand or xor min and max all have the same problem when used with reference types but I only managed to get swap to work.
Edit: Could such low level operations even understand that a string can be added to another for example?

@RX14
Copy link
Contributor

RX14 commented Jul 23, 2018

I guess they should check for references and error out with a nicer error message (use macro raise).

@@ -157,7 +157,12 @@ struct Atomic(T)
# atomic.get # => 10
# ```
def swap(value : T)
Ops.atomicrmw(:xchg, pointerof(@value), value, :sequentially_consistent, false)
{% if T.union? && T.union_types.all? { |t| t == Nil || t < Reference } || T < Reference %}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look at the compare_and_set method above for how to implement this. It uses different cases for nillable references and references. Currently this wont work for nilable references.

Copy link
Contributor Author

@JacobUb JacobUb Jul 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does work and I added a test specifically for that case. The difference from compare_and_set has to do with the return value of the method, not with the type of T.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, my bad.

It looks to me then like compare_and_set should work without the special case for nilables as Pointer(Void).null.as(String?) == nil.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried what you suggested and it appears to work but perhaps whoever implemented it knows of some edge case we do not.
Anyway, that is a matter for another issue/PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Exilor yup, which is why I approved this :)

@JacobUb
Copy link
Contributor Author

JacobUb commented Jul 23, 2018

They probably should but that's outside the scope of this PR.

Copy link
Member

@sdogruyol sdogruyol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @Exilor 👍

@sdogruyol sdogruyol merged commit e8ec7f2 into crystal-lang:master Jul 28, 2018
@sdogruyol sdogruyol added this to the Next milestone Jul 28, 2018
@RX14 RX14 modified the milestones: Next, 0.26.0 Jul 30, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants