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

Added Breaking/Erroring of Promises #118

Merged
merged 20 commits into from
Mar 15, 2017
Merged

Added Breaking/Erroring of Promises #118

merged 20 commits into from
Mar 15, 2017

Conversation

salenaer
Copy link
Contributor

@salenaer salenaer commented Mar 13, 2017

I've added ruining of promises, currently, an error occurs in the tests, but not during regular use. Neither Carmen nor I find the reason of the error.
Can you have a look at the code and see if we missed something?

Design: Ruining Promise in Absence of Handlers

A message is sent from A to B. The evaluation of this message in B results in an error. As such the promise (the result of this message send in A) needs to be ruined. To ruin a promise means setting the state to erroneous and running all error handlers connected to this promise. This exposes the occurrence of the error to A.

First, the handlers bound to this promise are started. If no such handlers exist the chained promises (promises resolved with the current ruined promise) are ruined. If none of the chained promises handled the exception, this exception is uncaught. Normally the user should be informed when an uncaught exception occurs. However, in our case, this is impossible, because of scheduling it is possible that the promise is ruined before the handlers are added. This is a race condition, this race condition should not be exposed to the user.

Pseudocode example of race condition as a result of scheduling, time runs downwards

A 						B
promise := B <-: message

						process(message)


promise whenResolved: [something] onError: [ handlers]

To change this behaviour make ruinChainedPromise return a handled boolean. Based on this boolean perform desired behaviour inside onError method of SPromise.

@smarr smarr changed the title Runing Added Ruining of Promises Mar 13, 2017
@smarr smarr self-assigned this Mar 13, 2017
@smarr smarr added this to the v0.3.0 milestone Mar 13, 2017
@smarr smarr added bug Fixes an issue, incorrect implementation enhancement Improves the implementation with something noteworthy labels Mar 13, 2017
Copy link
Owner

@smarr smarr left a comment

Choose a reason for hiding this comment

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

Thanks a lot for the pull request. This is a good start. However, I would have much preferred if we could have discussed some of the details like naming upfront.

The 'ruin' terminology does not fit into SOMns, it is likely AmbientTalk specific. Please either use 'break' as in Newspeak, or 'error' as it is already named in SOMns. Changing terminology is a major change that I am not happy to accept without proper discussion.

The other concerns I have are with commented tests, and what looks like duplication of rather complicated code.

Please let me know whether you would be happy to do those changes, or whether you would prefer me to take it from here.

public resolve: value = ( vmMirror actorsResolve: self with: value isBPResolution: false)
public error: value = ( self notYetImplemented )
public resolve: value = (vmMirror actorsResolve: self with: value isBPResolution: false)
public error: value = (vmMirror actorsRuin: self with: value)
Copy link
Owner

Choose a reason for hiding this comment

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

I am not happy with the terminology. ruin is neither SOMns nor Newspeak terminology.
SOMns uses error:, Newspeak uses whenBroken:. I would be willing to consider Newspeak terminology, but not ruin.

@@ -98,6 +98,11 @@ class Actors usingVmMirror: vmMirror usingKernel: kernel = Value (
public resolve: value = (
resolver resolve: value.
)

(*added*)
public ruin: exception = (
Copy link
Owner

Choose a reason for hiding this comment

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

Same here, ruin: is a no go. And anywhere in the code below.

)
)

(*
Copy link
Owner

Choose a reason for hiding this comment

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

Why is this test commented out?

) *)

(*
public testAsyncPromiseOfPromiseResolvesToException = (
Copy link
Owner

Choose a reason for hiding this comment

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

Same here, why adding commented out code?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Most of the tests are commented out as they do work when ran on their own. When I run multiple at the same time I get some error I can't seem to solve.

Copy link
Owner

Choose a reason for hiding this comment

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

Ok, so, just to clarify, do you want me to change the things I currently marked as issues and also try to solve the remaining bugs? I could do that. But I don't want to just take it out of your hands, since you probably spend already a lot of sweat on the PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You can take over, I really need to focus on things I need for my thesis

pp resolver error: exception.

^ assertPromise
) *)
Copy link
Owner

Choose a reason for hiding this comment

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

Is there any test that's actually not commented out?

public final void onError() {
throw new NotYetImplementedException(); // TODO: implement
public static void onError(final SAbstractObject exception, final Object wrapped, final SPromise p, final Actor current) {
//System.out.println("called on error");
Copy link
Owner

Choose a reason for hiding this comment

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

Please don't commit commented debugging code.

//execute all exceptionHandlers if the type of wrapped is equal to the exceptionClass the handler handles.
if (p.onException != null) {
for (int i = 0; i < p.onException.size(); i++) {
SClass exceptionClass = p.onException.get(i);
Copy link
Owner

Choose a reason for hiding this comment

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

I was under the impression that we figured out that the onException stuff can't be supported because it implies visible race conditions. Or is this not the case after all?
I guess it depends on how this is realized. But from the sequential world, filtering would be the way to go, which is a race. So, it can't be done, I think.

I'd rather remove the on: exception support.

return handled;
}

protected static void ruinChainedPromisesUnsynch(final SAbstractObject exception, final SPromise promise, final Actor current){
Copy link
Owner

Choose a reason for hiding this comment

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

Would it be possible to use the existing code here instead, and pass as an argument whether the resolution is successful or erroneous? This seems to be a duplication of rather intricate code, which I'd really like to avoid.

@@ -182,6 +182,26 @@ public final SPromise whenResolvedOnError(final SPromise promise,
return whenResolvedOrError(promise, resolved, error, resolvedTarget,
errorTarget, registerNode);
}

Copy link
Owner

Choose a reason for hiding this comment

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

Please don't included dead code

@@ -0,0 +1,45 @@
class Behaviour usingPlatform: platform = Value (
Copy link
Owner

Choose a reason for hiding this comment

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

Are the following files really to be committed here? seems like something you'd like in a separate repo.
Considering that the folder is named thesis?

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 want them in my local fork and thought you could refuse them when merging with the main.

Copy link
Owner

Choose a reason for hiding this comment

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

Ok, you might want to put them in a separate repo to avoid issues, since you seem to have sent the PR from master, I am worried that if i delete them, you might just miss them.

@smarr
Copy link
Owner

smarr commented Mar 14, 2017

Ok, thanks, then I'll take it over. And thanks for taking care of the checkstyle issues, I really appreciate it. I know it is tedious but helps to maintain a more uniform code style.

I'll push a rebase on master and then try to figure out what's going on with the tests.

@smarr smarr force-pushed the master branch 2 times, most recently from 1c81786 to 02f8414 Compare March 14, 2017 20:00
@smarr
Copy link
Owner

smarr commented Mar 14, 2017

@salenaer thanks again for the pull request.
And apologies for many of the issues that you saw. Some of that is because of broken stuff in the test framework. For instance: 79e293c

As you may see from the updated PR, I tried to avoid much of the code duplication of the previous version by reusing all of the normal resolution code. Instead of duplicating it, it now got a parameter that defines success or failure. Beside that, I only replicated a few optimizations that were in place before.

After a few minor fixes to the tests, they pass.

Would be great, if you could review the PR and check whether I missed anything.

Thanks!

@smarr
Copy link
Owner

smarr commented Mar 14, 2017

And yeah, that's just another example for: everything that's not tested is broken. Sorry...


public WhenResolvedOnErrorPrim(final boolean eagWrap, final SourceSection source) { super(eagWrap, source); }

@Specialization(guards = {"resolvedMethod == resolved.getMethod()", "errorMethod == error.getMethod()"})
@Specialization(guards = {"resolvedMethod == resolved.getMethod()", "errorMethod == error.getMethod()"}, limit = "1000")
Copy link
Owner

Choose a reason for hiding this comment

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

Todo for myself: remove limit, and replace by proper fallback case

@smarr smarr force-pushed the master branch 2 times, most recently from dd81f26 to 049256f Compare March 15, 2017 11:17
salenaer and others added 14 commits March 15, 2017 17:25
2 unresolved issues:
-actors.som (seems to be redundent)
-what to do with an exception that is not caught.
- adding tests for ruining
- fixed explicit ruining
- found problem with chaining and ruining

RM tiny

Signed-off-by: Stefan Marr <git@stefan-marr.de>
- added tests for ruining
- made ruining ruin all chained if not handled
- made ruining ruin chained of own chained if not handled
- currently bug causing two test to crash if run consequently
- added four more test
- finished nested ruining, tests still fail

RM behavior

Signed-off-by: Stefan Marr <git@stefan-marr.de>
- checkstyle errors
- codacy errors
- execution stats are kept in TracingActivityThread
- chainedPromise seems to need frame for now
- avoid using ‘ruin’, prefer ‘error’ or ‘break’ (work in progress)
- trace broken promise like resolved ones

Signed-off-by: Stefan Marr <git@stefan-marr.de>
The #on:do: method cannot be properly supported for promises, because registering handlers with filtering semantics is a racy operation.
Depending on the order of events, a handler might or might not trigger because a filter might have been inplace. And, we don’t want to expose such races.

Signed-off-by: Stefan Marr <git@stefan-marr.de>
Signed-off-by: Stefan Marr <git@stefan-marr.de>
- revise them, still were using old naming
- adapt assert in Minitest, too

Signed-off-by: Stefan Marr <git@stefan-marr.de>
Signed-off-by: Stefan Marr <git@stefan-marr.de>
Signed-off-by: Stefan Marr <git@stefan-marr.de>
Signed-off-by: Stefan Marr <git@stefan-marr.de>
- fix up terminology to avoid ruin
- fix some simple issues
- fix code style

Signed-off-by: Stefan Marr <git@stefan-marr.de>
Signed-off-by: Stefan Marr <git@stefan-marr.de>
Signed-off-by: Stefan Marr <git@stefan-marr.de>
- avoid code duplication, reusued normal resolution, and use Resolution as argument to distinguish
- introduce common AbstractPromiseResolutionNode to reuse code between successful and erroneous resolution
- use RegisterOnError node to optimize callback registration, same as RegisterWhenResolved
- check resolution type when resolving callbacks
- propagate breakpoint info
- use same implementation strategy for OnErrorPrim as for normal WhenResolvedPrim
- add promise error parsing to trace parsing

Signed-off-by: Stefan Marr <git@stefan-marr.de>
Signed-off-by: Stefan Marr <git@stefan-marr.de>
Signed-off-by: Stefan Marr <git@stefan-marr.de>
Signed-off-by: Stefan Marr <git@stefan-marr.de>
@smarr smarr changed the title Added Ruining of Promises Added Breaking/Erroring of Promises Mar 15, 2017
Signed-off-by: Stefan Marr <git@stefan-marr.de>
@smarr smarr merged commit 9c9888f into smarr:master Mar 15, 2017
@smarr
Copy link
Owner

smarr commented Mar 15, 2017

@salenaer the PR is merged and on master now. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Fixes an issue, incorrect implementation enhancement Improves the implementation with something noteworthy
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants