From c221611d782d9140e0cd0927cfb81061ca7987d4 Mon Sep 17 00:00:00 2001 From: cebgcontract <99630598+cebgcontract@users.noreply.github.com> Date: Wed, 20 Jul 2022 16:43:02 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=86js=E6=96=B9=E6=B3=95=E6=94=B9=E4=B8=BA?= =?UTF-8?q?=E5=BC=82=E6=AD=A5thread=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes/JcWallet.cpp | 160 ++++++++++++++++++++++++---------------- Classes/JcWallet.h | 23 +++--- Classes/WalletEvent.cpp | 4 +- Classes/WalletEvent.h | 4 +- js/main.js | 4 +- 5 files changed, 118 insertions(+), 77 deletions(-) diff --git a/Classes/JcWallet.cpp b/Classes/JcWallet.cpp index bb30047..889f1a5 100644 --- a/Classes/JcWallet.cpp +++ b/Classes/JcWallet.cpp @@ -1,5 +1,7 @@ #include "JcWallet.h" #include "WalletEvent.h" +#include +#include #include "stdarg.h" #include #include "cocos/scripting/js-bindings/jswrapper/SeApi.h" @@ -23,6 +25,67 @@ NS_CC_BEGIN cocos2d::Application *g_app = nullptr; JcWallet *JcWallet::_instance = nullptr; bool _isStarted = false; + uv_async_t gasync = {0}; + + struct AsyncTaskData { + std::mutex mtx; + std::list > tasks; + }; + // const char *methodName, int paramCount, char **paramList + + + // run in server thread loop + void flush_tasks_in_server_loop_cb(uv_async_t *asyn) { + AsyncTaskData *data = (AsyncTaskData *) asyn->data; + std::lock_guard guard(data->mtx); + while (!data->tasks.empty()) { + // fetch task, run task + data->tasks.front()(); + // drop task + data->tasks.pop_front(); + } + + } + + void init_libuv_async_handle(uv_async_t *async) { + memset(async, 0, sizeof(uv_async_t)); + uv_loop_t *loop = uv_default_loop(); + uv_async_init(loop, async, cocos2d::flush_tasks_in_server_loop_cb); + async->data = new AsyncTaskData(); + uv_run(loop, UV_RUN_DEFAULT); + } + + // run in game thread, dispatch runnable object into server loop + void schedule_task_into_server_thread_task_queue(uv_async_t *asyn, std::function func) { + + AsyncTaskData *data = (AsyncTaskData *) asyn->data; + { + std::lock_guard guard(data->mtx); + data->tasks.emplace_back(func); + } + //notify server thread to invoke `flush_tasks_in_server_loop_cb()` + uv_async_send(asyn); + } + +// #define RUN_IN_GAMETHREAD(task) \ +// do { \ +// cocos2d::Application::getInstance()->getScheduler()->performFunctionInCocosThread([=]() { \ +// task; \ +// });\ +// } while(0) + +#define DISPATCH_CALLBACK_IN_GAMETHREAD() do {\ + data->setCallback([callback](const std::string& msg) { \ + cocos2d::log("call back"); \ + }); \ + }while(0) + +#define RUN_IN_SERVERTHREAD(task) do { \ + schedule_task_into_server_thread_task_queue(&gasync, [=](){ \ + task; \ + }); \ + } while(0) + bool runGlobalMethod(const char *name, se::ValueArray args, se::Value *value) { se::AutoHandleScope scope; @@ -35,8 +98,8 @@ NS_CC_BEGIN return ok; } - bool addToArgArray(se::ValueArray *args, const char *valChar) { - std::string strVal(valChar); + bool addToArgArray(se::ValueArray *args, std::string strVal) { +// std::string strVal(valChar); se::Value tmpVal; bool ok = true; ok &= std_string_to_seval(strVal, &tmpVal); @@ -61,89 +124,60 @@ NS_CC_BEGIN } } + void JcWallet::initJSThread(std::shared_ptr wallet) { + wallet->initEnv(); + cocos2d::init_libuv_async_handle(&gasync); + } + JcWallet::~JcWallet() { EventDispatcher::destroy(); se::ScriptEngine::destroyInstance(); + uv_loop_close(uv_default_loop()); JcWallet::_instance = nullptr; } - char *JcWallet::initWallet(const char *passwordChar) { - static std::string result; + char *JcWallet::runJsMethod(std::shared_ptr data) { se::ValueArray args; - addToArgArray(&args, passwordChar); - se::Value value; - bool ok = runGlobalMethod("initWallet", args, &value); - if (ok && !value.isNullOrUndefined()) { - result = value.toString(); - WalletEvent::Emit("wallet_inited", "{1}"); - } else { - result = ""; + cocos2d::log("thread: %ld call method %s", uv_thread_self(), data->methodName.c_str()); + for (int i = 0; i < data->paramList.size(); i++) { + addToArgArray(&args, data->paramList[i]); } - return const_cast(result.c_str()); - } - - char *JcWallet::signLogin(const char *nonceChar, const char *tipChar) { - se::ValueArray args; - addToArgArray(&args, nonceChar); - addToArgArray(&args, tipChar); - se::Value value; - bool ok = runGlobalMethod("loginSign", args, &value); + bool ok = runGlobalMethod(data->methodName.c_str(), args, &value); static std::string result; if (ok && !value.isNullOrUndefined()) { result = value.toString(); } else { result = ""; } + cocos2d::log("method: %s ::result: %s", data->methodName.c_str(), result.c_str()); + WalletEvent::Emit("wallet_inited", result.c_str()); return const_cast(result.c_str()); } - char *JcWallet::createAccount() { -// return JcWallet::getInstance()->runJsMethod("createAccount", ""); - } - - char *JcWallet::importAccount(const char *privateKey) { -// return JcWallet::getInstance()->runJsMethod("importAccount", privateKey); - } - - char *JcWallet::runJsMethod(const char *methodName, int paramCount, char **paramList) { - const char *arg; - se::ValueArray args; - cocos2d::log("call method %s", methodName); - for (int i = 0; i < paramCount; i++) { - arg = *(paramList + i); - cocos2d::log("call method param: %d, val: %s", i, arg); - addToArgArray(&args, arg); + extern "C" { + void initEnv() { + if (!_isStarted) { + std::shared_ptr wallet(JcWallet::getInstance()); + std::thread([=]() { + JcWallet::initJSThread(wallet); + }).detach(); } - se::Value value; - bool ok = runGlobalMethod(methodName, args, &value); - static std::string result; - if (ok && !value.isNullOrUndefined()) { - result = value.toString(); - } else { - result = ""; - } - return const_cast(result.c_str()); } - extern "C" - { - char *initWallet(const char *passwordChar) { - JcWallet::getInstance()->initEnv(); - return JcWallet::getInstance()->initWallet(passwordChar); - } - char *signLogin(const char *nonceChar, const char *tipChar) { - return JcWallet::getInstance()->signLogin(nonceChar, tipChar); - } - char *createAccount() { - return JcWallet::getInstance()->createAccount(); - } - char *importAccount(const char *privateKey) { - return JcWallet::getInstance()->importAccount(privateKey); - } char *runWalletMethod(const char *methodName, int paramCount, char **paramList) { - JcWallet::getInstance()->initEnv(); - return JcWallet::getInstance()->runJsMethod(methodName, paramCount, paramList); + JSMethodParam *data = new JSMethodParam(); + std::string methodNameStr(methodName); + data->methodName = methodNameStr; + data->paramCount = paramCount; + for (int i = 0; i < paramCount; i++) { + char *arg = *(paramList + i); + std::string strVal(arg); + data->paramList.push_back(strVal); + } + std::shared_ptr params(data); + RUN_IN_SERVERTHREAD(JcWallet::getInstance()->runJsMethod(params)); + return "1"; } } diff --git a/Classes/JcWallet.h b/Classes/JcWallet.h index be1cf4f..1c42832 100644 --- a/Classes/JcWallet.h +++ b/Classes/JcWallet.h @@ -1,10 +1,21 @@ +#include "uv.h" #include "cocos2d.h" #include "stdarg.h" #include "scripting/js-bindings/manual/jsb_conversions.hpp" +#include +#include +#include +#include +#include #include "base/ccMacros.h" NS_CC_BEGIN - bool addToArgArray(se::ValueArray *args, const char *val); + struct JSMethodParam { + std::string methodName; + int paramCount; + std::vector paramList; + }; + bool addToArgArray(se::ValueArray *args, std::string val); bool runGlobalMethod(const char *name, se::ValueArray args, se::Value *value); @@ -18,15 +29,9 @@ NS_CC_BEGIN static JcWallet *getInstance() { return _instance; } - char *initWallet(const char *passwordChar); + char *runJsMethod(std::shared_ptr data); - char *signLogin(const char *nonceChar, const char *tipChar); - - char *createAccount(); - - char *importAccount(const char *privateKey); - - char *runJsMethod(const char *methodName, int paramCount, char **paramList); + static void initJSThread(std::shared_ptr wallet); private: static JcWallet *_instance; diff --git a/Classes/WalletEvent.cpp b/Classes/WalletEvent.cpp index 659c591..d41bc23 100644 --- a/Classes/WalletEvent.cpp +++ b/Classes/WalletEvent.cpp @@ -7,10 +7,10 @@ #include "WalletEvent.h" // 定义函数指针,用来接受C#的委托 -void(*WalletEvent::Emit)(char* name, char* message); +void(*WalletEvent::Emit)(const char* name, const char* message); // 注册C#的委托 -void registWalletEventDelegate(void(*Emit)(char* name, char* message)) +void registWalletEventDelegate(void(*Emit)(const char* name, const char* message)) { WalletEvent::Emit = Emit; } \ No newline at end of file diff --git a/Classes/WalletEvent.h b/Classes/WalletEvent.h index f9087e6..eb3475c 100644 --- a/Classes/WalletEvent.h +++ b/Classes/WalletEvent.h @@ -12,11 +12,11 @@ extern "C" class WalletEvent { public: - static void (*Emit)(char* name, char* message); + static void (*Emit)(const char* name, const char* message); }; // 注册C#的委托 -void registWalletEventDelegate(void (*Emit)(char* name, char* message)); +void registWalletEventDelegate(void (*Emit)(const char* name, const char* message)); } diff --git a/js/main.js b/js/main.js index 335e741..fddb5bd 100644 --- a/js/main.js +++ b/js/main.js @@ -1,7 +1,9 @@ console.log('>>hi tiny wallet3') function initWallet(password) { - var wallet = new jcwallet.default(password); + if (!jc.wallet) { + var wallet = new jcwallet.default(password); + } return jc.wallet.currentAccount().address; }