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

[Common] Move async class to common and support in executor. #2428

Merged
merged 4 commits into from
Jun 16, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions include/api/wasmedge/wasmedge.h
Original file line number Diff line number Diff line change
Expand Up @@ -1646,6 +1646,25 @@ WasmEdge_ExecutorInvoke(WasmEdge_ExecutorContext *Cxt,
const WasmEdge_Value *Params, const uint32_t ParamLen,
WasmEdge_Value *Returns, const uint32_t ReturnLen);

/// Asynchronous invoke a WASM function by the function instance.
///
/// After instantiating a WASM module, developers can get the function instance
/// context from the module instance. Then developers can invoke the function
/// asynchronously through this API.
///
/// \param Cxt the WasmEdge_ExecutorContext.
/// \param FuncCxt the function instance context to invoke.
/// \param Params the WasmEdge_Value buffer with the parameter values.
/// \param ParamLen the parameter buffer length.
///
/// \returns WasmEdge_Async. Call `WasmEdge_AsyncGet` for the result, and call
/// `WasmEdge_AsyncDelete` to destroy this object.
WASMEDGE_CAPI_EXPORT extern WasmEdge_Async *
WasmEdge_ExecutorAsyncInvoke(WasmEdge_ExecutorContext *Cxt,
const WasmEdge_FunctionInstanceContext *FuncCxt,
const WasmEdge_Value *Params,
const uint32_t ParamLen);

/// Deletion of the WasmEdge_ExecutorContext.
///
/// After calling this function, the context will be destroyed and should
Expand Down
26 changes: 12 additions & 14 deletions include/vm/async.h → include/common/async.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2019-2022 Second State INC

//===-- wasmedge/vm/async.h - Asynchronous Result class definition --------===//
//===-- wasmedge/common/async.h - Asynchronous execution class definition -===//
//
// Part of the WasmEdge Project.
//
Expand All @@ -13,27 +13,26 @@
//===----------------------------------------------------------------------===//
#pragma once

#include "vm.h"
#include "errcode.h"

#include <future>
#include <thread>

namespace WasmEdge {
namespace VM {

/// VM execution flow class
/// Async execution flow class
template <typename T> class Async {
public:
Async() noexcept = default;
template <typename... FArgsT, typename... ArgsT>
Async(T (VM::*FPtr)(FArgsT...), VM &TargetVM, ArgsT &&...Args)
: VMPtr(&TargetVM) {
template <typename Inst, typename... FArgsT, typename... ArgsT>
Async(T (Inst::*FPtr)(FArgsT...), Inst &TargetInst, ArgsT &&...Args)
: StopFunc([&TargetInst]() { TargetInst.stop(); }) {
std::promise<T> Promise;
Future = Promise.get_future();
Thread =
std::thread([FPtr, P = std::move(Promise),
Tuple = std::tuple(
&TargetVM, std::forward<ArgsT>(Args)...)]() mutable {
&TargetInst, std::forward<ArgsT>(Args)...)]() mutable {
P.set_value(std::apply(FPtr, Tuple));
});
Thread.detach();
Expand Down Expand Up @@ -66,20 +65,19 @@ template <typename T> class Async {
using std::swap;
swap(LHS.Future, RHS.Future);
swap(LHS.Thread, RHS.Thread);
swap(LHS.VMPtr, RHS.VMPtr);
swap(LHS.StopFunc, RHS.StopFunc);
}

void cancel() noexcept {
if (likely(VMPtr)) {
VMPtr->stop();
if (likely(StopFunc.operator bool())) {
StopFunc();
}
}

private:
protected:
std::shared_future<T> Future;
std::thread Thread;
VM *VMPtr;
std::function<void()> StopFunc;
};

} // namespace VM
} // namespace WasmEdge
8 changes: 7 additions & 1 deletion include/executor/executor.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#pragma once

#include "ast/module.h"
#include "common/async.h"
#include "common/configure.h"
#include "common/defines.h"
#include "common/errcode.h"
Expand Down Expand Up @@ -125,9 +126,14 @@ class Executor {

/// Invoke a WASM function by function instance.
Expect<std::vector<std::pair<ValVariant, ValType>>>
invoke(const Runtime::Instance::FunctionInstance &FuncInst,
invoke(const Runtime::Instance::FunctionInstance *FuncInst,
Span<const ValVariant> Params, Span<const ValType> ParamTypes);

/// Asynchronous invoke a WASM function by function instance.
Async<Expect<std::vector<std::pair<ValVariant, ValType>>>>
asyncInvoke(const Runtime::Instance::FunctionInstance *FuncInst,
Span<const ValVariant> Params, Span<const ValType> ParamTypes);

/// Stop execution
void stop() noexcept {
StopToken.store(1, std::memory_order_relaxed);
Expand Down
4 changes: 1 addition & 3 deletions include/vm/vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#pragma once

#include "common/async.h"
#include "common/configure.h"
#include "common/errcode.h"
#include "common/filesystem.h"
Expand All @@ -37,7 +38,6 @@
namespace WasmEdge {
namespace VM {

template <typename T> class Async;
/// VM execution flow class
class VM {
public:
Expand Down Expand Up @@ -312,5 +312,3 @@ class VM {

} // namespace VM
} // namespace WasmEdge

#include "async.h"
17 changes: 15 additions & 2 deletions lib/api/wasmedge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ struct WasmEdge_Async {
template <typename... Args>
WasmEdge_Async(Args &&...Vals) noexcept
: Async(std::forward<Args>(Vals)...) {}
WasmEdge::VM::Async<WasmEdge::Expect<
WasmEdge::Async<WasmEdge::Expect<
std::vector<std::pair<WasmEdge::ValVariant, WasmEdge::ValType>>>>
Async;
};
Expand Down Expand Up @@ -1632,13 +1632,26 @@ WasmEdge_ExecutorInvoke(WasmEdge_ExecutorContext *Cxt,
[&]()
-> WasmEdge::Expect<
std::vector<std::pair<WasmEdge::ValVariant, WasmEdge::ValType>>> {
return fromExecutorCxt(Cxt)->invoke(*fromFuncCxt(FuncCxt),
return fromExecutorCxt(Cxt)->invoke(fromFuncCxt(FuncCxt),
ParamPair.first, ParamPair.second);
},
[&](auto &&Res) { fillWasmEdge_ValueArr(*Res, Returns, ReturnLen); }, Cxt,
FuncCxt);
}

WASMEDGE_CAPI_EXPORT WasmEdge_Async *
WasmEdge_ExecutorAsyncInvoke(WasmEdge_ExecutorContext *Cxt,
const WasmEdge_FunctionInstanceContext *FuncCxt,
const WasmEdge_Value *Params,
const uint32_t ParamLen) {
if (Cxt && FuncCxt) {
auto ParamPair = genParamPair(Params, ParamLen);
return new WasmEdge_Async(fromExecutorCxt(Cxt)->asyncInvoke(
fromFuncCxt(FuncCxt), ParamPair.first, ParamPair.second));
}
return nullptr;
}

WASMEDGE_CAPI_EXPORT void
WasmEdge_ExecutorDelete(WasmEdge_ExecutorContext *Cxt) {
delete fromExecutorCxt(Cxt);
Expand Down
22 changes: 19 additions & 3 deletions lib/executor/executor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,16 @@ Executor::registerModule(Runtime::StoreManager &StoreMgr,

// Invoke function. See "include/executor/executor.h".
Expect<std::vector<std::pair<ValVariant, ValType>>>
Executor::invoke(const Runtime::Instance::FunctionInstance &FuncInst,
Executor::invoke(const Runtime::Instance::FunctionInstance *FuncInst,
Span<const ValVariant> Params,
Span<const ValType> ParamTypes) {
if (unlikely(FuncInst == nullptr)) {
spdlog::error(ErrCode::Value::FuncNotFound);
hydai marked this conversation as resolved.
Show resolved Hide resolved
return Unexpect(ErrCode::Value::FuncNotFound);
}

// Check parameter and function type.
const auto &FuncType = FuncInst.getFuncType();
const auto &FuncType = FuncInst->getFuncType();
const auto &PTypes = FuncType.getParamTypes();
const auto &RTypes = FuncType.getReturnTypes();
std::vector<ValType> GotParamTypes(ParamTypes.begin(), ParamTypes.end());
Expand All @@ -75,7 +80,7 @@ Executor::invoke(const Runtime::Instance::FunctionInstance &FuncInst,
Runtime::StackManager StackMgr;

// Call runFunction.
if (auto Res = runFunction(StackMgr, FuncInst, Params); !Res) {
if (auto Res = runFunction(StackMgr, *FuncInst, Params); !Res) {
return Unexpect(Res);
}

Expand All @@ -91,5 +96,16 @@ Executor::invoke(const Runtime::Instance::FunctionInstance &FuncInst,
return Returns;
}

Async<Expect<std::vector<std::pair<ValVariant, ValType>>>>
Executor::asyncInvoke(const Runtime::Instance::FunctionInstance *FuncInst,
Span<const ValVariant> Params,
Span<const ValType> ParamTypes) {
Expect<std::vector<std::pair<ValVariant, ValType>>> (Executor::*FPtr)(
const Runtime::Instance::FunctionInstance *, Span<const ValVariant>,
Span<const ValType>) = &Executor::invoke;
return {FPtr, *this, FuncInst, std::vector(Params.begin(), Params.end()),
std::vector(ParamTypes.begin(), ParamTypes.end())};
}

} // namespace Executor
} // namespace WasmEdge
8 changes: 1 addition & 7 deletions lib/vm/vm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// SPDX-FileCopyrightText: 2019-2022 Second State INC

#include "vm/vm.h"
#include "vm/async.h"

#include "host/wasi/wasimodule.h"
#include "plugin/plugin.h"
Expand Down Expand Up @@ -379,14 +378,9 @@ VM::unsafeExecute(const Runtime::Instance::ModuleInstance *ModInst,
// Find exported function by name.
Runtime::Instance::FunctionInstance *FuncInst =
ModInst->findFuncExports(Func);
if (unlikely(FuncInst == nullptr)) {
spdlog::error(ErrCode::Value::FuncNotFound);
spdlog::error(ErrInfo::InfoExecuting(ModInst->getModuleName(), Func));
return Unexpect(ErrCode::Value::FuncNotFound);
}

// Execute function.
if (auto Res = ExecutorEngine.invoke(*FuncInst, Params, ParamTypes);
if (auto Res = ExecutorEngine.invoke(FuncInst, Params, ParamTypes);
unlikely(!Res)) {
if (Res.error() != ErrCode::Value::Terminated) {
spdlog::error(ErrInfo::InfoExecuting(ModInst->getModuleName(), Func));
Expand Down
42 changes: 14 additions & 28 deletions test/aot/AOTcoreTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,26 +265,27 @@ INSTANTIATE_TEST_SUITE_P(TestUnit, NativeCoreTest,
INSTANTIATE_TEST_SUITE_P(TestUnit, CustomWasmCoreTest,
testing::ValuesIn(T.enumerate()));

std::array<WasmEdge::Byte, 46> AsyncWasm{
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60,
0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x07,
0x0a, 0x01, 0x06, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x00, 0x0a,
0x09, 0x01, 0x07, 0x00, 0x03, 0x40, 0x0c, 0x00, 0x0b, 0x0b};

TEST(AsyncRunWsmFile, NativeInterruptTest) {
WasmEdge::Configure Conf;
Conf.getCompilerConfigure().setInterruptible(true);
Conf.getCompilerConfigure().setOutputFormat(
CompilerConfigure::OutputFormat::Native);

WasmEdge::VM::VM VM(Conf);
std::array<WasmEdge::Byte, 46> Wasm{
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60,
0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x07,
0x0a, 0x01, 0x06, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x00, 0x0a,
0x09, 0x01, 0x07, 0x00, 0x03, 0x40, 0x0c, 0x00, 0x0b, 0x0b};
WasmEdge::Loader::Loader Loader(Conf);
WasmEdge::Validator::Validator ValidatorEngine(Conf);
WasmEdge::AOT::Compiler Compiler(Conf);
auto Path = std::filesystem::temp_directory_path() /
std::filesystem::u8path("AOTcoreTest" WASMEDGE_LIB_EXTENSION);
auto Module = *Loader.parseModule(Wasm);
auto Module = *Loader.parseModule(AsyncWasm);
ASSERT_TRUE(ValidatorEngine.validate(*Module));
ASSERT_TRUE(Compiler.compile(Wasm, *Module, Path));
ASSERT_TRUE(Compiler.compile(AsyncWasm, *Module, Path));
{
auto Timeout =
std::chrono::system_clock::now() + std::chrono::milliseconds(1);
Expand Down Expand Up @@ -315,19 +316,14 @@ TEST(AsyncExecute, NativeInterruptTest) {
CompilerConfigure::OutputFormat::Native);

WasmEdge::VM::VM VM(Conf);
std::array<WasmEdge::Byte, 46> Wasm{
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60,
0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x07,
0x0a, 0x01, 0x06, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x00, 0x0a,
0x09, 0x01, 0x07, 0x00, 0x03, 0x40, 0x0c, 0x00, 0x0b, 0x0b};
WasmEdge::Loader::Loader Loader(Conf);
WasmEdge::Validator::Validator ValidatorEngine(Conf);
WasmEdge::AOT::Compiler Compiler(Conf);
auto Path = std::filesystem::temp_directory_path() /
std::filesystem::u8path("AOTcoreTest" WASMEDGE_LIB_EXTENSION);
auto Module = *Loader.parseModule(Wasm);
auto Module = *Loader.parseModule(AsyncWasm);
ASSERT_TRUE(ValidatorEngine.validate(*Module));
ASSERT_TRUE(Compiler.compile(Wasm, *Module, Path));
ASSERT_TRUE(Compiler.compile(AsyncWasm, *Module, Path));
ASSERT_TRUE(VM.loadWasm(Path));
ASSERT_TRUE(VM.validate());
ASSERT_TRUE(VM.instantiate());
Expand Down Expand Up @@ -361,19 +357,14 @@ TEST(AsyncRunWsmFile, CustomWasmInterruptTest) {
CompilerConfigure::OutputFormat::Wasm);

WasmEdge::VM::VM VM(Conf);
std::array<WasmEdge::Byte, 46> Wasm{
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60,
0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x07,
0x0a, 0x01, 0x06, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x00, 0x0a,
0x09, 0x01, 0x07, 0x00, 0x03, 0x40, 0x0c, 0x00, 0x0b, 0x0b};
WasmEdge::Loader::Loader Loader(Conf);
WasmEdge::Validator::Validator ValidatorEngine(Conf);
WasmEdge::AOT::Compiler Compiler(Conf);
auto Path = std::filesystem::temp_directory_path() /
std::filesystem::u8path("AOTcoreTest.aot.wasm");
auto Module = *Loader.parseModule(Wasm);
auto Module = *Loader.parseModule(AsyncWasm);
ASSERT_TRUE(ValidatorEngine.validate(*Module));
ASSERT_TRUE(Compiler.compile(Wasm, *Module, Path));
ASSERT_TRUE(Compiler.compile(AsyncWasm, *Module, Path));
{
auto Timeout =
std::chrono::system_clock::now() + std::chrono::milliseconds(1);
Expand Down Expand Up @@ -404,19 +395,14 @@ TEST(AsyncExecute, CustomWasmInterruptTest) {
CompilerConfigure::OutputFormat::Wasm);

WasmEdge::VM::VM VM(Conf);
std::array<WasmEdge::Byte, 46> Wasm{
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60,
0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x07,
0x0a, 0x01, 0x06, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x00, 0x0a,
0x09, 0x01, 0x07, 0x00, 0x03, 0x40, 0x0c, 0x00, 0x0b, 0x0b};
WasmEdge::Loader::Loader Loader(Conf);
WasmEdge::Validator::Validator ValidatorEngine(Conf);
WasmEdge::AOT::Compiler Compiler(Conf);
auto Path = std::filesystem::temp_directory_path() /
std::filesystem::u8path("AOTcoreTest.aot.wasm");
auto Module = *Loader.parseModule(Wasm);
auto Module = *Loader.parseModule(AsyncWasm);
ASSERT_TRUE(ValidatorEngine.validate(*Module));
ASSERT_TRUE(Compiler.compile(Wasm, *Module, Path));
ASSERT_TRUE(Compiler.compile(AsyncWasm, *Module, Path));
ASSERT_TRUE(VM.loadWasm(Path));
ASSERT_TRUE(VM.validate());
ASSERT_TRUE(VM.instantiate());
Expand Down
Loading