blob: b8a1163943c8ce76c2b9b60b80c3656fdf6868be [file] [log] [blame] [edit]
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include <chrono>
#include <future>
#include <iostream>
#include <thread>
#include "helpers.h"
#include "include/dart_api.h"
#include "include/dart_engine.h"
void ScheduleDartMessage(Dart_Isolate isolate, void* context) {
std::ignore = std::async(DartEngine_HandleMessage, isolate);
}
void FulfillIntPromise(void* context, int64_t value) {
auto promise = reinterpret_cast<std::promise<int64_t>*>(context);
promise->set_value(value);
delete promise;
}
// Helper to call Dart function `returnRegularFutureC`.
std::future<int64_t> ReturnRegularFuture(Dart_Isolate isolate,
int64_t delay_ms,
bool use_microtask) {
auto promise = new std::promise<int64_t>();
auto result = promise->get_future();
IsolateScope isolate_scope(isolate);
DartScope dart_scope;
// args
Dart_Handle args[] = {
Dart_NewInteger(delay_ms), Dart_NewBoolean(use_microtask),
Dart_NewInteger(
reinterpret_cast<intptr_t>(&FulfillIntPromise)), // callback
Dart_NewInteger(reinterpret_cast<intptr_t>(promise)) // context
};
// call
CheckError(Dart_Invoke(Dart_RootLibrary(),
Dart_NewStringFromCString("returnRegularFutureC"), 4,
args));
CheckError(DartEngine_DrainMicrotasksQueue(), "draining microtasks queue");
return result;
}
// Helper to call Dart function `sumIntStreamC`.
std::future<int64_t> SumIntStream(Dart_Isolate isolate,
int count,
int64_t delay_ms,
bool use_async_star) {
auto promise = new std::promise<int64_t>();
auto result = promise->get_future();
IsolateScope isolate_scope(isolate);
DartScope dart_scope;
// args
Dart_Handle args[] = {
Dart_NewInteger(count), Dart_NewInteger(delay_ms),
Dart_NewBoolean(use_async_star),
Dart_NewInteger(
reinterpret_cast<intptr_t>(&FulfillIntPromise)), // callback
Dart_NewInteger(reinterpret_cast<intptr_t>(promise)) // context
};
// call
CheckError(Dart_Invoke(Dart_RootLibrary(),
Dart_NewStringFromCString("sumIntStreamC"), 5, args));
CheckError(DartEngine_DrainMicrotasksQueue(), "draining microtasks queue");
return result;
}
class AwaitAndMultiplyCall {
public:
AwaitAndMultiplyCall(Dart_Isolate isolate,
Dart_PersistentHandle handle,
std::future<int64_t>&& result)
: result(std::move(result)), isolate_(isolate), handle_(handle) {}
void CompleteA(int64_t value) {
IsolateScope isolate_scope(isolate_);
DartScope dart_scope;
Dart_Handle args[] = {Dart_NewInteger(value)};
CheckError(
Dart_Invoke(handle_, Dart_NewStringFromCString("setA"), 1, args));
CheckError(DartEngine_DrainMicrotasksQueue(), "draining microtasks queue");
}
void CompleteB(int64_t value) {
IsolateScope isolate_scope(isolate_);
DartScope dart_scope;
Dart_Handle args[] = {Dart_NewInteger(value)};
CheckError(
Dart_Invoke(handle_, Dart_NewStringFromCString("setB"), 1, args));
CheckError(DartEngine_DrainMicrotasksQueue(), "draining microtasks queue");
}
std::future<int64_t> result;
void Release() {
IsolateScope isolate_scope(isolate_);
DartScope dart_scope;
Dart_DeletePersistentHandle(handle_);
}
private:
Dart_Isolate isolate_;
Dart_PersistentHandle handle_;
};
AwaitAndMultiplyCall AwaitAndMultiply(Dart_Isolate isolate) {
auto promise = new std::promise<int64_t>();
auto future = promise->get_future();
IsolateScope isolate_scope(isolate);
DartScope dart_scope;
Dart_Handle args[] = {
Dart_NewInteger(reinterpret_cast<intptr_t>(&FulfillIntPromise)),
Dart_NewInteger(reinterpret_cast<intptr_t>(promise)),
};
Dart_PersistentHandle call_handle = Dart_NewPersistentHandle(CheckError(
Dart_Invoke(Dart_RootLibrary(),
Dart_NewStringFromCString("awaitAndMultiplyC"), 2, args)));
CheckError(DartEngine_DrainMicrotasksQueue(), "draining microtasks queue");
return AwaitAndMultiplyCall(isolate, call_handle, std::move(future));
}
int main(int argc, char** argv) {
if (argc == 1) {
std::cerr << "Must specify snapshot path" << std::endl;
std::exit(1);
}
char* error = nullptr;
//
// Set up message handling and start isolate.
//
DartEngine_MessageScheduler scheduler{ScheduleDartMessage, nullptr};
DartEngine_SetDefaultMessageScheduler(scheduler);
DartEngine_SnapshotData snapshot_data = AutoSnapshotFromFile(argv[1], &error);
CheckError(error, "reading snapshot");
Dart_Isolate isolate = DartEngine_CreateIsolate(snapshot_data, &error);
CheckError(error, "creating isolate");
//
// Call Dart functions.
//
auto result1 = ReturnRegularFuture(isolate, 5, false).get();
std::cout << "returnRegularFutureC(useMicrotask = false) returns: " << result1
<< std::endl;
auto result2 = ReturnRegularFuture(isolate, 5, true).get();
std::cout << "returnRegularFutureC(useMicrotask = true) returns: " << result2
<< std::endl;
auto result3 = SumIntStream(isolate, 5, 5, false).get();
std::cout << "sumIntStream(useAsyncStar = false) returns: " << result3
<< std::endl;
auto result4 = SumIntStream(isolate, 5, 5, true).get();
std::cout << "sumIntStream(useAsyncStar = true) returns: " << result4
<< std::endl;
auto call = AwaitAndMultiply(isolate);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
call.CompleteB(5);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
call.CompleteA(20);
auto result5 = call.result.get();
std::cout << "awaitAndMultiply(5, 20) = " << result5 << std::endl;
call.Release();
//
// Shutdown
//
DartEngine_Shutdown();
}