You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[This may be out-of-date, but I'm going to import it anyway and look at it later.]
In the current Java API, the heavily-overloaded isolated() function can take several different forms of argument (Runnable, Supplier<R>, Consumer<T>, Function<T,R>, and probably a few others). In each, it essentially boils down to
Create a new publishable live child context.
In that context, call the user-provided function, passing in any user-provided arguments, and remember the value returned.
Attempt to publish the child context.
This may result in rerunning tasks.
If the publish succeeds, return the remembered value.
If it doesn't succeed, and the options to the function specify retrying, drop the child context on the floor and go around again.
This is fine when the function is a simple Runnable or Consumer, but it runs into problems when it's something that wants to return a value. Logically, the value should be the one was computed by the function at the time of successful publication, but
Rerunning tasks cleans up any modifications to the managed space, so all of the side effects are correct, but it doesn't change the value returned by the function, and
Even if we could figure out how to get the function to recompute its value (which we can't), we've already cached the old value before we try the publish.
This implies that it's not safe to use isolated() blocks that return values, and we should probably remove them. (Note that this only applies to isolated(), which tries to publish. It doesn't apply to inReadOnlySnapshot(), detached(), or inSnapshot().) Rather, what should happen is that the isolated() call should take a Runnable or Consumer, which should make modifications in such a way that something outside of the child context can compute the overall result. This could be done by calling methods on an argument passed in or by modifying objects bound to the closure. At the end, these external arguments would have consistent data, and the value could be computed.
Note that this implies that when a task is re-run, when it makes calls on these objects, the new calls need to replace the old ones. (This would be a good use of the accumulators and task-dependent data structures, but could apply to simpler data structures if the set of parameters is deterministic, so re-running will always replace values, never omit them.)
The first form calls callIsolated() as before to get a data block that the getter can compute a value from. The assumption is that the computer will stash the value there, and if resolution happens, it will update the contents but not return a different value (this will have to be well documented).
The second form is used when there's no actual intermediate data. The computer sticks the value someplace that the getter knows about.
The third form passes in the location, which is seen and updated by the computer and read by the getter.
Of course, all of these are convenience functions. If the programmer knows to do this, they could simply have the isolated function return, say, a Holder<T> and use its value.
[imported from HPE issue 299]
[This may be out-of-date, but I'm going to import it anyway and look at it later.]
In the current Java API, the heavily-overloaded
isolated()
function can take several different forms of argument (Runnable
,Supplier<R>
,Consumer<T>
,Function<T,R>
, and probably a few others). In each, it essentially boils down toThis is fine when the function is a simple
Runnable
orConsumer
, but it runs into problems when it's something that wants to return a value. Logically, the value should be the one was computed by the function at the time of successful publication, butThis implies that it's not safe to use
isolated()
blocks that return values, and we should probably remove them. (Note that this only applies toisolated()
, which tries to publish. It doesn't apply toinReadOnlySnapshot()
,detached()
, orinSnapshot()
.) Rather, what should happen is that theisolated()
call should take aRunnable
orConsumer
, which should make modifications in such a way that something outside of the child context can compute the overall result. This could be done by calling methods on an argument passed in or by modifying objects bound to the closure. At the end, these external arguments would have consistent data, and the value could be computed.Note that this implies that when a task is re-run, when it makes calls on these objects, the new calls need to replace the old ones. (This would be a good use of the accumulators and task-dependent data structures, but could apply to simpler data structures if the set of parameters is deterministic, so re-running will always replace values, never omit them.)
To simplify things, I propose adding
The text was updated successfully, but these errors were encountered: