-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Ensuring class_getter
runs exactly once under concurrent access
#14905
Comments
class_getter
runs exactly once under concurrent access
Perhaps we can jerry rig an atomic compare and set on the type id? Then we'll just need an otherwise unused type to signal that someone else is already in the process of calculating. |
Wouldn't that only work for mixed unions? |
I suppose we could force a mixed union using an appropriate type to signal work in progress? |
This is related to #15085. Perhaps we could use the same mechanism for both (for example a spin-lock on the type id). |
This issue has been mentioned on Crystal Forum. There might be relevant details there: https://forum.crystal-lang.org/t/charting-the-route-to-multi-threading-support/7320/1 |
The simplest solution would be to replace the "lazy method" with an explicit assignment: thread safety would handled by With the exception that Note: apparently codegen will always declare & initialize all class vars with an initializer (default value); while LLVM will optimize them away if the program never accesses them, dev builds (i.e. |
I tried to reused I'll have to write something custom, that will take and call an actual |
I was eventually able to reuse Using the captured block would allow for a better optimization: always inline the quick check and never inline the actual initialization. But capturing the block would be breaking change (can't We might want to introduce an opt-in flag. |
Capturing the block would be nice 👍 |
….init_runtime` (#15369) Adds `Crystal.init_runtime` which calls `Thread.init`, `Fiber.init` to explicitly initialize the class variables defined on `Thread` and `Fiber`. In order to implement #14905 we'll need the ability to access `Fiber.current` which depends on `Thread.current` but if these accessors use the class getter/property macros then we'll enter an infinite recursion.
A
class_getter
with a block usually runs exactly once:However, if the current fiber is ever suspended, the block might be run multiple times:
And if
-Dpreview_mt
is in effect, the block also gets run more than once, even without theFiber.yield
.Often,
Foo.x
represents some kind of cached object that might be expensive to compute, like #14891 and the Unicode data tables; if we also disregard the block's return value, then this would include the various interrupt handlers guarded byAtomic::Flag
s too. There should be an easier way in the standard library to ensure this block is really run exactly once, regardless of the degree of concurrent access.Constants are one alternative, but whether they run at program startup or on first access is rather opaque, and also they are slightly broken, such as in #13054.
This could apply to
class_property
as well, and less likely to the instance variantsgetter
andproperty
.The text was updated successfully, but these errors were encountered: