-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
add invokelatest to circumvent world-age problems #19784
Conversation
(I modeled the |
@@ -584,18 +584,18 @@ function uv_getaddrinfocb(req::Ptr{Void}, status::Cint, addrinfo::Ptr{Void}) | |||
cb = unsafe_pointer_to_objref(data)::Function | |||
pop!(callback_dict,cb) # using pop forces an error if cb not in callback_dict | |||
if status != 0 || addrinfo == C_NULL | |||
cb(UVError("uv_getaddrinfocb received an unexpected status code", status)) | |||
invokelatest(cb, UVError("uv_getaddrinfocb received an unexpected status code", status)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
our libuv callbacks should never be invoking callbacks directly. we've refactored most of them, but it looks like this one still needs to be fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, but clearly a matter for a different PR...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM other than the minor issues commented above.
I also think it's useful to have a version of cfunction
that doesn't capture the world (and therefore might do conditional dynamic dispatch).
src/gf.c
Outdated
argv[0] = f; | ||
for(int i=1; i<nargs+1; i++) | ||
argv[i] = jl_fieldref(argtuple, i-1); | ||
size_t last_age = jl_get_ptls_states()->world_age; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be a jl_ptls_t ptls = jl_get_ptls_states();
at the beginning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you fixed another one....
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I fixed the fix
src/julia.h
Outdated
@@ -1381,6 +1381,7 @@ STATIC_INLINE int jl_vinfo_usedundef(uint8_t vi) | |||
|
|||
JL_DLLEXPORT jl_value_t *jl_apply_generic(jl_value_t **args, uint32_t nargs); | |||
JL_DLLEXPORT jl_value_t *jl_invoke(jl_method_instance_t *meth, jl_value_t **args, uint32_t nargs); | |||
JL_DLLEXPORT jl_value_t *jl_invoke_latest(jl_value_t *f, jl_value_t *argtuple); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need to make this a C api? I think we can leave it out so that changing the implementation (likely) won't be a breaking change at all.
1270f03
to
839336f
Compare
I guess Compat for this |
Can we get this in before the feature freeze? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
jl_f__apply_pure
would be a better model for how to implement this. But I'm not sure I like this function (that's why I didn't include it in the PR and went with the more annoying eval
call), or will go with a different way entirely for making cfunction work. We'll definitely put something in before the feature freeze though.
If we do go with this, it should have a not-pure guard at the top (
Line 409 in c38a5a3
jl_error("task switch not allowed from inside staged nor pure functions"); |
I did look at |
(Even if there are better ways to do |
@vtjnash, does it look good now, aside from apparently unrelated Travis problems? |
Rebased. Good to merge? |
Bump, @vtjnash |
I think I want to go a different direction with this (https://discourse.julialang.org/t/proposal-for-a-first-class-dispatch-wrapper/1127/2?u=jameson), which is why I've been slow here. |
59a96fa
to
53e54a8
Compare
Ping @vtjnash. |
Bump. It seems we should merge this, since otherwise people will just define
which doesn't seem better. |
Rebased. |
I'm just bike-shedding, but should we call this |
It takes separate arguments, not a container, so it is invoke-like. |
Can this still make it into 0.6? Kind of late now, but it's been in the works since before the planned feature freeze. (cc @tkelman) |
I suddenly became very interested in this when I realized what huge overhead making and eval'ing expressions is adding to remote operations. |
Will this be applicable here - https://github.com/JuliaString/Format.jl/blob/newmaster/src/cformat.jl#L6 - too? If so, an update of this section - https://docs.julialang.org/en/latest/manual/methods.html#Redefining-Methods-1 - stating performance implications of a second eval and a fix via |
Yes looks like it would also be applicable there. I'm not sure how much we want to commit to this function, but I guess it would be ok to mention in the docs. |
Are we sure we want it exported? |
I can change it to a non-exported function and remove it from NEWS if that is what people prefer for 0.6. |
I think @JeffBezanson and @vtjnash's call, but it seems like an option. |
I'd rather not export it (especially at this point in the release cycle). |
I would keep the NEWS entry |
src/builtins.c
Outdated
{ | ||
jl_ptls_t ptls = jl_get_ptls_states(); | ||
size_t last_age = ptls->world_age; | ||
ptls->world_age = jl_world_counter; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a if (!ptls->in_pure_callback)
guard on this line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean like
if (ptls->in_pure_callback)
jl_error("invokelatest cannot be used in a generated or pure functions");
similar to jl_toplevel_eval_in
or jl_switchto
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No error is necessary in this case. It just should ignore jl_world_counter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, done, though I don't really understand why this is the case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's mostly just by-definition. A pure function is one for which the world-counter has no effect. In those other examples, those two functions try to change jl_world_counter
, so they have to throw an error. In this example, it's only trying to read jl_world_counter
, which is OK, as long as it can't see the value change.
base/essentials.jl
Outdated
|
||
Calls `f(args...)`, but guarantees that the most recent method of `f` | ||
will be executed. This is useful in specialized circumstances, | ||
especially `cfunction` callbacks that may extract a Julia `Function` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't need to mention cfunction anymore, it's not relevant there anymore. But perhaps should add a mention of long-running event loops?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking of something like JuliaGizmos/Reactive.jl#131, where it's not calling eval, but it wants to be able to react when other Tasks call eval.
Removed the export, updated the docstring, and added an |
In
cfunction
callbacks (#19774) and functions that calleval
or similar (#19770), one occasionally runs into problems where an obsolete version of a function is called when the latest one is desired. Currently, the workaround is to calleval
, which is somewhat awkward and error-prone due to the necessity of constructing anExpr
. This PR adds aninvokelatest(f, args...)
function that calls the latest version off(args...)
.