Skip to content

Commit 4477e02

Browse files
committed
LLVMExecutableCode: Implement promises
1 parent e0143a6 commit 4477e02

File tree

2 files changed

+104
-0
lines changed

2 files changed

+104
-0
lines changed

src/dev/engine/internal/llvm/llvmexecutablecode.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <scratchcpp/value_functions.h>
55
#include <scratchcpp/stage.h>
66
#include <scratchcpp/iengine.h>
7+
#include <scratchcpp/dev/promise.h>
78
#include <llvm/Support/Error.h>
89
#include <iostream>
910

@@ -46,6 +47,15 @@ void LLVMExecutableCode::run(ExecutionContext *context)
4647
if (ctx->finished())
4748
return;
4849

50+
auto promise = ctx->promise();
51+
52+
if (promise) {
53+
if (promise->isResolved())
54+
ctx->setPromise(nullptr);
55+
else
56+
return;
57+
}
58+
4959
if (ctx->coroutineHandle()) {
5060
bool done = m_resumeFunction(ctx->coroutineHandle());
5161

@@ -69,13 +79,15 @@ void LLVMExecutableCode::kill(ExecutionContext *context)
6979
LLVMExecutionContext *ctx = getContext(context);
7080
ctx->setCoroutineHandle(nullptr);
7181
ctx->setFinished(true);
82+
ctx->setPromise(nullptr);
7283
}
7384

7485
void LLVMExecutableCode::reset(ExecutionContext *context)
7586
{
7687
LLVMExecutionContext *ctx = getContext(context);
7788
ctx->setCoroutineHandle(nullptr);
7889
ctx->setFinished(false);
90+
ctx->setPromise(nullptr);
7991
}
8092

8193
bool LLVMExecutableCode::isFinished(ExecutionContext *context) const

test/dev/llvm/llvmexecutablecode_test.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <scratchcpp/value_functions.h>
33
#include <scratchcpp/variable.h>
44
#include <scratchcpp/list.h>
5+
#include <scratchcpp/dev/promise.h>
56
#include <dev/engine/internal/llvm/llvmexecutablecode.h>
67
#include <dev/engine/internal/llvm/llvmexecutioncontext.h>
78
#include <llvm/Support/TargetSelect.h>
@@ -144,3 +145,94 @@ TEST_F(LLVMExecutableCodeTest, MainFunction)
144145
ASSERT_TRUE(code.isFinished(anotherCtx.get()));
145146
ASSERT_FALSE(code.isFinished(ctx.get()));
146147
}
148+
149+
TEST_F(LLVMExecutableCodeTest, Promise)
150+
{
151+
auto f = beginMainFunction();
152+
addTestFunction(f);
153+
endFunction(nullPointer());
154+
155+
beginResumeFunction();
156+
endFunction(m_builder->getInt1(true));
157+
158+
LLVMExecutableCode code(std::move(m_module));
159+
auto ctx = code.createExecutionContext(&m_target);
160+
ASSERT_FALSE(code.isFinished(ctx.get()));
161+
162+
// run()
163+
auto promise = std::make_shared<Promise>();
164+
ctx->setPromise(promise);
165+
EXPECT_CALL(m_mock, f).Times(0);
166+
167+
for (int i = 0; i < 10; i++) {
168+
code.run(ctx.get());
169+
ASSERT_FALSE(code.isFinished(ctx.get()));
170+
}
171+
172+
promise->resolve();
173+
174+
EXPECT_CALL(m_mock, f);
175+
code.run(ctx.get());
176+
ASSERT_TRUE(code.isFinished(ctx.get()));
177+
ASSERT_EQ(ctx->promise(), nullptr);
178+
code.reset(ctx.get());
179+
180+
// kill()
181+
promise = std::make_shared<Promise>();
182+
ctx->setPromise(promise);
183+
EXPECT_CALL(m_mock, f).Times(0);
184+
185+
for (int i = 0; i < 10; i++) {
186+
code.run(ctx.get());
187+
ASSERT_FALSE(code.isFinished(ctx.get()));
188+
}
189+
190+
code.kill(ctx.get());
191+
ASSERT_TRUE(code.isFinished(ctx.get()));
192+
ASSERT_EQ(ctx->promise(), nullptr);
193+
code.reset(ctx.get());
194+
195+
// reset()
196+
promise = std::make_shared<Promise>();
197+
ctx->setPromise(promise);
198+
EXPECT_CALL(m_mock, f).Times(0);
199+
200+
for (int i = 0; i < 10; i++) {
201+
code.run(ctx.get());
202+
ASSERT_FALSE(code.isFinished(ctx.get()));
203+
}
204+
205+
code.reset(ctx.get());
206+
ASSERT_FALSE(code.isFinished(ctx.get()));
207+
ASSERT_EQ(ctx->promise(), nullptr);
208+
209+
EXPECT_CALL(m_mock, f);
210+
code.run(ctx.get());
211+
ASSERT_TRUE(code.isFinished(ctx.get()));
212+
213+
// Test with another context
214+
Target anotherTarget;
215+
auto anotherCtx = code.createExecutionContext(&anotherTarget);
216+
ASSERT_FALSE(code.isFinished(anotherCtx.get()));
217+
ASSERT_TRUE(code.isFinished(ctx.get()));
218+
219+
promise = std::make_shared<Promise>();
220+
anotherCtx->setPromise(promise);
221+
EXPECT_CALL(m_mock, f).Times(0);
222+
223+
for (int i = 0; i < 10; i++) {
224+
code.run(anotherCtx.get());
225+
ASSERT_FALSE(code.isFinished(anotherCtx.get()));
226+
}
227+
228+
promise->resolve();
229+
230+
EXPECT_CALL(m_mock, f);
231+
code.run(anotherCtx.get());
232+
ASSERT_TRUE(code.isFinished(anotherCtx.get()));
233+
ASSERT_TRUE(code.isFinished(ctx.get()));
234+
235+
code.reset(ctx.get());
236+
ASSERT_TRUE(code.isFinished(anotherCtx.get()));
237+
ASSERT_FALSE(code.isFinished(ctx.get()));
238+
}

0 commit comments

Comments
 (0)