将js方法改为异步thread调用

This commit is contained in:
cebgcontract 2022-07-20 16:43:02 +08:00
parent 5d771cc4a3
commit c221611d78
5 changed files with 118 additions and 77 deletions

View File

@ -1,5 +1,7 @@
#include "JcWallet.h" #include "JcWallet.h"
#include "WalletEvent.h" #include "WalletEvent.h"
#include <atomic>
#include <iostream>
#include "stdarg.h" #include "stdarg.h"
#include <string> #include <string>
#include "cocos/scripting/js-bindings/jswrapper/SeApi.h" #include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
@ -23,6 +25,67 @@ NS_CC_BEGIN
cocos2d::Application *g_app = nullptr; cocos2d::Application *g_app = nullptr;
JcWallet *JcWallet::_instance = nullptr; JcWallet *JcWallet::_instance = nullptr;
bool _isStarted = false; bool _isStarted = false;
uv_async_t gasync = {0};
struct AsyncTaskData {
std::mutex mtx;
std::list<std::function<void()> > 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<std::mutex> 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<void()> func) {
AsyncTaskData *data = (AsyncTaskData *) asyn->data;
{
std::lock_guard<std::mutex> 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) { bool runGlobalMethod(const char *name, se::ValueArray args, se::Value *value) {
se::AutoHandleScope scope; se::AutoHandleScope scope;
@ -35,8 +98,8 @@ NS_CC_BEGIN
return ok; return ok;
} }
bool addToArgArray(se::ValueArray *args, const char *valChar) { bool addToArgArray(se::ValueArray *args, std::string strVal) {
std::string strVal(valChar); // std::string strVal(valChar);
se::Value tmpVal; se::Value tmpVal;
bool ok = true; bool ok = true;
ok &= std_string_to_seval(strVal, &tmpVal); ok &= std_string_to_seval(strVal, &tmpVal);
@ -61,89 +124,60 @@ NS_CC_BEGIN
} }
} }
void JcWallet::initJSThread(std::shared_ptr<JcWallet> wallet) {
wallet->initEnv();
cocos2d::init_libuv_async_handle(&gasync);
}
JcWallet::~JcWallet() { JcWallet::~JcWallet() {
EventDispatcher::destroy(); EventDispatcher::destroy();
se::ScriptEngine::destroyInstance(); se::ScriptEngine::destroyInstance();
uv_loop_close(uv_default_loop());
JcWallet::_instance = nullptr; JcWallet::_instance = nullptr;
} }
char *JcWallet::initWallet(const char *passwordChar) { char *JcWallet::runJsMethod(std::shared_ptr<JSMethodParam> data) {
static std::string result;
se::ValueArray args; se::ValueArray args;
addToArgArray(&args, passwordChar); cocos2d::log("thread: %ld call method %s", uv_thread_self(), data->methodName.c_str());
se::Value value; for (int i = 0; i < data->paramList.size(); i++) {
bool ok = runGlobalMethod("initWallet", args, &value); addToArgArray(&args, data->paramList[i]);
if (ok && !value.isNullOrUndefined()) {
result = value.toString();
WalletEvent::Emit("wallet_inited", "{1}");
} else {
result = "";
} }
return const_cast<char *>(result.c_str());
}
char *JcWallet::signLogin(const char *nonceChar, const char *tipChar) {
se::ValueArray args;
addToArgArray(&args, nonceChar);
addToArgArray(&args, tipChar);
se::Value value; se::Value value;
bool ok = runGlobalMethod("loginSign", args, &value); bool ok = runGlobalMethod(data->methodName.c_str(), args, &value);
static std::string result; static std::string result;
if (ok && !value.isNullOrUndefined()) { if (ok && !value.isNullOrUndefined()) {
result = value.toString(); result = value.toString();
} else { } else {
result = ""; result = "";
} }
cocos2d::log("method: %s ::result: %s", data->methodName.c_str(), result.c_str());
WalletEvent::Emit("wallet_inited", result.c_str());
return const_cast<char *>(result.c_str()); return const_cast<char *>(result.c_str());
} }
char *JcWallet::createAccount() { extern "C" {
// return JcWallet::getInstance()->runJsMethod("createAccount", ""); void initEnv() {
} if (!_isStarted) {
std::shared_ptr<JcWallet> wallet(JcWallet::getInstance());
char *JcWallet::importAccount(const char *privateKey) { std::thread([=]() {
// return JcWallet::getInstance()->runJsMethod("importAccount", privateKey); JcWallet::initJSThread(wallet);
} }).detach();
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);
} }
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<char *>(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) { char *runWalletMethod(const char *methodName, int paramCount, char **paramList) {
JcWallet::getInstance()->initEnv(); JSMethodParam *data = new JSMethodParam();
return JcWallet::getInstance()->runJsMethod(methodName, paramCount, paramList); 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<JSMethodParam> params(data);
RUN_IN_SERVERTHREAD(JcWallet::getInstance()->runJsMethod(params));
return "1";
} }
} }

View File

@ -1,10 +1,21 @@
#include "uv.h"
#include "cocos2d.h" #include "cocos2d.h"
#include "stdarg.h" #include "stdarg.h"
#include "scripting/js-bindings/manual/jsb_conversions.hpp" #include "scripting/js-bindings/manual/jsb_conversions.hpp"
#include <thread>
#include <memory>
#include <mutex>
#include <list>
#include <atomic>
#include "base/ccMacros.h" #include "base/ccMacros.h"
NS_CC_BEGIN NS_CC_BEGIN
bool addToArgArray(se::ValueArray *args, const char *val); struct JSMethodParam {
std::string methodName;
int paramCount;
std::vector<std::string> paramList;
};
bool addToArgArray(se::ValueArray *args, std::string val);
bool runGlobalMethod(const char *name, se::ValueArray args, se::Value *value); bool runGlobalMethod(const char *name, se::ValueArray args, se::Value *value);
@ -18,15 +29,9 @@ NS_CC_BEGIN
static JcWallet *getInstance() { return _instance; } static JcWallet *getInstance() { return _instance; }
char *initWallet(const char *passwordChar); char *runJsMethod(std::shared_ptr<JSMethodParam> data);
char *signLogin(const char *nonceChar, const char *tipChar); static void initJSThread(std::shared_ptr<JcWallet> wallet);
char *createAccount();
char *importAccount(const char *privateKey);
char *runJsMethod(const char *methodName, int paramCount, char **paramList);
private: private:
static JcWallet *_instance; static JcWallet *_instance;

View File

@ -7,10 +7,10 @@
#include "WalletEvent.h" #include "WalletEvent.h"
// 定义函数指针用来接受C#的委托 // 定义函数指针用来接受C#的委托
void(*WalletEvent::Emit)(char* name, char* message); void(*WalletEvent::Emit)(const char* name, const char* message);
// 注册C#的委托 // 注册C#的委托
void registWalletEventDelegate(void(*Emit)(char* name, char* message)) void registWalletEventDelegate(void(*Emit)(const char* name, const char* message))
{ {
WalletEvent::Emit = Emit; WalletEvent::Emit = Emit;
} }

View File

@ -12,11 +12,11 @@ extern "C"
class WalletEvent class WalletEvent
{ {
public: public:
static void (*Emit)(char* name, char* message); static void (*Emit)(const char* name, const char* message);
}; };
// 注册C#的委托 // 注册C#的委托
void registWalletEventDelegate(void (*Emit)(char* name, char* message)); void registWalletEventDelegate(void (*Emit)(const char* name, const char* message));
} }

View File

@ -1,7 +1,9 @@
console.log('>>hi tiny wallet3') console.log('>>hi tiny wallet3')
function initWallet(password) { function initWallet(password) {
var wallet = new jcwallet.default(password); if (!jc.wallet) {
var wallet = new jcwallet.default(password);
}
return jc.wallet.currentAccount().address; return jc.wallet.currentAccount().address;
} }