From 885a2e020e3c1f4db870b18cc21a36d3f287dd0d Mon Sep 17 00:00:00 2001 From: tclinken Date: Sun, 19 Apr 2020 18:20:39 -0700 Subject: [PATCH] Generate rvalue reference overloads with actor compiler --- fdbrpc/FlowTests.actor.cpp | 10 ++++ flow/actorcompiler/ActorCompiler.cs | 87 +++++++++++++++++++++++++++-- flow/flow.h | 3 + 3 files changed, 95 insertions(+), 5 deletions(-) diff --git a/fdbrpc/FlowTests.actor.cpp b/fdbrpc/FlowTests.actor.cpp index ade8946c35..18336cf9c5 100644 --- a/fdbrpc/FlowTests.actor.cpp +++ b/fdbrpc/FlowTests.actor.cpp @@ -1392,6 +1392,16 @@ struct Tracker { } }; +TEST_CASE("/flow/flow/PromiseStream/move2") { + PromiseStream stream; + stream.send(Tracker{}); + Tracker tracker = waitNext(stream.getFuture()); + Tracker movedTracker = std::move(tracker); + ASSERT(!movedTracker.moved); + ASSERT(movedTracker.copied == 0); + return Void(); +} + TEST_CASE("/flow/flow/PromiseStream/move") { state PromiseStream stream; { diff --git a/flow/actorcompiler/ActorCompiler.cs b/flow/actorcompiler/ActorCompiler.cs index 175ceb7b0a..06861a2044 100644 --- a/flow/actorcompiler/ActorCompiler.cs +++ b/flow/actorcompiler/ActorCompiler.cs @@ -86,31 +86,65 @@ namespace actorcompiler string indentation; StreamWriter body; public bool wasCalled { get; protected set; } + public Function overload = null; public Function() { body = new StreamWriter(new MemoryStream()); } + public void setOverload(Function overload) { + this.overload = overload; + } + + public Function popOverload() { + Function result = this.overload; + this.overload = null; + return result; + } + + public void addOverload(params string[] formalParameters) { + setOverload( + new Function { + name = name, + returnType = returnType, + endIsUnreachable = endIsUnreachable, + formalParameters = formalParameters + } + ); + } + public void Indent(int change) { for(int i=0; i", fullClassName, this.whenCount + i, ch.wait.result.type, ch.wait.isWaitNext ? "ActorSingleCallback" : "ActorCallback"), CallbackTypeInStateClass = string.Format("{3}< {0}, {1}, {2} >", className, this.whenCount + i, ch.wait.result.type, ch.wait.isWaitNext ? "ActorSingleCallback" : "ActorCallback") @@ -784,6 +819,7 @@ namespace actorcompiler var r = ch.Body; if (ch.Stmt.wait.resultIsState) { + Function overload = r.popOverload(); CompileStatement(new StateDeclarationStatement { FirstSourceLine = ch.Stmt.FirstSourceLine, @@ -794,6 +830,11 @@ namespace actorcompiler initializerConstructorSyntax = false } }, cx.WithTarget(r)); + if (overload != null) + { + overload.WriteLine("{0} = std::move(__{0});", ch.Stmt.wait.result.name); + r.setOverload(overload); + } } if (ch.Stmt.body != null) { @@ -804,8 +845,14 @@ namespace actorcompiler reachable = true; if (cx.next.formalParameters.Length == 1) r.WriteLine("loopDepth = {0};", cx.next.call("loopDepth")); - else + else { + Function overload = r.popOverload(); r.WriteLine("loopDepth = {0};", cx.next.call(ch.Stmt.wait.result.name, "loopDepth")); + if (overload != null) { + overload.WriteLine("loopDepth = {0};", cx.next.call(string.Format("std::move({0})", ch.Stmt.wait.result.name), "loopDepth")); + r.setOverload(overload); + } + } } var cbFunc = new Function { @@ -817,13 +864,22 @@ namespace actorcompiler }, endIsUnreachable = true }; + cbFunc.addOverload(ch.CallbackTypeInStateClass + "*", ch.Stmt.wait.result.type + " && value"); functions.Add(string.Format("{0}#{1}", cbFunc.name, ch.Index), cbFunc); cbFunc.Indent(codeIndent); ProbeEnter(cbFunc, actor.name, ch.Index); cbFunc.WriteLine("{0};", exitFunc.call()); + + Function _overload = cbFunc.popOverload(); TryCatch(cx.WithTarget(cbFunc), cx.catchFErr, cx.tryLoopDepth, () => { cbFunc.WriteLine("{0};", ch.Body.call("value", "0")); }, false); + if (_overload != null) { + TryCatch(cx.WithTarget(_overload), cx.catchFErr, cx.tryLoopDepth, () => { + _overload.WriteLine("{0};", ch.Body.call("std::move(value)", "0")); + }, false); + cbFunc.setOverload(_overload); + } ProbeExit(cbFunc, actor.name, ch.Index); var errFunc = new Function @@ -916,10 +972,14 @@ namespace actorcompiler }, FirstSourceLine = stmt.FirstSourceLine }; - if (!stmt.resultIsState) + if (!stmt.resultIsState) { cx.next.formalParameters = new string[] { string.Format("{0} const& {1}", stmt.result.type, stmt.result.name), loopDepth }; + cx.next.addOverload( + string.Format("{0} && {1}", stmt.result.type, stmt.result.name), + loopDepth); + } CompileStatement(equiv, cx); } void CompileStatement(CodeBlock stmt, Context cx) @@ -1116,6 +1176,14 @@ namespace actorcompiler { WriteFunction(writer, func, body); } + if (func.overload != null) + { + string overloadBody = func.overload.BodyText; + if (overloadBody.Length != 0) + { + WriteFunction(writer, func.overload, overloadBody); + } + } } } @@ -1133,7 +1201,7 @@ namespace actorcompiler writer.WriteLine(memberIndentStr + "}"); } - Function getFunction(string baseName, string addName, params string[] formalParameters) + Function getFunction(string baseName, string addName, string[] formalParameters, string[] overloadFormalParameters) { string proposedName; if (addName == "cont" && baseName.Length>=5 && baseName.Substring(baseName.Length - 5, 4) == "cont") @@ -1149,10 +1217,19 @@ namespace actorcompiler returnType = "int", formalParameters = formalParameters }; + if (overloadFormalParameters != null) { + f.addOverload(overloadFormalParameters); + } f.Indent(codeIndent); functions.Add(f.name, f); return f; } + + Function getFunction(string baseName, string addName, params string[] formalParameters) + { + return getFunction(baseName, addName, formalParameters, null); + } + string[] ParameterList() { return actor.parameters.Select(p => diff --git a/flow/flow.h b/flow/flow.h index 1823a0a6ee..270bb3d26b 100644 --- a/flow/flow.h +++ b/flow/flow.h @@ -1017,6 +1017,9 @@ struct ActorSingleCallback : SingleCallback { virtual void fire(ValueType const& value) { static_cast(this)->a_callback_fire(this, value); } + virtual void fire(ValueType && value) { + static_cast(this)->a_callback_fire(this, std::move(value)); + } virtual void error(Error e) { static_cast(this)->a_callback_error(this, e); }