From 7c78c22dab30426930dd7c213d10324c49a8036f Mon Sep 17 00:00:00 2001 From: cebgcontract <99630598+cebgcontract@users.noreply.github.com> Date: Thu, 24 Nov 2022 12:52:19 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8C=E6=AD=A5android=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes_cocos/JcWallet.h | 4 +++ Classes_cocos/JcWallet.mm | 54 +++++++++++++++++++++++++++++++++------ 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/Classes_cocos/JcWallet.h b/Classes_cocos/JcWallet.h index f0d8fbd..629cecc 100644 --- a/Classes_cocos/JcWallet.h +++ b/Classes_cocos/JcWallet.h @@ -37,6 +37,10 @@ NS_CC_BEGIN void performFunctionInCocosThread( const std::function &function); + void tickRun(); + + void jsToUnity(std::string funId, std::string msg); + private: static JcWallet *_instance; std::vector> _functionsToPerform; diff --git a/Classes_cocos/JcWallet.mm b/Classes_cocos/JcWallet.mm index 7b0b248..7d55c44 100644 --- a/Classes_cocos/JcWallet.mm +++ b/Classes_cocos/JcWallet.mm @@ -28,10 +28,10 @@ NS_CC_BEGIN cocos2d::Application *g_app = nullptr; JcWallet *JcWallet::_instance = nullptr; + uv_loop_t *loop = nullptr; bool _isStarted = false; uv_async_t gasync = {0}; - struct AsyncTaskData { std::mutex mtx; std::list > tasks; @@ -52,7 +52,9 @@ NS_CC_BEGIN void init_libuv_async_handle(uv_async_t *async) { memset(async, 0, sizeof(uv_async_t)); - uv_loop_t *loop = uv_default_loop(); + // uv_loop_t *loop = uv_default_loop(); + loop = (uv_loop_t*)malloc(sizeof(uv_loop_t)); + uv_loop_init(loop); uv_async_init(loop, async, cocos2d::flush_tasks_in_server_loop_cb); async->data = new AsyncTaskData(); uv_run(loop, UV_RUN_DEFAULT); @@ -69,7 +71,12 @@ NS_CC_BEGIN //notify server thread to invoke `flush_tasks_in_server_loop_cb()` return uv_async_send(asyn); } - +#define RUN_IN_GAMETHREAD(task) \ + do { \ + JcWallet::getInstance()->performFunctionInCocosThread([=]() { \ + task; \ + });\ + } while(0) #define RUN_IN_SERVERTHREAD(task) do { \ schedule_task_into_server_thread_task_queue(&gasync, [=](){ \ task; \ @@ -98,6 +105,8 @@ NS_CC_BEGIN JcWallet::JcWallet() { JcWallet::_instance = this; + _functionsToPerform.reserve(30); + std::unique_lock lock(_performMutex); } void JcWallet::initEnv() { @@ -111,6 +120,7 @@ NS_CC_BEGIN g_app->start(); _isStarted = true; WalletEvent::Emit("wallet_init_event", "{}"); +// RUN_IN_GAMETHREAD(JcWallet::getInstance()->jsToUnity("wallet_init_event", "{}")); cocos2d::init_libuv_async_handle(&gasync); } } @@ -127,12 +137,12 @@ NS_CC_BEGIN JcWallet::~JcWallet() { EventDispatcher::destroy(); se::ScriptEngine::destroyInstance(); - uv_loop_close(uv_default_loop()); + uv_loop_close(loop); JcWallet::_instance = nullptr; } char *JcWallet::runJsMethod(std::shared_ptr data) { - cocos2d::log("thread: %ld call method %s", uv_thread_self(), data->methodName.c_str()); + cocos2d::log("thread: %ld call method %s params: %d", uv_thread_self(), data->methodName.c_str(), data->args.size()); se::Value value; bool ok = cocos2d::runGlobalMethod(data->methodName.c_str(), data->args, &value); static std::string result; @@ -143,14 +153,39 @@ NS_CC_BEGIN result = ""; } cocos2d::log("method: %s ::result: %s", data->methodName.c_str(), result.c_str()); - WalletEvent::Emit(data->funId.c_str(), result.c_str()); + RUN_IN_GAMETHREAD(JcWallet::getInstance()->jsToUnity(data->funId, result)); +// WalletEvent::Emit(data->funId.c_str(), result.c_str()); } return const_cast(result.c_str()); } + void JcWallet::performFunctionInCocosThread( const std::function &function) { + _performMutex.lock(); + _functionsToPerform.push_back(function); + _performMutex.unlock(); + } + + void JcWallet::tickRun() { + _performMutex.lock(); + if( !_functionsToPerform.empty() ) { + // fixed #4123: Save the callback functions, they must be invoked after '_performMutex.unlock()', otherwise if new functions are added in callback, it will cause thread deadlock. + auto temp = _functionsToPerform; + for( const auto &function : temp ) { + function(); + } + _functionsToPerform.clear(); + } + _performMutex.unlock(); + } + + void JcWallet::jsToUnity(std::string funId, std::string msg) { + WalletEvent::Emit(funId.c_str(), msg.c_str()); + } + extern "C" { void initEnv() { if (!_isStarted) { + new JcWallet(); std::shared_ptr wallet(JcWallet::getInstance()); std::thread([=]() { JcWallet::initJSThread(wallet); @@ -162,6 +197,7 @@ NS_CC_BEGIN schedule_task_into_server_thread_task_queue(&gasync, [=](){ JcWallet::getInstance()->tick(dt); }); + JcWallet::getInstance()->tickRun(); } } @@ -180,9 +216,9 @@ NS_CC_BEGIN int result = schedule_task_into_server_thread_task_queue(&gasync, [=](){ JcWallet::getInstance()->runJsMethod(params); }); -// RUN_IN_SERVERTHREAD(JcWallet::getInstance()->runJsMethod(params)); return result == 0 ? 1 : 0; } + } int nativeCallBack(const char *funId, const char *methodName, const char *cparams) { @@ -201,6 +237,7 @@ int nativeCallBack(const char *funId, const char *methodName, const char *cparam } NS_CC_END + static bool getOrCreatePlainObject_r(const char* name, se::Object* parent, se::Object** outObj) { assert(parent != nullptr); @@ -232,7 +269,8 @@ bool jsb_wallet_callback(se::State& s) { std::string msg; ok = seval_to_std_string(args[1], &msg); SE_PRECONDITION2(ok, false, "Error processing arguments"); - WalletEvent::Emit(funId.c_str(), msg.c_str()); +// WalletEvent::Emit(funId.c_str(), msg.c_str()); + RUN_IN_GAMETHREAD(JcWallet::getInstance()->jsToUnity(funId, msg)); return true; } return false;