diff --git a/deps/message-port/message-port.h b/deps/message-port/message-port.h index c3f483f62d..6958ffaefe 100644 --- a/deps/message-port/message-port.h +++ b/deps/message-port/message-port.h @@ -95,11 +95,10 @@ class EXPORT_API Port { void OnMessage(const OnMessageCallback& callback); void Unref(); + Port(); ~Port(); private: - Port(); - Result PostMessageAsync(std::shared_ptr event); struct Internal; diff --git a/deps/node/src/lwnode/lwnode-public.cc b/deps/node/src/lwnode/lwnode-public.cc index aa7cbdc0f4..97ac7934f1 100644 --- a/deps/node/src/lwnode/lwnode-public.cc +++ b/deps/node/src/lwnode/lwnode-public.cc @@ -62,8 +62,8 @@ class Runtime::Internal { Internal() { LWNODE_DEV_LOG("[Runtime::Internal::Internal] new"); - // Ensure that builtin file is loaded before initializing node. - native_module::initializeLWNodeBuiltinFile(); + init_future_ = init_promise_.get_future(); + runner_.SetInitPromise(std::move(init_promise_)); } std::pair Init(int argc, char** argv) { @@ -149,6 +149,8 @@ class Runtime::Internal { Runtime::Configuration config_; std::atomic state_{State::kNotInitialized}; std::mutex stop_mutex_; + std::promise init_promise_; + std::future init_future_; }; /************************************************************************** @@ -168,7 +170,7 @@ Runtime::~Runtime() { LWNODE_DEV_LOG("[Runtime::~Runtime]"); } -int Runtime::Start(int argc, char** argv, std::promise&& promise) { +int Runtime::Start(int argc, char** argv) { LWNODE_PERF_LOG("[Runtime::Start]"); LWNODE_DEV_LOG("[Runtime] version: %s", LWNODE_VERSION_TAG); #if defined(NDEBUG) @@ -177,7 +179,6 @@ int Runtime::Start(int argc, char** argv, std::promise&& promise) { LWNODE_DEV_LOG("[Runtime] debug mode"); #endif - internal_->runner_.SetInitPromise(std::move(promise)); std::pair init_result = internal_->Init(argc, argv); if (init_result.first) { @@ -199,6 +200,14 @@ std::shared_ptr Runtime::GetPort() { return internal_->runner_.GetPort(); } +std::future_status Runtime::WaitForReady(int64_t ms) { + if (ms < 0) { + internal_->init_future_.wait(); + return std::future_status::ready; + } + return internal_->init_future_.wait_for(std::chrono::milliseconds(ms)); +} + /************************************************************************** * Runtime::Configuration class **************************************************************************/ diff --git a/deps/node/src/node_main_lw.cc b/deps/node/src/node_main_lw.cc index b132b547fe..a880d9f9a0 100644 --- a/deps/node/src/node_main_lw.cc +++ b/deps/node/src/node_main_lw.cc @@ -76,7 +76,6 @@ int main(int argc, char* argv[]) { // FIXME: Fix Runtime::Init() call to ensure environment initialization // before running the loop, Runtime::Run(). This workaround passes a // promise directly to know when that is. - std::promise promise; if (lwnode::ParseAULEvent(argc, argv)) { if (!lwnode::InitScriptRootPath()) { @@ -85,9 +84,9 @@ int main(int argc, char* argv[]) { char* args[] = { const_cast(""), const_cast("index.js"), nullptr}; - return runtime.Start(2, args, std::move(promise)); + return runtime.Start(2, args); } // started by command line - return runtime.Start(argc, argv, std::move(promise)); + return runtime.Start(argc, argv); } diff --git a/deps/node/src/node_main_lw_runner-inl.h b/deps/node/src/node_main_lw_runner-inl.h index cb06abb7a6..eb5c572c5a 100644 --- a/deps/node/src/node_main_lw_runner-inl.h +++ b/deps/node/src/node_main_lw_runner-inl.h @@ -239,7 +239,9 @@ class LWNodeMainRunner { } std::shared_ptr GetPort() { - CHECK_NOT_NULL(environment_); + if (!environment_) { + return std::make_shared(); + } return environment_->GetPort(); } diff --git a/examples/tizen/message-port/src/main.cc b/examples/tizen/message-port/src/main.cc index afb22410a3..4e55272a20 100644 --- a/examples/tizen/message-port/src/main.cc +++ b/examples/tizen/message-port/src/main.cc @@ -11,9 +11,6 @@ int main(int argc, char* argv[]) { dlog_print( DLOG_INFO, APP_LOG_TAG, "[Native] message-port example app started..."); - std::promise promise; - std::future init_future = promise.get_future(); - auto runtime = std::make_shared(); std::thread t([&]() { @@ -36,13 +33,13 @@ int main(int argc, char* argv[]) { const_cast(""), const_cast("index.js"), nullptr}; dlog_print(DLOG_INFO, APP_LOG_TAG, "[Native] runtime.Start() called..."); - runtime->Start(2, args, std::move(promise)); + runtime->Start(2, args); dlog_print(DLOG_INFO, APP_LOG_TAG, "[Native] end thread"); }); // Wait until the js script is initialized to get the port. - init_future.wait(); + runtime->WaitForReady(); std::shared_ptr port = runtime->GetPort(); diff --git a/include/lwnode/lwnode-public.h b/include/lwnode/lwnode-public.h index 2bbfc60261..82136ef51a 100644 --- a/include/lwnode/lwnode-public.h +++ b/include/lwnode/lwnode-public.h @@ -86,20 +86,36 @@ class LWNODE_EXPORT Runtime { * @param argc - Argument count. * @param argv - Argument vector. The element should be the starting file * name of the application. - * @param promise - Promise object. It will be set when the runtime - * initialization is complete. * @return Returns the exit code of the runtime. **/ - int Start(int argc, char** argv, std::promise&& promise); + int Start(int argc, char** argv); /** - * Stop the runtime. You can use this function to stop the runtime from another - * thread. + * Stop the runtime. You can use this function to stop the runtime from + * another thread. **/ void Stop(); + /** + * Get the message port instance. + * + * @return Returns the shared pointer of the message port instance. If the + * runtime is not ready, it returns the unavailable port instance. Otherwise, + * it returns the shared pointer of the available message port instance. + * + **/ std::shared_ptr GetPort(); + /** + * Wait until the runtime is ready. + * + * @param ms - Timeout in milliseconds. If it is negative, it waits + * indefinitely. + * @return Returns the status of the future object. If it is ready, the + * runtime is ready. + **/ + std::future_status WaitForReady(int64_t ms = -1); + private: class Internal; Internal* internal_ = nullptr; diff --git a/include/lwnode/lwnode-version.h b/include/lwnode/lwnode-version.h index da48b458c9..fc1c1b29dd 100644 --- a/include/lwnode/lwnode-version.h +++ b/include/lwnode/lwnode-version.h @@ -18,5 +18,5 @@ #define LWNODE_VERSION_MAJOR 1 #define LWNODE_VERSION_MINOR 0 - #define LWNODE_VERSION_PATCH 11 - #define LWNODE_VERSION_TAG "v1.0.11" + #define LWNODE_VERSION_PATCH 12 + #define LWNODE_VERSION_TAG "v1.0.12" diff --git a/include/lwnode/message-port.h b/include/lwnode/message-port.h index c3f483f62d..6958ffaefe 100644 --- a/include/lwnode/message-port.h +++ b/include/lwnode/message-port.h @@ -95,11 +95,10 @@ class EXPORT_API Port { void OnMessage(const OnMessageCallback& callback); void Unref(); + Port(); ~Port(); private: - Port(); - Result PostMessageAsync(std::shared_ptr event); struct Internal; diff --git a/test/embedding/embedtest.cc b/test/embedding/embedtest.cc index 98a04224eb..62ae08a6e3 100644 --- a/test/embedding/embedtest.cc +++ b/test/embedding/embedtest.cc @@ -32,8 +32,6 @@ std::string getTimestamp() { TEST0(Embedtest, MessagePort2_Post_Many_JS_First) { auto runtime = std::make_shared(); - std::promise promise; - std::future init_future = promise.get_future(); const char* script = "test/embedding/test-02-message-port-many.js"; std::string path = (std::filesystem::current_path() / script).string(); @@ -42,13 +40,10 @@ TEST0(Embedtest, MessagePort2_Post_Many_JS_First) { const_cast(path.c_str()), const_cast(std::to_string(post_first).c_str())}; - std::thread worker = std::thread( - [&](std::promise&& promise) mutable { - runtime->Start(COUNT_OF(args), args, std::move(promise)); - }, - std::move(promise)); + std::thread worker = + std::thread([&]() mutable { runtime->Start(COUNT_OF(args), args); }); - init_future.wait(); + runtime->WaitForReady(); int count1 = 0; @@ -83,22 +78,18 @@ TEST0(Embedtest, Restart) { for (int i = 0; i < 3; i++) { auto runtime = std::make_shared(); - std::promise promise; - std::future init_future = promise.get_future(); const char* script = "test/embedding/test-21-runtime-hello.js"; std::string path = (std::filesystem::current_path() / script).string(); char* args[] = {const_cast(""), const_cast(path.c_str())}; - std::thread worker = std::thread( - [&](std::promise&& promise) mutable { - std::cout << ++count << " Start " << std::endl; - runtime->Start(COUNT_OF(args), args, std::move(promise)); - std::cout << count << " /Start " << std::endl; - }, - std::move(promise)); + std::thread worker = std::thread([&]() mutable { + std::cout << ++count << " Start " << std::endl; + runtime->Start(COUNT_OF(args), args); + std::cout << count << " /Start " << std::endl; + }); - init_future.wait(); + runtime->WaitForReady(); worker.join(); std::this_thread::sleep_for(std::chrono::seconds(1)); } @@ -113,8 +104,6 @@ TEST0(Embedtest, RestartAfterStop) { for (int i = 0; i < 3; i++) { auto runtime = std::make_shared(); - std::promise promise; - std::future init_future = promise.get_future(); const char* script = "test/embedding/test-22-runtime-heartbeat.js"; std::string path = (std::filesystem::current_path() / script).string(); @@ -124,15 +113,13 @@ TEST0(Embedtest, RestartAfterStop) { const_cast(path.c_str())}; std::cout << ++count << "Thread " << std::endl; - std::thread worker = std::thread( - [&](std::promise&& promise) mutable { - std::cout << count << " Start " << std::endl; - runtime->Start(COUNT_OF(args), args, std::move(promise)); - std::cout << count << " /Start " << std::endl; - }, - std::move(promise)); + std::thread worker = std::thread([&]() mutable { + std::cout << count << " Start " << std::endl; + runtime->Start(COUNT_OF(args), args); + std::cout << count << " /Start " << std::endl; + }); - init_future.wait(); + runtime->WaitForReady(); std::this_thread::sleep_for(std::chrono::seconds(3)); runtime->Stop(); @@ -146,8 +133,6 @@ TEST0(Embedtest, RestartAfterStop) { TEST(Embedtest, MessagePortErrorAfterRegisterOnMessage, 5000) { auto runtime = std::make_shared(); - std::promise promise; - std::future init_future = promise.get_future(); const char* script = "test/embedding/test-04-message-port-error.js"; std::string path = (std::filesystem::current_path() / script).string(); @@ -156,13 +141,10 @@ TEST(Embedtest, MessagePortErrorAfterRegisterOnMessage, 5000) { const_cast(path.c_str()), const_cast(std::to_string(post_first).c_str())}; - std::thread worker = std::thread( - [&](std::promise&& promise) mutable { - runtime->Start(COUNT_OF(args), args, std::move(promise)); - }, - std::move(promise)); + std::thread worker = + std::thread([&]() mutable { runtime->Start(COUNT_OF(args), args); }); - init_future.wait(); + runtime->WaitForReady(); int count1 = 0; diff --git a/test/embedding/example.cc b/test/embedding/example.cc index 0b71ecd288..3474ad99c6 100644 --- a/test/embedding/example.cc +++ b/test/embedding/example.cc @@ -1,3 +1,4 @@ +#include #include #include #include @@ -18,26 +19,40 @@ int main(int argc, char* argv[]) { } auto runtime = std::make_shared(std::move(configuration)); - std::promise promise; - std::future init_future = promise.get_future(); const char* script = "test/embedding/test-01-message-port-basic.js"; std::string path = (std::filesystem::current_path() / script).string(); char* args[] = {const_cast(""), const_cast(path.c_str())}; - std::thread worker = std::thread( - [&](std::promise&& promise) mutable { - // FIXME: Fix Runtime::Init() call to ensure environment initialization - // before running the loop, Runtime::Run(). This workaround passes a - // promise directly to know when that is. - auto result = runtime->Start(COUNT_OF(args), args, std::move(promise)); - std::cout << "result: " << result << std::endl; - }, - std::move(promise)); + std::thread worker = std::thread([&]() mutable { + // FIXME: Fix Runtime::Init() call to ensure environment initialization + // before running the loop, Runtime::Run(). This workaround passes a + // promise directly to know when that is. + int result = 0; + do { + std::cout << "start runtime" << std::endl; + result = runtime->Start(COUNT_OF(args), args); + std::cout << "result: " << result << std::endl; - init_future.wait(); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + } while (result == 100); + }); + + while (true) { + std::future_status status = runtime->WaitForReady(50); + if (status == std::future_status::timeout) { + std::cout << "runtime is not ready: timeout" << std::endl; + } else if (status == std::future_status::deferred) { + std::cout << "runtime is not ready: deferred" << std::endl; + } else if (status == std::future_status::ready) { + std::cout << "runtime is ready" << std::endl; + break; + } + } int count1 = 0; auto port2 = runtime->GetPort(); + std::cout << "done get port" << std::endl; + port2->OnMessage([&](const MessageEvent* event) { std::cout << event->data() << std::endl; count1++; diff --git a/test/embedding/message-port-sync.cc b/test/embedding/message-port-sync.cc index e3152869ba..25b0cfbacb 100644 --- a/test/embedding/message-port-sync.cc +++ b/test/embedding/message-port-sync.cc @@ -33,19 +33,14 @@ std::string CallMethod(Port* port, const std::string& function) { int main(int argc, char* argv[]) { auto runtime = std::make_shared(); - std::promise promise; - std::future init_future = promise.get_future(); const char* script = "test/embedding/test-03-message-port-sync.js"; std::string path = (std::filesystem::current_path() / script).string(); char* args[] = {const_cast(""), const_cast(path.c_str())}; - std::thread worker = std::thread( - [&](std::promise&& promise) mutable { - runtime->Start(COUNT_OF(args), args, std::move(promise)); - }, - std::move(promise)); + std::thread worker = + std::thread([&]() mutable { runtime->Start(COUNT_OF(args), args); }); - init_future.wait(); + runtime->WaitForReady(); auto port2 = runtime->GetPort(); port2->OnMessage([&](const MessageEvent* event) { diff --git a/test/embedding/runtime-stop.cc b/test/embedding/runtime-stop.cc index e20b91e44b..03a799dc1c 100644 --- a/test/embedding/runtime-stop.cc +++ b/test/embedding/runtime-stop.cc @@ -15,22 +15,18 @@ constexpr size_t COUNT_OF(T (&)[N]) noexcept { int main(int argc, char* argv[]) { auto runtime = std::make_shared(); - std::promise promise; - std::future init_future = promise.get_future(); const char* script = "test/embedding/test-20-runtime-stop.js"; std::string path = (std::filesystem::current_path() / script).string(); char* args[] = {const_cast(""), const_cast(path.c_str())}; - std::thread worker = std::thread( - [&](std::promise&& promise) mutable { - // FIXME: Fix Runtime::Init() call to ensure environment initialization - // before running the loop, Runtime::Run(). This workaround passes a - // promise directly to know when that is. - runtime->Start(COUNT_OF(args), args, std::move(promise)); - }, - std::move(promise)); + std::thread worker = std::thread([&]() mutable { + // FIXME: Fix Runtime::Init() call to ensure environment initialization + // before running the loop, Runtime::Run(). This workaround passes a + // promise directly to know when that is. + runtime->Start(COUNT_OF(args), args); + }); - init_future.wait(); + runtime->WaitForReady(); std::cout << "[C]sleep app" << std::endl; std::this_thread::sleep_for(std::chrono::seconds(3)); diff --git a/test/embedding/send-message-sync.cc b/test/embedding/send-message-sync.cc index 1795cce7d6..05a57656f5 100644 --- a/test/embedding/send-message-sync.cc +++ b/test/embedding/send-message-sync.cc @@ -44,22 +44,19 @@ int main(int argc, char* argv[]) { auto runtime = std::make_shared(std::move(configuration)); - std::promise promise; - std::future init_future = promise.get_future(); const char* script = "test/embedding/test-10-send-message-sync-basic.js"; std::string path = (std::filesystem::current_path() / script).string(); char* args[] = {const_cast(""), const_cast(path.c_str())}; std::thread worker = std::thread( - [&](std::promise&& promise) mutable { + [&]() mutable { // FIXME: Fix Runtime::Init() call to ensure environment initialization // before running the loop, Runtime::Run(). This workaround passes a // promise directly to know when that is. - runtime->Start(COUNT_OF(args), args, std::move(promise)); - }, - std::move(promise)); + runtime->Start(COUNT_OF(args), args); + }); - init_future.wait(); + runtime->WaitForReady(); int count1 = 0; auto port2 = runtime->GetPort(); diff --git a/test/embedding/test-01-message-port-basic.js b/test/embedding/test-01-message-port-basic.js index dbcdf0f8b2..93c3b099a6 100644 --- a/test/embedding/test-01-message-port-basic.js +++ b/test/embedding/test-01-message-port-basic.js @@ -1,6 +1,8 @@ const lwnode = process.lwnode; const port = process.lwnode.port; +console.log("start"); + lwnode.ref(); port.onmessage = (event) => {