This patch supports UI thread for ui-applications. There are two threads.
The main thread is for Service thread and the sub thread is for UI thread.
Service thread is recommended to contain the Model of MVC pattern. UI thread
is recommended to contain the View and Controller of MVC pattern.
Requires:
- https://review.tizen.org/gerrit/#/c/platform/upstream/efl/+/270474/
Change-Id: I77b196dd37e6cd42c9c3b914bfe9ed89f3c61391
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
%{_includedir}/appcore_cpp/app_core_base.hh
%{_includedir}/appcore_cpp/interface_app_core.hh
%{_includedir}/appcore_cpp/interface_app_core_ui.hh
+%{_includedir}/appcore_cpp/interface_app_core_ui_event.hh
%{_includedir}/appcore_cpp/interface_main_loop.hh
%{_includedir}/appcore_cpp/interface_window.hh
%{_libdir}/libapp-core-cpp.so
%{_libdir}/libappcore-ui.so
%{_libdir}/pkgconfig/appcore-ui.pc
+%{_includedir}/appcore_cpp/app_core_task_base.hh
%{_includedir}/appcore_cpp/app_core_ui_base.hh
%{_includedir}/appcore_cpp/api/app_core_ui_base.h
%{_libdir}/libapp-core-ui-cpp.so
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} APP_CORE_CPP_SRCS)
+SET(COMMON_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/../common/glib_private.cc)
-ADD_LIBRARY(${TARGET_APP_CORE_CPP} SHARED ${APP_CORE_CPP_SRCS})
+ADD_LIBRARY(${TARGET_APP_CORE_CPP} SHARED
+ ${APP_CORE_CPP_SRCS}
+ ${COMMON_SRCS})
TARGET_INCLUDE_DIRECTORIES(${TARGET_APP_CORE_CPP} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
#include <sstream>
#include "app-core-cpp/app_core_base.hh"
+#include "common/glib_private.hh"
#include "common/log_private.hh"
extern "C" void aul_finalize();
void AppCoreBase::Impl::LanguageChangeCb(keynode_t* key, void* user_data) {
AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
if (base->impl_->sid_) {
- g_source_remove(base->impl_->sid_);
+ GLib::SourceRemove(base->impl_->sid_);
base->impl_->sid_ = 0;
}
if (strcmp(env_lang, lang) != 0) {
_I("LANG(%s), LANGSET(%s)", env_lang, lang);
- sid_ = g_idle_add(InvokeLangChangeCb, parent_);
+ sid_ = GLib::IdleAdd(InvokeLangChangeCb, parent_);
}
}
if (!impl_->allowed_bg_)
RemoveSuspendTimer();
- if (impl_->loop_delegator_)
- impl_->loop_delegator_->OnLoopExit();
- else
- OnLoopExit();
+ Exit();
break;
case AUL_TERMINATE_INST:
case AUL_TERMINATE_BG_INST:
}
void AppCoreBase::AddSuspendTimer() {
- impl_->tid_ = g_timeout_add_seconds(5, [](gpointer data) -> gboolean {
+ impl_->tid_ = GLib::TimeoutAdd(5000, [](gpointer data) -> gboolean {
AppCoreBase* base = reinterpret_cast<AppCoreBase*>(data);
base->FlushMemory();
return FALSE;
void AppCoreBase::RemoveSuspendTimer() {
if (impl_->tid_ > 0) {
- g_source_remove(impl_->tid_);
+ GLib::SourceRemove(impl_->tid_);
impl_->tid_ = 0;
}
}
traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT)
- g_idle_add(Impl::InitSuspendCb, this);
+ GLib::IdleAdd(Impl::InitSuspendCb, this);
traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:SET_SYSTEM_EVENT");
if (!impl_->dirty_) {
impl_->UnsetDefaultEvents();
if (impl_->sid_) {
- g_source_remove(impl_->sid_);
+ GLib::SourceRemove(impl_->sid_);
impl_->sid_ = 0;
}
--- /dev/null
+/*
+ * Copyright (c) 2022 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_CPP_INTERFACE_APP_CORE_UI_EVENT_HH_
+#define TIZEN_CPP_APP_CORE_CPP_INTERFACE_APP_CORE_UI_EVENT_HH_
+
+#undef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+
+namespace tizen_cpp {
+
+class EXPORT_API IAppCoreUiEvent {
+ public:
+ enum class UiState {
+ RESUMED,
+ PAUSED,
+ };
+
+ virtual ~IAppCoreUiEvent() = default;
+
+ virtual void Post(UiState state) = 0;
+ virtual void OnUiEvent(UiState state) = 0;
+};
+
+} // namespace tizen_cpp
+
+#endif // TIZEN_CPP_APP_CORE_CPP_INTERFACE_APP_CORE_UI_EVENT_HH_
#include <glib.h>
#include <stdlib.h>
+#include <condition_variable>
#include <memory>
+#include <mutex>
#include <string>
#include <thread>
#include "app-core-efl-cpp/app_core_efl_base.hh"
#include "app-core-efl-cpp/voice_elm_private.hh"
#include "common/log_private.hh"
+#include "common/glib_private.hh"
namespace tizen_cpp {
AppCoreEflBase* parent_;
std::thread thread_;
+ bool thread_started_ = false;
+ std::condition_variable cond_;
std::unique_ptr<VoiceElm> vc_elm_;
guint source_id_ = 0;
+ std::mutex mutex_;
+ bool initialized_ = false;
};
AppCoreEflBase::Impl::Impl(AppCoreEflBase* parent) : parent_(parent) {}
thread_.join();
if (source_id_ != 0)
- g_source_remove(source_id_);
+ GLib::SourceRemove(source_id_);
}
void AppCoreEflBase::Impl::Init(int argc, char** argv) {
+ if (initialized_)
+ return;
+
elm_init(argc, argv);
unsigned int hint = parent_->GetHint();
if ((hint & HINT_HW_ACC_CONTROL) && !getenv("AUL_HWACC")) {
}
if (VoiceElm::IsVtAutoMode()) {
+ std::unique_lock<std::mutex> lock(mutex_);
thread_ = std::thread([&] {
+ std::unique_lock<std::mutex> lock(mutex_);
+ thread_started_ = true;
+ cond_.notify_one();
+
int retry_count = 3;
do {
if (vc_elm_.get() == nullptr)
vc_elm_.reset(VoiceElm::Load());
if (vc_elm_.get() != nullptr) {
- source_id_ = g_idle_add([](gpointer user_data) {
+ source_id_ = GLib::IdleAdd([](gpointer user_data) {
auto* impl = static_cast<AppCoreEflBase::Impl*>(user_data);
if (impl->vc_elm_.get() != nullptr)
impl->vc_elm_->Init();
}
} while (retry_count--);
});
+ cond_.wait(lock, [&] { return thread_started_; });
}
+
+ initialized_ = true;
}
void AppCoreEflBase::Impl::Finish() {
+ if (!initialized_)
+ return;
+
if (thread_.joinable())
thread_.join();
+ thread_started_ = false;
+
+ if (source_id_ != 0) {
+ GLib::SourceRemove(source_id_);
+ source_id_ = 0;
+ }
+
elm_shutdown();
// Check loader case
setenv("AUL_LOADER_INIT", "0", 1);
elm_shutdown();
}
+
+ initialized_ = false;
}
void AppCoreEflBase::Impl::LoopRun() {
#include "app-core-ui-cpp/api/app_core_ui_base.h"
+#include <stdlib.h>
+
#include "app-core-ui-cpp/app_core_ui_base.hh"
#undef API
auto* base = static_cast<AppCoreUiBase*>(h);
base->SetSystemResourceReclaiming(enable);
}
+
+API void* app_core_ui_base_get_tizen_glib_context(void) {
+ const char* env = getenv("TIZEN_GLIB_CONTEXT");
+ if (env)
+ return reinterpret_cast<void*>(strtoul(env, nullptr, 10));
+
+ return nullptr;
+}
void app_core_ui_base_set_system_resource_reclaiming(app_core_ui_base_h h, bool enable);
+void *app_core_ui_base_get_tizen_glib_context(void);
+
#ifdef __cplusplus
}
#endif // __cplusplus
--- /dev/null
+/*
+ * Copyright (c) 2022 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_task_base.hh"
+
+#include <glib.h>
+#include <vconf-internal-keys.h>
+
+#include <memory>
+#include <mutex>
+#include <queue>
+#include <vector>
+
+#include "common/glib_private.hh"
+
+namespace tizen_cpp {
+
+class SystemEvent : public AppCoreBase::EventBase {
+ public:
+ class IEvent {
+ public:
+ virtual ~IEvent() = default;
+ virtual void OnSystemEvent(Type type) = 0;
+ };
+
+ SystemEvent(IAppCore::IEvent::Type type, IEvent* listener);
+
+ void OnEvent(const std::string& value) override;
+ void OnEvent(int value) override;
+
+ private:
+ IEvent* listener_;
+};
+
+class AppCoreTaskBase::Impl : public SystemEvent::IEvent {
+ public:
+ Impl(AppCoreTaskBase* parent);
+
+ void LoopInit(int argc, char** argv);
+ void LoopRun();
+ void LoopExit();
+ void LoopFinish();
+ void SetSystemEvents();
+ void UnsetSystemEvents();
+ void Post(UiState state);
+ std::recursive_mutex& GetMutex() const;
+
+ private:
+ void OnSystemEvent(IAppCore::IEvent::Type type) override;
+ DeviceOrientationState ConvertRotationState(int value);
+ LowMemoryState ConvertLowMemoryState(int value);
+ LowBatteryState ConvertLowBatteryState(int value);
+
+ private:
+ friend class AppCoreTaskBase;
+ AppCoreTaskBase* parent_;
+ std::shared_ptr<SystemEvent> low_memory_;
+ std::shared_ptr<SystemEvent> low_battery_;
+ std::shared_ptr<SystemEvent> lang_change_;
+ std::shared_ptr<SystemEvent> device_orientation_changed_;
+ std::shared_ptr<SystemEvent> region_change_;
+ GMainLoop* loop_ = nullptr;
+ std::queue<UiState> queue_;
+ mutable std::recursive_mutex mutex_;
+};
+
+SystemEvent::SystemEvent(Type type, SystemEvent::IEvent* listener)
+ : EventBase(type), listener_(listener) {
+}
+
+void SystemEvent::OnEvent(const std::string& value) {
+ listener_->OnSystemEvent(GetType());
+}
+
+void SystemEvent::OnEvent(int value) {
+ listener_->OnSystemEvent(GetType());
+}
+
+AppCoreTaskBase::Impl::Impl(AppCoreTaskBase* parent) : parent_(parent) {
+ low_memory_ = std::make_shared<SystemEvent>(
+ IAppCore::IEvent::Type::LOW_MEMORY, this);
+ low_battery_ = std::make_shared<SystemEvent>(
+ IAppCore::IEvent::Type::LOW_BATTERY, this);
+ lang_change_ = std::make_shared<SystemEvent>(
+ IAppCore::IEvent::Type::LANG_CHANGE, this);
+ device_orientation_changed_ = std::make_shared<SystemEvent>(
+ IAppCore::IEvent::Type::DEVICE_ORIENTATION_CHANGED, this);
+ region_change_ = std::make_shared<SystemEvent>(
+ IAppCore::IEvent::Type::REGION_CHANGE, this);
+}
+
+void AppCoreTaskBase::Impl::LoopInit(int argc, char** argv) {
+ loop_ = g_main_loop_new(nullptr, FALSE);
+}
+
+void AppCoreTaskBase::Impl::LoopRun() {
+ g_main_loop_run(loop_);
+}
+
+void AppCoreTaskBase::Impl::LoopExit() {
+ g_main_loop_quit(loop_);
+}
+
+void AppCoreTaskBase::Impl::LoopFinish() {
+ g_main_loop_unref(loop_);
+}
+
+void AppCoreTaskBase::Impl::SetSystemEvents() {
+ parent_->AddEvent(low_memory_);
+ parent_->AddEvent(low_battery_);
+ parent_->AddEvent(lang_change_);
+ parent_->AddEvent(device_orientation_changed_);
+ parent_->AddEvent(region_change_);
+}
+
+void AppCoreTaskBase::Impl::UnsetSystemEvents() {
+ parent_->RemoveEvent(region_change_);
+ parent_->RemoveEvent(device_orientation_changed_);
+ parent_->RemoveEvent(lang_change_);
+ parent_->RemoveEvent(low_battery_);
+ parent_->RemoveEvent(low_memory_);
+}
+
+void AppCoreTaskBase::Impl::OnSystemEvent(IAppCore::IEvent::Type type) {
+ if (type == IAppCore::IEvent::Type::LOW_MEMORY) {
+ parent_->OnLowMemory(ConvertLowMemoryState(low_memory_->GetVal(0)));
+ } else if (type == IAppCore::IEvent::Type::LOW_BATTERY) {
+ parent_->OnLowBattery(ConvertLowBatteryState(low_battery_->GetVal(0)));
+ } else if (type == IAppCore::IEvent::Type::LANG_CHANGE) {
+ parent_->OnLangChanged(lang_change_->GetVal(""));
+ } else if (type == IAppCore::IEvent::Type::DEVICE_ORIENTATION_CHANGED) {
+ parent_->OnDeviceOrientationChanged(
+ ConvertRotationState(device_orientation_changed_->GetVal(0)));
+ } else if (type == IAppCore::IEvent::Type::REGION_CHANGE) {
+ parent_->OnRegionChanged(region_change_->GetVal(""));
+ }
+}
+
+void AppCoreTaskBase::Impl::Post(UiState state) {
+ std::lock_guard<std::recursive_mutex> lock(mutex_);
+ queue_.push(state);
+
+ GLib::IdleAdd(g_main_context_default(), [](gpointer user_data) {
+ auto* impl = static_cast<AppCoreTaskBase::Impl*>(user_data);
+ UiState state;
+ {
+ std::lock_guard<std::recursive_mutex> lock(impl->GetMutex());
+ state = impl->queue_.front();
+ impl->queue_.pop();
+ }
+ impl->parent_->OnUiEvent(state);
+ return G_SOURCE_REMOVE;
+ }, this);
+}
+
+std::recursive_mutex& AppCoreTaskBase::Impl::GetMutex() const {
+ return mutex_;
+}
+
+AppCoreTaskBase::DeviceOrientationState
+AppCoreTaskBase::Impl::ConvertRotationState(int value) {
+ AppCoreTaskBase::DeviceOrientationState state;
+
+ switch (value) {
+ case AppCoreBase::ROTATION_PORTRAIT_NORMAL:
+ state = AppCoreTaskBase::DEVICE_ORIENTATION_STATE_0;
+ break;
+ case AppCoreBase::ROTATION_PORTRAIT_REVERSE:
+ state = AppCoreTaskBase::DEVICE_ORIENTATION_STATE_180;
+ break;
+ case AppCoreBase::ROTATION_LANDSCAPE_NORMAL:
+ state = AppCoreTaskBase::DEVICE_ORIENTATION_STATE_270;
+ break;
+ case AppCoreBase::ROTATION_LANDSCAPE_REVERSE:
+ state = AppCoreTaskBase::DEVICE_ORIENTATION_STATE_90;
+ break;
+ default:
+ state = AppCoreTaskBase::DEVICE_ORIENTATION_STATE_UNKNOWN;
+ break;
+ }
+
+ return state;
+}
+
+AppCoreTaskBase::LowMemoryState AppCoreTaskBase::Impl::ConvertLowMemoryState(
+ int value) {
+ AppCoreTaskBase::LowMemoryState state;
+
+ switch (value) {
+ case VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL:
+ state = AppCoreTaskBase::LOW_MEMORY_STATE_NORMAL;
+ break;
+ case VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING:
+ state = AppCoreTaskBase::LOW_MEMORY_STATE_SOFT_WARNING;
+ break;
+ case VCONFKEY_SYSMAN_LOW_MEMORY_HARD_WARNING:
+ state = AppCoreTaskBase::LOW_MEMORY_STATE_HARD_WARNING;
+ break;
+ default:
+ state = AppCoreTaskBase::LOW_MEMORY_STATE_UNKNOWN;
+ break;
+ }
+
+ return state;
+}
+
+AppCoreTaskBase::LowBatteryState AppCoreTaskBase::Impl::ConvertLowBatteryState(
+ int value) {
+ AppCoreTaskBase::LowBatteryState state;
+
+ switch (value) {
+ case VCONFKEY_SYSMAN_BAT_POWER_OFF:
+ state = AppCoreTaskBase::LOW_BATTERY_STATE_POWER_OFF;
+ break;
+ case VCONFKEY_SYSMAN_BAT_CRITICAL_LOW:
+ state = AppCoreTaskBase::LOW_BATTERY_STATE_CRITICAL_LOW;
+ break;
+ default:
+ state = AppCoreTaskBase::LOW_BATTERY_STATE_UNKNOWN;
+ break;
+ }
+
+ return state;
+}
+
+AppCoreTaskBase::AppCoreTaskBase() : impl_(new Impl(this)) {}
+
+AppCoreTaskBase::~AppCoreTaskBase() = default;
+
+int AppCoreTaskBase::OnReceive(aul_type type, tizen_base::Bundle b) {
+ return AppCoreBase::OnReceive(type, std::move(b));
+}
+
+int AppCoreTaskBase::OnCreate() {
+ return 0;
+}
+
+int AppCoreTaskBase::OnTerminate() {
+ return AppCoreBase::OnTerminate();
+}
+
+int AppCoreTaskBase::OnControl(tizen_base::Bundle b) {
+ return AppCoreBase::OnControl(std::move(b));
+}
+
+int AppCoreTaskBase::OnTrimMemory() {
+ return AppCoreBase::OnTrimMemory();
+}
+
+void AppCoreTaskBase::OnLoopInit(int argc, char** argv) {
+ impl_->LoopInit(argc, argv);
+}
+
+void AppCoreTaskBase::OnLoopRun() {
+ impl_->LoopRun();
+}
+
+void AppCoreTaskBase::OnLoopExit() {
+ impl_->LoopExit();
+}
+
+void AppCoreTaskBase::OnLoopFinish() {
+ impl_->LoopFinish();
+}
+
+void AppCoreTaskBase::OnLowMemory(LowMemoryState state) {}
+
+void AppCoreTaskBase::OnLowBattery(LowBatteryState state) {}
+
+void AppCoreTaskBase::OnLangChanged(const std::string& lang) {}
+
+void AppCoreTaskBase::OnDeviceOrientationChanged(DeviceOrientationState state) {}
+
+void AppCoreTaskBase::OnRegionChanged(const std::string& region) {}
+
+void AppCoreTaskBase::Run(int argc, char** argv) {
+ impl_->SetSystemEvents();
+ AppCoreBase::Run(argc, argv);
+ impl_->UnsetSystemEvents();
+}
+
+void AppCoreTaskBase::OnUiEvent(UiState state) {}
+
+void AppCoreTaskBase::Post(UiState state) {
+ impl_->Post(state);
+}
+
+} // namespace tizen_cpp
--- /dev/null
+/*
+ * Copyright (c) 2022 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_TASK_BASE_HH_
+#define TIZEN_CPP_APP_CORE_UI_CPP_APP_CORE_TASK_BASE_HH_
+
+#include <memory>
+
+#include <app_core_base.hh>
+#include <interface_app_core_ui_event.hh>
+
+#undef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+
+namespace tizen_cpp {
+
+class EXPORT_API AppCoreTaskBase : public AppCoreBase,
+ public IAppCoreUiEvent {
+ public:
+ enum LowMemoryState {
+ LOW_MEMORY_STATE_UNKNOWN,
+ LOW_MEMORY_STATE_NORMAL,
+ LOW_MEMORY_STATE_SOFT_WARNING,
+ LOW_MEMORY_STATE_HARD_WARNING,
+ };
+
+ enum LowBatteryState {
+ LOW_BATTERY_STATE_UNKNOWN,
+ LOW_BATTERY_STATE_POWER_OFF,
+ LOW_BATTERY_STATE_CRITICAL_LOW,
+ };
+
+ enum DeviceOrientationState {
+ DEVICE_ORIENTATION_STATE_UNKNOWN,
+ DEVICE_ORIENTATION_STATE_0,
+ DEVICE_ORIENTATION_STATE_180,
+ DEVICE_ORIENTATION_STATE_270,
+ DEVICE_ORIENTATION_STATE_90,
+ };
+
+ AppCoreTaskBase();
+ virtual ~AppCoreTaskBase();
+
+ int OnReceive(aul_type type, tizen_base::Bundle b) override;
+ int OnCreate() override;
+ int OnTerminate() override;
+ int OnControl(tizen_base::Bundle b) override;
+
+ int OnTrimMemory() override;
+ void OnLoopInit(int argc, char** argv) override;
+ void OnLoopRun() override;
+ void OnLoopExit() override;
+ void OnLoopFinish() override;
+
+ virtual void OnLowMemory(LowMemoryState state);
+ virtual void OnLowBattery(LowBatteryState state);
+ virtual void OnLangChanged(const std::string& lang);
+ virtual void OnDeviceOrientationChanged(DeviceOrientationState state);
+ virtual void OnRegionChanged(const std::string& region);
+
+ void Run(int argc, char** argv) override;
+
+ void OnUiEvent(UiState state) override;
+ void Post(UiState state) override;
+
+ private:
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+};
+
+} // namespace tizen_cpp
+
+#endif // TIZEN_CPP_APP_CORE_UI_CPP_APP_CORE_TASK_BASE_HH_
#include <list>
#include <memory>
#include <string>
+#include <thread>
#include "app-core-cpp/app_core_base.hh"
#include "app-core-ui-cpp/api/app_core_ui_base.h"
+#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/wayland_handler_private.hh"
#include "common/ecore_handler.hh"
+#include "common/glib_private.hh"
#include "common/log_private.hh"
namespace tizen_cpp {
int FiniWl();
void PluginInit(int argc, char** argv);
void PluginFini();
+ void Run(int argc, char** argv);
+ void Exit();
std::list<std::shared_ptr<WinNode>> winnode_list_;
unsigned int hint_;
IAppCoreUi* core_ui_delegator_ = nullptr;
std::unique_ptr<AppCoreUiDelegator> plugin_delegator_;
std::unique_ptr<AppCoreUiPlugin> plugin_;
+ std::unique_ptr<AppCoreTaskBase> service_;
+ GMainContext* context_ = nullptr;
+ std::thread thread_;
};
AppCoreUiBase::AppCoreUiBase(unsigned int hint)
plugin_->Fini(parent_);
}
-void AppCoreUiBase::Run(int argc, char** argv) {
+void AppCoreUiBase::DoRun(int argc, char** argv) {
SetCoreDelegator(nullptr);
SetLoopDelegator(nullptr);
SetCoreUiDelegator(nullptr);
AppCoreBase::Run(argc, argv);
}
+void AppCoreUiBase::DoExit() {
+ AppCoreBase::Exit();
+}
+
+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<unsigned int>(context_));
+ setenv("TIZEN_GLIB_CONTEXT", env.c_str(), 1);
+
+ thread_ = std::thread([&] {
+ parent_->DoRun(argc, argv);
+ });
+
+ service_->Run(argc, argv);
+
+ if (thread_.joinable())
+ thread_.join();
+
+ setenv("TIZEN_GLIB_CONTEXT", "", 1);
+ g_main_context_unref(context_);
+ context_ = nullptr;
+ return;
+ }
+
+ parent_->DoRun(argc, argv);
+}
+
+void AppCoreUiBase::Impl::Exit() {
+ if (hint_ & HINT_DUAL_THREAD) {
+ GLib::IdleAdd(context_, [](gpointer user_data) {
+ auto* impl = static_cast<AppCoreUiBase::Impl*>(user_data);
+ impl->parent_->DoExit();
+ return G_SOURCE_REMOVE;
+ }, this);
+
+ service_->Exit();
+ return;
+ }
+
+ parent_->DoExit();
+}
+
+void AppCoreUiBase::Run(int argc, char** argv) {
+ impl_->Run(argc, argv);
+}
+
+void AppCoreUiBase::Exit() {
+ impl_->Exit();
+}
+
void AppCoreUiBase::Dispose() {
impl_->handler_->Fini();
impl_->FiniWl();
impl_->PluginFini();
}
+std::unique_ptr<AppCoreTaskBase> AppCoreUiBase::CreateTask() {
+ return std::make_unique<AppCoreTaskBase>();
+}
+
void AppCoreUiBase::Impl::PrepareToSuspend() {
if (parent_->IsBgAllowed() && !parent_->IsSuspended()) {
SuspendedState suspend = SUSPENDED_STATE_WILL_ENTER_SUSPEND;
state_ = AS_PAUSED;
traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:PAUSE");
_D("Call pause callback");
+ if (parent_->GetHint() & HINT_DUAL_THREAD)
+ service_->Post(AppCoreTaskBase::UiState::PAUSED);
+
int ret;
if (core_ui_delegator_)
ret = core_ui_delegator_->OnPause();
LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:start]", appid_.c_str());
traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:RESUME");
_D("Call resume callback");
+ if (parent_->GetHint() & HINT_DUAL_THREAD)
+ service_->Post(AppCoreTaskBase::UiState::RESUMED);
+
parent_->RemoveSuspendTimer();
if (core_ui_delegator_)
core_ui_delegator_->OnResume();
#include <memory>
#include <app_core_base.hh>
+#include <app_core_task_base.hh>
#include <interface_app_core_ui.hh>
#include <interface_window.hh>
constexpr static int HINT_WINDOW_AUTO_CONTROL = 0x10;
constexpr static int HINT_LEGACY_CONTROL = 0x20;
constexpr static int HINT_WINDOW_ID_CONTROL = 0x40;
+ constexpr static int HINT_DUAL_THREAD = 0x80;
AppCoreUiBase(unsigned int hint);
virtual ~AppCoreUiBase();
void SetSystemResourceReclaiming(bool enable);
void Run(int argc, char** argv) override;
void Dispose() override;
+ virtual std::unique_ptr<AppCoreTaskBase> CreateTask();
+ void Exit() override;
protected:
void SetCoreUiDelegator(IAppCoreUi* delegator);
void SetWindowDelegator(IWindow* delegator);
private:
+ void DoRun(int argc, char** argv);
+ void DoExit();
+
+ private:
class Impl;
std::unique_ptr<Impl> impl_;
};
#include <stdexcept>
-#include "common/log_private.hh"
#include "common/ecore_handler.hh"
+#include "common/glib_private.hh"
+#include "common/log_private.hh"
namespace tizen_cpp {
if (flush_timer_ != 0)
return;
- flush_timer_ = g_timeout_add(5000, FlushMemoryCb, this);
+ flush_timer_ = GLib::TimeoutAdd(5000, FlushMemoryCb, this);
}
void EcoreHandler::RemoveFlushTimer() {
if (flush_timer_ == 0)
return;
- g_source_remove(flush_timer_);
+ GLib::SourceRemove(flush_timer_);
flush_timer_ = 0;
}
--- /dev/null
+/*
+ * Copyright (c) 2022 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 "common/glib_private.hh"
+
+namespace tizen_cpp {
+
+guint GLib::IdleAdd(GSourceFunc func, gpointer data) {
+ return IdleAddFull(G_PRIORITY_DEFAULT, g_main_context_get_thread_default(),
+ func, data);
+}
+
+guint GLib::IdleAdd(GMainContext* context, GSourceFunc func, gpointer data) {
+ return IdleAddFull(G_PRIORITY_DEFAULT, context, func, data);
+}
+
+guint GLib::IdleAddFull(guint priority, GMainContext* context,
+ GSourceFunc func, gpointer data) {
+ auto* source = g_idle_source_new();
+ if (source == nullptr)
+ return 0;
+
+ g_source_set_callback(source, func, data, nullptr);
+ g_source_set_priority(source, priority);
+ guint source_id = g_source_attach(source, context);
+ g_source_unref(source);
+ return source_id;
+}
+
+guint GLib::TimeoutAdd(guint interval, GSourceFunc func, gpointer data) {
+ return TimeoutAdd(g_main_context_get_thread_default(), interval, func, data);
+}
+
+guint GLib::TimeoutAdd(GMainContext* context, guint interval,
+ GSourceFunc func, gpointer data) {
+ auto* source = g_timeout_source_new(interval);
+ if (source == nullptr)
+ return 0;
+
+ g_source_set_callback(source, func, data, nullptr);
+ guint source_id = g_source_attach(source, context);
+ g_source_unref(source);
+ return source_id;
+}
+
+void GLib::SourceRemove(guint source_id) {
+ SourceRemove(g_main_context_get_thread_default(), source_id);
+}
+
+void GLib::SourceRemove(GMainContext* context, guint source_id) {
+ auto* source = g_main_context_find_source_by_id(context, source_id);
+ if (source != nullptr && !g_source_is_destroyed(source))
+ g_source_destroy(source);
+}
+
+} // namespace tizen_cpp
--- /dev/null
+/*
+ * Copyright (c) 2022 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_COMMON_GLIB_PRIVATE_HH_
+#define TIZEN_CPP_COMMON_GLIB_PRIVATE_HH_
+
+#include <glib.h>
+
+namespace tizen_cpp {
+
+class GLib {
+ public:
+ static guint IdleAdd(GSourceFunc func, gpointer data);
+ static guint IdleAdd(GMainContext* context, GSourceFunc func, gpointer data);
+ static guint IdleAddFull(guint priority, GMainContext* context,
+ GSourceFunc func, gpointer data);
+ static guint TimeoutAdd(guint interval, GSourceFunc func, gpointer data);
+ static guint TimeoutAdd(GMainContext* context, guint interval,
+ GSourceFunc func, gpointer data);
+ static void SourceRemove(guint source_id);
+ static void SourceRemove(GMainContext* context, guint source_id);
+};
+
+} // namespace tizen_cpp
+
+#endif // TIZEN_CPP_COMMON_GLIB_PRIVATE_HH_