From 0fccc83c176895af404afc6ffab60cf5e563528e Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 13 Jun 2023 00:16:01 +0000 Subject: [PATCH] Add AppCoreUiThreadBase class To support preloading ui thread in the candidate process, the class is added. The AppCoreUiBase class uses the AppCoreUiThreadBase class to create & run the ui thread. Change-Id: Ibb290befd3fb58bbb465873d2ef9bff2ba4863a5 Signed-off-by: Hwankyu Jhun --- CMakeLists.txt | 1 + packaging/app-core.spec | 27 ++-- tizen-cpp/app-core-ui-cpp/CMakeLists.txt | 1 + tizen-cpp/app-core-ui-cpp/app_core_ui_base.cc | 56 ++------ .../app-core-ui-cpp/app_core_ui_thread_base.cc | 145 +++++++++++++++++++++ .../app-core-ui-cpp/app_core_ui_thread_base.hh | 55 ++++++++ unittests/CMakeLists.txt | 1 + 7 files changed, 232 insertions(+), 54 deletions(-) create mode 100644 tizen-cpp/app-core-ui-cpp/app_core_ui_thread_base.cc create mode 100644 tizen-cpp/app-core-ui-cpp/app_core_ui_thread_base.hh diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f9fe37..a24831a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,7 @@ PKG_CHECK_MODULES(GOBJECT_2_DEPS REQUIRED gobject-2.0) PKG_CHECK_MODULES(PKGMGR_INFO_DEPS REQUIRED pkgmgr-info) PKG_CHECK_MODULES(SENSOR_DEPS REQUIRED sensor) PKG_CHECK_MODULES(TIZEN_EXTENSION_CLIENT_DEPS REQUIRED tizen-extension-client) +PKG_CHECK_MODULES(TIZEN_SHARED_QUEUE_DEPS REQUIRED tizen-shared-queue) PKG_CHECK_MODULES(TTRACE_DEPS REQUIRED ttrace) PKG_CHECK_MODULES(VCONF_DEPS REQUIRED vconf) PKG_CHECK_MODULES(WAYLAND_CLIENT_DEPS REQUIRED wayland-client) diff --git a/packaging/app-core.spec b/packaging/app-core.spec index 66abd88..39b7e7b 100644 --- a/packaging/app-core.spec +++ b/packaging/app-core.spec @@ -5,26 +5,28 @@ Release: 0 Group: Application Framework/Libraries License: Apache-2.0 Source0: app-core-%{version}.tar.gz -BuildRequires: pkgconfig(ecore-wl2) -BuildRequires: pkgconfig(wayland-client) -BuildRequires: pkgconfig(tizen-extension-client) -BuildRequires: pkgconfig(wayland-tbm-client) Source1001: app-core.manifest -BuildRequires: pkgconfig(gio-2.0) -BuildRequires: pkgconfig(sensor) -BuildRequires: pkgconfig(vconf) + +BuildRequires: cmake BuildRequires: pkgconfig(aul) BuildRequires: pkgconfig(bundle) +BuildRequires: pkgconfig(capi-system-info) BuildRequires: pkgconfig(dlog) -BuildRequires: pkgconfig(elementary) BuildRequires: pkgconfig(ecore) -BuildRequires: pkgconfig(gobject-2.0) +BuildRequires: pkgconfig(ecore-wl2) +BuildRequires: pkgconfig(elementary) +BuildRequires: pkgconfig(gio-2.0) BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(gmock) +BuildRequires: pkgconfig(gobject-2.0) BuildRequires: pkgconfig(pkgmgr-info) +BuildRequires: pkgconfig(sensor) +BuildRequires: pkgconfig(tizen-extension-client) +BuildRequires: pkgconfig(tizen-shared-queue) BuildRequires: pkgconfig(ttrace) -BuildRequires: pkgconfig(gmock) -BuildRequires: cmake -BuildRequires: pkgconfig(capi-system-info) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(wayland-client) +BuildRequires: pkgconfig(wayland-tbm-client) %if 0%{?gcov:1} BuildRequires: lcov @@ -295,6 +297,7 @@ install -m 0644 %{name}.zip %{buildroot}%{_datadir}/gcov/ %{_includedir}/appcore_cpp/app_core_task_base.hh %{_includedir}/appcore_cpp/app_core_ui_base.hh +%{_includedir}/appcore_cpp/app_core_ui_thread_base.hh %{_includedir}/appcore_cpp/api/app_core_ui_base.h %{_libdir}/libapp-core-ui-cpp.so %{_libdir}/pkgconfig/app-core-ui-cpp.pc diff --git a/tizen-cpp/app-core-ui-cpp/CMakeLists.txt b/tizen-cpp/app-core-ui-cpp/CMakeLists.txt index b722e69..6c52af8 100644 --- a/tizen-cpp/app-core-ui-cpp/CMakeLists.txt +++ b/tizen-cpp/app-core-ui-cpp/CMakeLists.txt @@ -31,6 +31,7 @@ APPLY_PKG_CONFIG(${TARGET_APP_CORE_UI_CPP} PUBLIC GOBJECT_2_DEPS PKGMGR_INFO_DEPS TIZEN_EXTENSION_CLIENT_DEPS + TIZEN_SHARED_QUEUE_DEPS TTRACE_DEPS WAYLAND_CLIENT_DEPS ) diff --git a/tizen-cpp/app-core-ui-cpp/app_core_ui_base.cc b/tizen-cpp/app-core-ui-cpp/app_core_ui_base.cc index e7f8c0e..9b1c99f 100644 --- a/tizen-cpp/app-core-ui-cpp/app_core_ui_base.cc +++ b/tizen-cpp/app-core-ui-cpp/app_core_ui_base.cc @@ -39,6 +39,7 @@ #include "app-core-ui-cpp/app_core_task_base.hh" #include "app-core-ui-cpp/app_core_ui_delegator_private.hh" #include "app-core-ui-cpp/app_core_ui_plugin_private.hh" +#include "app-core-ui-cpp/app_core_ui_thread_base.hh" #include "app-core-ui-cpp/wayland_handler_private.hh" #include "app-core-ui-cpp/window_position_private.hh" #include "common/ecore_handler.hh" @@ -51,22 +52,6 @@ constexpr const char K_SERVICE_THREAD[] = "__K_SERVICE_THREAD"; constexpr const char K_HINT_RECENT_SCREEN_POSITION[] = "__K_HINT_RECENT_SCREEN_POSITION"; -void SetComm(const std::string& name) { - pid_t tid = syscall(__NR_gettid); - std::string path = "/proc/" + std::to_string(tid) + "/comm"; - int fd = open(path.c_str(), O_WRONLY); - if (fd < 0) { - _E("open(%s) is failed. errno(%d)", path.c_str(), errno); - return; - } - - ssize_t bytes_written = write(fd, name.c_str(), name.length() + 1); - if (bytes_written < 0) - _E("write(%d) is failed. errno(%d)", fd, errno); - - close(fd); -} - class AppCoreUiBase::Impl { public: Impl(AppCoreUiBase* parent, unsigned int hint) @@ -151,11 +136,10 @@ class AppCoreUiBase::Impl { std::unique_ptr plugin_delegator_; std::unique_ptr plugin_; std::unique_ptr service_; - GMainContext* context_ = nullptr; - std::thread thread_; std::unique_ptr position_; Ecore_Wl2_Window* window_ = nullptr; std::unique_ptr wp_manager_; + std::unique_ptr thread_; }; AppCoreUiBase::AppCoreUiBase(unsigned int hint) @@ -526,28 +510,16 @@ void AppCoreUiBase::DoExit() { void AppCoreUiBase::Impl::Run(int argc, char** argv) { if (hint_ & HINT_DUAL_THREAD) { - // For the loader case - while (ecore_shutdown() != 0) {} - service_ = parent_->CreateTask(); - context_ = g_main_context_new(); - std::string env = std::to_string( - reinterpret_cast(context_)); - setenv("TIZEN_GLIB_CONTEXT", env.c_str(), 1); - - thread_ = std::thread([&] { - SetComm("UIThread+"); - parent_->DoRun(argc, argv); - }); + auto* thread_context = AppCoreUiThreadBase::GetContext(); + if (thread_context == nullptr) { + thread_.reset(new AppCoreUiThreadBase()); + thread_->Run(argc, argv); + thread_context = AppCoreUiThreadBase::GetContext(); + } + thread_context->Post([&]() { parent_->DoRun(argc, argv); }); service_->Run(argc, argv); - - if (thread_.joinable()) - thread_.join(); - - setenv("TIZEN_GLIB_CONTEXT", "0", 1); - g_main_context_unref(context_); - context_ = nullptr; return; } @@ -556,11 +528,11 @@ void AppCoreUiBase::Impl::Run(int argc, char** argv) { void AppCoreUiBase::Impl::Exit() { if (hint_ & HINT_DUAL_THREAD) { - GLib::IdleAdd(context_, [](gpointer user_data) { - auto* impl = static_cast(user_data); - impl->parent_->DoExit(); - return G_SOURCE_REMOVE; - }, this); + auto* thread_context = AppCoreUiThreadBase::GetContext(); + if (thread_context != nullptr) { + thread_context->Post([&]() { parent_->DoExit(); }); + thread_context->Exit(); + } service_->Exit(); return; diff --git a/tizen-cpp/app-core-ui-cpp/app_core_ui_thread_base.cc b/tizen-cpp/app-core-ui-cpp/app_core_ui_thread_base.cc new file mode 100644 index 0000000..2b3fe35 --- /dev/null +++ b/tizen-cpp/app-core-ui-cpp/app_core_ui_thread_base.cc @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "app-core-ui-cpp/app_core_ui_thread_base.hh" + +#include +#include +#include +#include + +#include +#include + +#include + +#include "common/glib_private.hh" +#include "common/log_private.hh" + +namespace tizen_cpp { +namespace { + +AppCoreUiThreadBase* context = nullptr; + +} // namespace + +class AppCoreUiThreadBase::Impl { + public: + Impl(AppCoreUiThreadBase* parent) : parent_(parent) {} + + ~Impl() { + if (thread_.joinable()) + thread_.join(); + } + + void Run(int argc, char** argv) { + if (context_ != nullptr) { + _E("Already running"); + return; + } + + context_ = g_main_context_new(); + std::string context_str = std::to_string( + reinterpret_cast(context_)); + setenv("TIZEN_GLIB_CONTEXT", context_str.c_str(), 1); + + thread_ = std::thread([&] { + pthread_setname_np(pthread_self(), "UIThread+"); + parent_->OnLoopInit(argc, argv); + parent_->OnLoopRun(); + parent_->OnLoopFinish(); + }); + } + + void Exit() { + parent_->OnLoopExit(); + } + + void Post(Runner runner) { + queue_.Push(std::move(runner)); + + guint source = GLib::IdleAdd(context_, + [](gpointer user_data) { + auto* impl = static_cast(user_data); + auto action = std::move(impl->queue_.WaitAndPop()); + action(); + return G_SOURCE_REMOVE; + }, this); + if (source == 0) + _E("Failed to add idle source"); + } + + private: + friend class AppCoreUiThreadBase; + AppCoreUiThreadBase* parent_; + + private: + std::thread thread_; + GMainContext* context_ = nullptr; + tizen_base::SharedQueue queue_; +}; + +AppCoreUiThreadBase::AppCoreUiThreadBase() : impl_(new Impl(this)) { + if (context != nullptr) + _E("Already exists"); + + context = this; +} + +AppCoreUiThreadBase::~AppCoreUiThreadBase() { + context = nullptr; +} + +void AppCoreUiThreadBase::Run(int argc, char** argv) { + impl_->Run(argc, argv); +} + +void AppCoreUiThreadBase::Exit() { + impl_->Exit(); +} + +void AppCoreUiThreadBase::Post(Runner runner) { + impl_->Post(std::move(runner)); +} + +void AppCoreUiThreadBase::OnLoopInit(int argc, char** argv) { + _W("Loop init"); + ecore_init(); +} + +void AppCoreUiThreadBase::OnLoopRun() { + _W("Loop run"); + ecore_main_loop_begin(); +} + +void AppCoreUiThreadBase::OnLoopExit() { + _W("Loop quit"); + ecore_main_loop_thread_safe_call_sync([](void* data) -> void* { + ecore_main_loop_quit(); + return nullptr; + }, nullptr); +} + +void AppCoreUiThreadBase::OnLoopFinish() { + _W("Loop finish"); + ecore_shutdown(); +} + +AppCoreUiThreadBase* AppCoreUiThreadBase::GetContext() { + return context; +} + +} // namespace tizen_cpp diff --git a/tizen-cpp/app-core-ui-cpp/app_core_ui_thread_base.hh b/tizen-cpp/app-core-ui-cpp/app_core_ui_thread_base.hh new file mode 100644 index 0000000..b13254d --- /dev/null +++ b/tizen-cpp/app-core-ui-cpp/app_core_ui_thread_base.hh @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TIZEN_CPP_APP_CORE_UI_CPP_APP_CORE_UI_THREAD_BASE_HH_ +#define TIZEN_CPP_APP_CORE_UI_CPP_APP_CORE_UI_THREAD_BASE_HH_ + +#include +#include + +#include + +#undef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) + +namespace tizen_cpp { + +class EXPORT_API AppCoreUiThreadBase : public IMainLoop { + public: + using Runner = std::function; + + AppCoreUiThreadBase(); + virtual ~AppCoreUiThreadBase(); + + void Run(int argc, char** argv); + void Exit(); + void Post(Runner runner); + + void OnLoopInit(int argc, char** argv) override; + void OnLoopRun() override; + void OnLoopExit() override; + void OnLoopFinish() override; + + static AppCoreUiThreadBase* GetContext(); + + private: + class Impl; + std::unique_ptr impl_; +}; + +} // namespace tizen_cpp + +#endif // TIZEN_CPP_APP_CORE_UI_CPP_APP_CORE_UI_THREAD_BASE_HH_ diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index 23aeff3..b7a6671 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -48,6 +48,7 @@ APPLY_PKG_CONFIG(${TARGET_UNIT_TEST} PUBLIC PKGMGR_INFO_DEPS SENSOR_DEPS TIZEN_EXTENSION_CLIENT_DEPS + TIZEN_SHARED_QUEUE_DEPS TTRACE_DEPS VCONF_DEPS WAYLAND_CLIENT_DEPS -- 2.7.4