From 2673cea45df37dc1b755c1a9cddf03001a9e091d Mon Sep 17 00:00:00 2001 From: onexiaomin Date: Wed, 15 Feb 2023 10:22:05 +0800 Subject: [PATCH] add ThreadSafeSchedule() interface which contains only one parameter. Signed-off-by: wangminmin --- .../include/n_async/n_async_context.h | 2 +- .../include/n_async/n_async_work_callback.h | 4 +- .../src/n_async/n_async_work_callback.cpp | 128 +++++++++++++++++- 3 files changed, 131 insertions(+), 3 deletions(-) diff --git a/utils/filemgmt_libn/include/n_async/n_async_context.h b/utils/filemgmt_libn/include/n_async/n_async_context.h index 2d0b206aa..b252831af 100644 --- a/utils/filemgmt_libn/include/n_async/n_async_context.h +++ b/utils/filemgmt_libn/include/n_async/n_async_context.h @@ -35,7 +35,7 @@ public: NContextCBExec cbExec_; NContextCBComplete cbComplete_; napi_async_work awork_; - NRef thisPtr_; + NVal thisPtr_; NAsyncContext(NVal thisPtr) : err_(0), res_(NVal()), cbExec_(nullptr), cbComplete_(nullptr), awork_(nullptr), thisPtr_(thisPtr) diff --git a/utils/filemgmt_libn/include/n_async/n_async_work_callback.h b/utils/filemgmt_libn/include/n_async/n_async_work_callback.h index 66af8fbf8..6fb514668 100644 --- a/utils/filemgmt_libn/include/n_async/n_async_work_callback.h +++ b/utils/filemgmt_libn/include/n_async/n_async_work_callback.h @@ -24,8 +24,10 @@ namespace LibN { class NAsyncWorkCallback : public NAsyncWork { public: NAsyncWorkCallback(napi_env env, NVal thisPtr, NVal cb); - ~NAsyncWorkCallback() = default; + ~NAsyncWorkCallback(); NVal Schedule(std::string procedureName, NContextCBExec cbExec, NContextCBComplete cbComplete) final; + void ThreadSafeSchedule(NContextCBComplete cbComplete); + explicit operator bool() const; private: NAsyncContextCallback *ctx_ = nullptr; diff --git a/utils/filemgmt_libn/src/n_async/n_async_work_callback.cpp b/utils/filemgmt_libn/src/n_async/n_async_work_callback.cpp index f040cfabe..0721ddec3 100644 --- a/utils/filemgmt_libn/src/n_async/n_async_work_callback.cpp +++ b/utils/filemgmt_libn/src/n_async/n_async_work_callback.cpp @@ -14,7 +14,12 @@ */ #include "n_async_work_callback.h" + +#include +#include + #include "filemgmt_libhilog.h" +#include "uv.h" namespace OHOS { namespace FileManagement { @@ -26,13 +31,55 @@ NAsyncWorkCallback::NAsyncWorkCallback(napi_env env, NVal thisPtr, NVal cb) : NA ctx_ = new NAsyncContextCallback(thisPtr, cb); } +NAsyncWorkCallback::~NAsyncWorkCallback() +{ + if (!ctx_) { + return; + } + + unique_ptr ptr(ctx_); + uv_loop_s *loop = nullptr; + napi_status status = napi_get_uv_event_loop(env_, &loop); + if (status != napi_ok) { + HILOGE("Failed to get uv event loop"); + return; + } + + unique_ptr work(new (std::nothrow) uv_work_t); + if (work == nullptr) { + HILOGE("Failed to new uv_work_t"); + return; + } + work->data = static_cast(ctx_); + + int ret = uv_queue_work( + loop, work.get(), [](uv_work_t *work) {}, + [](uv_work_t *work, int status) { + NAsyncContextCallback *ctx = static_cast(work->data); + delete ctx; + delete work; + }); + if (ret) { + HILOGE("Failed to call uv_queue_work %{public}d", status); + return; + } + ptr.release(); + work.release(); + ctx_ = nullptr; +} + +NAsyncWorkCallback::operator bool() const +{ + return bool(ctx_->cb_); +} + static void CallbackExecute(napi_env env, void *data) { auto ctx = static_cast(data); if (ctx != nullptr && ctx->cbExec_ != nullptr) { ctx->err_ = ctx->cbExec_(); } else { - HILOGE("Callback execute function, This pointer or function address is empty."); + HILOGE("Callback execute function, This pointer or function address is empty"); } } @@ -99,6 +146,85 @@ NVal NAsyncWorkCallback::Schedule(string procedureName, NContextCBExec cbExec, N ctx_ = nullptr; // The ownership of ctx_ has been transferred return NVal::CreateUndefined(env_); } + +static void AfterWorkCallback(napi_env env, napi_status status, void *data, NContextCBComplete cbComplete) +{ + napi_handle_scope scope = nullptr; + napi_open_handle_scope(env, &scope); + auto ctx = static_cast(data); + if (ctx == nullptr) { + HILOGE("This pointer address is empty"); + napi_close_handle_scope(env, scope); + return; + } + if (cbComplete) { + ctx->res_ = cbComplete(env, ctx->err_); + ctx->cbComplete_ = nullptr; + } + + vector argv; + if (!ctx->res_.TypeIsError(true)) { + argv = {NError(ERRNO_NOERR).GetNapiErr(env), ctx->res_.val_}; + } else { + argv = {ctx->res_.val_}; + } + + napi_value global = nullptr; + napi_value callback = ctx->cb_.Deref(env).val_; + napi_value tmp = nullptr; + napi_get_global(env, &global); + napi_status stat = napi_call_function(env, global, callback, argv.size(), argv.data(), &tmp); + if (stat != napi_ok) { + HILOGE("Failed to call function for %{public}d", stat); + } + + napi_close_handle_scope(env, scope); + napi_delete_async_work(env, ctx->awork_); +} + +void NAsyncWorkCallback::ThreadSafeSchedule(NContextCBComplete cbComplete) +{ + ctx_->cbExec_ = nullptr; + ctx_->cbComplete_ = nullptr; + + uv_loop_s *loop = nullptr; + napi_status status = napi_get_uv_event_loop(env_, &loop); + if (status != napi_ok) { + HILOGE("Failed to get uv event loop"); + return; + } + + unique_ptr work(new (std::nothrow) uv_work_t); + if (!work) { + HILOGE("Failed to new uv_work_t"); + return; + } + + struct WorkArgs { + NAsyncWorkCallback *ptr = nullptr; + NContextCBComplete cb; + }; + auto workArgs = make_unique(); + workArgs->ptr = this; + workArgs->cb = cbComplete; + + work->data = static_cast(workArgs.get()); + + int ret = uv_queue_work( + loop, work.get(), [](uv_work_t *work) {}, + [](uv_work_t *work, int status) { + auto workArgs = static_cast(work->data); + AfterWorkCallback(workArgs->ptr->env_, napi_ok, workArgs->ptr->ctx_, workArgs->cb); + delete workArgs; + delete work; + }); + if (ret) { + HILOGE("Failed to call uv_queue_work %{public}d", status); + return; + } + workArgs.release(); + work.release(); +} } // namespace LibN } // namespace FileManagement } // namespace OHOS -- Gitee