Last active
November 4, 2024 13:07
-
-
Save ngot/4e363c08c1a912f3f10fda882a9e3956 to your computer and use it in GitHub Desktop.
V8 Thread Demo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <iostream> | |
| #include <chrono> | |
| #include <thread> | |
| #include <future> | |
| #include "libplatform/libplatform.h" | |
| #include "v8.h" | |
| v8::Local<v8::Context> CreateContext(v8::Isolate *isolate); | |
| void Start(const v8::FunctionCallbackInfo<v8::Value> &args); | |
| void Sleep(const v8::FunctionCallbackInfo<v8::Value> &args); | |
| int main(int argc, char *argv[]) | |
| { | |
| // Initialize V8. | |
| v8::V8::InitializeICUDefaultLocation(argv[0]); | |
| v8::V8::InitializeExternalStartupData(argv[0]); | |
| v8::Platform *platform = v8::platform::CreateDefaultPlatform(); | |
| v8::V8::InitializePlatform(platform); | |
| v8::V8::Initialize(); | |
| // Create a new Isolate and make it the current one. | |
| v8::Isolate::CreateParams create_params; | |
| create_params.array_buffer_allocator = | |
| v8::ArrayBuffer::Allocator::NewDefaultAllocator(); | |
| v8::Isolate *isolate = v8::Isolate::New(create_params); | |
| { | |
| v8::Isolate::Scope isolate_scope(isolate); | |
| // Create a stack-allocated handle scope. | |
| v8::HandleScope handle_scope(isolate); | |
| // Create a new context. | |
| v8::Local<v8::Context> context = CreateContext(isolate); | |
| // Enter the context for compiling and running the hello world script. | |
| v8::Context::Scope context_scope(context); | |
| // Create a string containing the JavaScript source code. | |
| v8::Local<v8::String> source = | |
| v8::String::NewFromUtf8(isolate, "start(()=>{console.log(123)});", | |
| v8::NewStringType::kNormal) | |
| .ToLocalChecked(); | |
| // Compile the source code. | |
| v8::Local<v8::Script> script = | |
| v8::Script::Compile(context, source).ToLocalChecked(); | |
| // Run the script to get the result. | |
| v8::Local<v8::Value> result = script->Run(context).ToLocalChecked(); | |
| // Convert the result to an UTF8 string and print it. | |
| v8::String::Utf8Value utf8(isolate, result); | |
| printf("%s\n", *utf8); | |
| } | |
| // Dispose the isolate and tear down V8. | |
| isolate->Dispose(); | |
| v8::V8::Dispose(); | |
| v8::V8::ShutdownPlatform(); | |
| delete platform; | |
| delete create_params.array_buffer_allocator; | |
| return 0; | |
| } | |
| v8::Local<v8::Context> CreateContext(v8::Isolate *isolate) | |
| { | |
| // Create a template for the global object. | |
| v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate); | |
| // Bind the global 'start' function to the C++ Print callback. | |
| global->Set( | |
| v8::String::NewFromUtf8(isolate, "start", v8::NewStringType::kNormal) | |
| .ToLocalChecked(), | |
| v8::FunctionTemplate::New(isolate, Start)); | |
| // Bind the global 'sleep' function to the C++ Print callback. | |
| global->Set( | |
| v8::String::NewFromUtf8(isolate, "sleep", v8::NewStringType::kNormal) | |
| .ToLocalChecked(), | |
| v8::FunctionTemplate::New(isolate, Sleep)); | |
| return v8::Context::New(isolate, NULL, global); | |
| } | |
| void Sleep(const v8::FunctionCallbackInfo<v8::Value> &args) | |
| { | |
| std::cout << "sleep start" << std::endl; | |
| v8::Isolate *isolate = args.GetIsolate(); | |
| if (v8::Locker::IsLocked(isolate)) | |
| v8::Unlocker unlocker(isolate); | |
| int time = args[0]->Int32Value(isolate->GetCurrentContext()).FromMaybe(0); | |
| std::this_thread::sleep_for(std::chrono::seconds(time)); | |
| std::cout << "sleep end" << std::endl; | |
| } | |
| void do_work(void *p, std::promise<void> barrier) | |
| { | |
| v8::Isolate *isolate = (v8::Isolate *)p; | |
| // v8::Locker locker(isolate); // crash | |
| std::cout << "do_work start" << std::endl; | |
| std::this_thread::sleep_for(std::chrono::seconds(2)); | |
| barrier.set_value(); | |
| std::cout << "do_work end" << std::endl; | |
| } | |
| void Start(const v8::FunctionCallbackInfo<v8::Value> &args) | |
| { | |
| std::cout << "Start start" << std::endl; | |
| v8::Local<v8::Function> fn = v8::Local<v8::Function>::Cast(args[0]); | |
| v8::Isolate *isolate = args.GetIsolate(); | |
| std::promise<void> new_promise; | |
| std::future<void> new_future = new_promise.get_future(); | |
| std::thread new_thread(do_work, isolate, std::move(new_promise)); | |
| new_future.wait(); | |
| new_future.get(); | |
| new_thread.join(); | |
| std::cout << "Start end" << std::endl; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks @ErickWendel!