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

More "thread-safe" LazyString #44936

Merged
merged 10 commits into from
Apr 13, 2022
Merged

More "thread-safe" LazyString #44936

merged 10 commits into from
Apr 13, 2022

Conversation

tkf
Copy link
Member

@tkf tkf commented Apr 11, 2022

This patch makes LazyString thread-safe in the sense that

## Safety properties for concurrent programs
A lazy string itself does not introduce any concurrency problems even if it is printed in
multiple Julia tasks. However, if `print` methods on a captured value can have a
concurrency issue when invoked without synchronizations, printing the lazy string may cause
an issue. Furthermore, the `print` methods on the captured values may be invoked multiple
times.

It's probably a non-issue ATM but it's also very cheap to do this anyway. I just noticed it while writing #44935.

@tkf tkf added the multithreading Base.Threads and related functionality label Apr 11, 2022
base/strings/lazy.jl Outdated Show resolved Hide resolved
end
end
return l.str
old = swapfield!(l, :str, str, :acquire_release)
Copy link
Member

@vtjnash vtjnash Apr 11, 2022

Choose a reason for hiding this comment

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

You appear to have the @atomic macros, so does this work?

Suggested change
old = swapfield!(l, :str, str, :acquire_release)
old = @atomicswap :acquire_release l.str = str

But it is not actually the function you seem to have meant to call, which seems to be:

Suggested change
old = swapfield!(l, :str, str, :acquire_release)
old, = @atomicreplace :acquire_release l.str nothing => str

Copy link
Member Author

@tkf tkf Apr 12, 2022

Choose a reason for hiding this comment

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

Ah, yes, thanks, I needed a CAS there.

We can't use the macros for operations due to the missing length(::Array) method at this point. I juggled around the definitions just enough for @atomic field::T. Or is it better to define some array methods earlier?

Copy link
Member Author

@tkf tkf Apr 12, 2022

Choose a reason for hiding this comment

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

Or is it better to define some array methods earlier?

Maybe this is simple enough: b8dd080

Copy link
Member

@vtjnash vtjnash left a comment

Choose a reason for hiding this comment

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

Should we add a serialize method also, which drops the data and just keeps the string:

serialize(s::AbstractSerializer, l::LazyStr) =
    serialize(s, _LazyStr((), string(l)))

Copy link
Member

@JeffBezanson JeffBezanson left a comment

Choose a reason for hiding this comment

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

Nice, thanks!!

@tkf tkf merged commit b6a6875 into JuliaLang:master Apr 13, 2022
@tkf tkf deleted the atomic-lazystr branch April 13, 2022 02:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
multithreading Base.Threads and related functionality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants