From 550021294c35ef8ec73c53532775d8ac8580e1ff Mon Sep 17 00:00:00 2001 From: jusung son Date: Thu, 15 Feb 2024 17:27:20 +0900 Subject: [PATCH] tizen-core: Apply tizen-core to ecore timer Change-Id: Ib2d5a127f16cb7abfed941bdc7f869bf941b367a Signed-off-by: jusung son --- src/lib/ecore/ecore_timer.c | 109 +++++++++++ src/lib/ecore/meson.build | 3 +- src/lib/ecore/tizen-core/tcore_timer.cc | 315 ++++++++++++++++++++++++++++++++ src/lib/ecore/tizen-core/tcore_timer.h | 41 +++++ 4 files changed, 467 insertions(+), 1 deletion(-) create mode 100644 src/lib/ecore/tizen-core/tcore_timer.cc create mode 100644 src/lib/ecore/tizen-core/tcore_timer.h diff --git a/src/lib/ecore/ecore_timer.c b/src/lib/ecore/ecore_timer.c index 8740b1a..a79ffee 100644 --- a/src/lib/ecore/ecore_timer.c +++ b/src/lib/ecore/ecore_timer.c @@ -10,6 +10,11 @@ #include "Ecore.h" #include "ecore_private.h" +#ifdef USE_TIZEN_CORE +#include "tizen-core/tcore_timer.h" +#endif // USE_TIZEN_CORE + + #define MY_CLASS EFL_LOOP_TIMER_CLASS #define MY_CLASS_NAME "Efl_Loop_Timer" @@ -188,6 +193,14 @@ EFL_CALLBACKS_ARRAY_DEFINE(legacy_timer, EAPI Ecore_Timer * ecore_timer_add(double in, Ecore_Task_Cb func, const void *data) { +#ifdef USE_TIZEN_CORE + if (tcore_ready()) + { + if (in < 0.05f) in = 0.05f; + return tcore_timer_add(in * 1000, func, data); + } +#endif // USE_TIZEN_CORE + Ecore_Timer_Legacy *legacy; Eo *timer; @@ -212,6 +225,14 @@ ecore_timer_add(double in, Ecore_Task_Cb func, const void *data) EAPI Ecore_Timer * ecore_timer_loop_add(double in, Ecore_Task_Cb func, const void *data) { +#ifdef USE_TIZEN_CORE + if (tcore_ready()) + { + if (in < 0.05f) in = 0.05f; + return tcore_timer_add(in * 1000, func, data); + } +#endif // USE_TIZEN_CORE + Ecore_Timer_Legacy *legacy; Eo *timer; @@ -237,6 +258,13 @@ ecore_timer_loop_add(double in, Ecore_Task_Cb func, const void *data) EAPI void * ecore_timer_del(Ecore_Timer *timer) { +#ifdef USE_TIZEN_CORE + if (tcore_ready()) + { + return tcore_timer_del(timer); + } +#endif // USE_TIZEN_CORE + void *data; if (!timer) return NULL; @@ -261,6 +289,15 @@ ecore_timer_del(Ecore_Timer *timer) EOLIAN static void _efl_loop_timer_timer_interval_set(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer, double in) { +#ifdef USE_TIZEN_CORE + if (tcore_ready()) + { + if (in < 0.05f) in = 0.05f; + tcore_timer_set_interval(timer, in * 1000); + return; + } +#endif // USE_TIZEN_CORE + if (in < 0.0) in = 0.0; timer->in = in; } @@ -268,18 +305,43 @@ _efl_loop_timer_timer_interval_set(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *tim EOLIAN static double _efl_loop_timer_timer_interval_get(const Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer) { +#ifdef USE_TIZEN_CORE + if (tcore_ready()) + { + double ret = tcore_timer_get_interval(timer); + + return ret / 1000.0; + } +#endif // USE_TIZEN_CORE + return timer->in; } EOLIAN static void _efl_loop_timer_timer_delay(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *pd, double add) { + #ifdef USE_TIZEN_CORE + if (tcore_ready()) + { + tcore_timer_set_delay(pd, add * 1000); + return; + } +#endif // USE_TIZEN_CORE + _efl_loop_timer_util_delay(pd, add); } EOLIAN static void _efl_loop_timer_timer_reset(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer) { +#ifdef USE_TIZEN_CORE + if (tcore_ready()) + { + tcore_timer_reset(timer); + return; + } +#endif // USE_TIZEN_CORE + double now, add; if (!timer->loop_data) return; @@ -301,6 +363,14 @@ _efl_loop_timer_timer_reset(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer) EOLIAN static void _efl_loop_timer_timer_loop_reset(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer) { +#ifdef USE_TIZEN_CORE + if (tcore_ready()) + { + tcore_timer_reset(timer); + return; + } +#endif // USE_TIZEN_CORE + double now, add; if (!timer->loop_data) return; @@ -322,6 +392,14 @@ _efl_loop_timer_timer_loop_reset(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer EOLIAN static double _efl_loop_timer_time_pending_get(const Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer) { +#ifdef USE_TIZEN_CORE + if (tcore_ready()) + { + double ret = tcore_timer_get_pending_time(timer); + return ret / 1000.0; + } +#endif // USE_TIZEN_CORE + double now, ret = 0.0; now = ecore_time_get(); @@ -333,6 +411,14 @@ _efl_loop_timer_time_pending_get(const Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data EAPI void ecore_timer_freeze(Ecore_Timer *timer) { +#ifdef USE_TIZEN_CORE + if (tcore_ready()) + { + tcore_timer_freeze(timer); + return; + } +#endif // USE_TIZEN_CORE + ECORE_TIMER_CHECK(timer); efl_event_freeze(timer); } @@ -364,6 +450,13 @@ _efl_loop_timer_efl_object_event_freeze(Eo *obj, Efl_Loop_Timer_Data *timer) EAPI Eina_Bool ecore_timer_freeze_get(Ecore_Timer *timer) { +#ifdef USE_TIZEN_CORE + if (tcore_ready()) + { + return tcore_timer_is_running(timer); + } +#endif // USE_TIZEN_CORE + EINA_MAIN_LOOP_CHECK_RETURN_VAL(EINA_FALSE); return !!efl_event_freeze_count_get(timer); } @@ -377,6 +470,13 @@ _efl_loop_timer_efl_object_event_freeze_count_get(const Eo *obj EINA_UNUSED, Efl EAPI void ecore_timer_thaw(Ecore_Timer *timer) { +#ifdef USE_TIZEN_CORE + if (tcore_ready()) + { + tcore_timer_thaw(timer); + return; + } +#endif // USE_TIZEN_CORE ECORE_TIMER_CHECK(timer); efl_event_thaw(timer); } @@ -485,6 +585,10 @@ _efl_loop_timer_efl_object_parent_set(Eo *obj, Efl_Loop_Timer_Data *pd, Efl_Obje { Eina_Inlist *first; +#ifdef USE_TIZEN_CORE + if (tcore_ready()) { return; } +#endif // USE_TIZEN_CORE + efl_parent_set(efl_super(obj, EFL_LOOP_TIMER_CLASS), parent); if ((!pd->constructed) || (!pd->finalized)) return; @@ -521,6 +625,11 @@ _efl_loop_timer_efl_object_parent_set(Eo *obj, Efl_Loop_Timer_Data *pd, Efl_Obje EOLIAN static void _efl_loop_timer_efl_object_destructor(Eo *obj, Efl_Loop_Timer_Data *pd) { + +#ifdef USE_TIZEN_CORE + if (tcore_ready()) { return; } +#endif // USE_TIZEN_CORE + _efl_loop_timer_util_loop_clear(pd); efl_destructor(efl_super(obj, MY_CLASS)); } diff --git a/src/lib/ecore/meson.build b/src/lib/ecore/meson.build index 40ec5c1..d4b2541 100644 --- a/src/lib/ecore/meson.build +++ b/src/lib/ecore/meson.build @@ -211,7 +211,8 @@ if get_option('tizen-core') == true ecore_src += files([ 'tizen-core/tcore.cc', 'tizen-core/tcore_events.cc', - 'tizen-core/tcore_idler.cc' + 'tizen-core/tcore_idler.cc', + 'tizen-core/tcore_timer.cc' ]) config_h.set('USE_TIZEN_CORE', '1') endif diff --git a/src/lib/ecore/tizen-core/tcore_timer.cc b/src/lib/ecore/tizen-core/tcore_timer.cc new file mode 100644 index 0000000..8946cd9 --- /dev/null +++ b/src/lib/ecore/tizen-core/tcore_timer.cc @@ -0,0 +1,315 @@ +#include "tcore_timer.h" + +#include + +#include +#include + +#include "log_private.h" +#include "tcore.h" + +namespace { + +class TimerManager { + public: + class TimerTask { + public: + TimerTask(unsigned int interval, Ecore_Task_Cb cb, const void* data) + : interval_(interval), + cb_(cb), + data_(const_cast(data)) {} + + bool Tick() { + SetNextTick(); + + if (!cb_) return false; + + return static_cast(cb_(data_)); + } + + void Start() { + tizen_core_add_timer(tcore_get_core(), interval_, TimerCb, this, + &source_); + SetNextTick(); + } + + void* Stop() { + if (source_) { + tizen_core_remove_source(tcore_get_core(), source_); + source_ = nullptr; + } + + new_interval_ = 0; + delay_ = 0; + pending_time_ = 0; + next_tick_ = std::chrono::milliseconds(0); + return data_; + } + + void Reschedule() { + if (delay_) { + if (new_interval_ == 0) new_interval_ = interval_; + + interval_ = delay_; + delay_ = 0; + + Stop(); + Start(); + + return; + } + + if (new_interval_) { + interval_ = new_interval_; + new_interval_ = 0; + + Stop(); + Start(); + } + } + + void SetInterval(unsigned int interval) { interval_ = interval; } + + unsigned int GetInterval() const { return interval_; } + + void SetNewInterval(unsigned int interval) { new_interval_ = interval; } + + unsigned int GetNewInterval() const { return new_interval_; } + + void SetDelay(unsigned int delay) { delay_ = delay; } + + unsigned int GetDelay() const { return delay_; } + + void SetFreezePendingTime(unsigned int pending_time) { + pending_time_ = pending_time; + } + + unsigned int GetFreezePendingTime() const { return pending_time_; } + + bool isRunning() const { return source_ ? true : false; } + + std::chrono::milliseconds GetNextTick() const { return next_tick_; } + + private: + static bool TimerCb(void* user_data) { + auto* timer = static_cast(user_data); + unsigned int delay = timer->GetDelay(); + + timer->Reschedule(); + + if (delay != 0) return false; + + return timer->Tick(); + } + + void SetNextTick() { + auto now = std::chrono::steady_clock::now(); + next_tick_ = std::chrono::duration_cast( + now.time_since_epoch()) + + std::chrono::milliseconds(interval_); + } + + private: + unsigned int interval_; + Ecore_Task_Cb cb_; + void* data_; + tizen_core_source_h source_ = nullptr; + unsigned int new_interval_ = 0; + unsigned int delay_ = 0; + std::chrono::milliseconds next_tick_ = std::chrono::milliseconds(0); + bool frozen = false; + unsigned int pending_time_ = 0; + }; + + TimerManager() = default; + + ~TimerManager() = default; + + TimerTask* AddTimer(unsigned int interval, Ecore_Task_Cb cb, + const void* data) { + TimerManager::TimerTask* timer; + + try { + timer = new TimerManager::TimerTask(interval, cb, data); + timer->Start(); + } catch (const std::bad_alloc& e) { + _E("Allocation failed: %s", e.what()); + return nullptr; + } + + return timer; + } + + void* DelTimer(TimerTask* timer) { + void* data = timer->Stop(); + delete timer; + + return data; + } + + void SetInterval(TimerTask* timer, unsigned int interval) { + if (timer->GetInterval() == interval) return; + + timer->SetNewInterval(interval); + } + + unsigned int GetInterval(TimerTask* timer) { + unsigned int ret = timer->GetNewInterval(); + + if (ret) return ret; + + return timer->GetInterval(); + } + + void SetDelay(TimerTask* timer, unsigned int delay) { + if (!timer->isRunning()) { + timer->SetFreezePendingTime(timer->GetFreezePendingTime() + delay); + return; + } + timer->SetDelay(delay); + } + + unsigned int GetPendingTime(TimerTask* timer) { + if (!timer->isRunning()) return timer->GetFreezePendingTime(); + + auto now = std::chrono::steady_clock::now(); + auto pendingTime = timer->GetNextTick() - + std::chrono::duration_cast( + now.time_since_epoch()); + + return pendingTime.count(); + } + + void Freeze(TimerTask* timer) { + if (!timer->isRunning()) return; + + timer->Stop(); + timer->SetFreezePendingTime(GetPendingTime(timer)); + } + + void Thaw(TimerTask* timer) { + if (timer->isRunning()) return; + + timer->SetNewInterval(timer->GetInterval()); + timer->SetInterval(timer->GetFreezePendingTime()); + timer->SetFreezePendingTime(0); + timer->Start(); + } + + bool IsRunning(TimerTask* timer) { return timer->isRunning(); } + + void Reset(TimerTask* timer) { + if (timer->isRunning()) { + unsigned int new_interval = timer->GetNewInterval(); + if (new_interval != 0) { + timer->SetNewInterval(0); + timer->SetInterval(new_interval); + } + timer->SetDelay(0); + timer->Stop(); + timer->Start(); + } else { + timer->SetFreezePendingTime(timer->GetInterval()); + } + } +}; + +TimerManager manager; + +} // namespace + +Ecore_Timer* tcore_timer_add(unsigned int interval, Ecore_Task_Cb callback, + const void* user_data) { + if (!callback) { + _E("callback is null"); + return nullptr; + } + + return reinterpret_cast( + manager.AddTimer(interval, callback, user_data)); +} + +void* tcore_timer_del(Ecore_Timer* timer) { + if (!timer) { + _E("timer is null"); + return nullptr; + } + + return manager.DelTimer(reinterpret_cast(timer)); +} + +void tcore_timer_set_interval(Efl_Loop_Timer_Data* timer, + unsigned int interval) { + if (!timer) { + _E("timer is null"); + return; + } + + manager.SetInterval(reinterpret_cast(timer), + interval); +} + +unsigned int tcore_timer_get_interval(Efl_Loop_Timer_Data* timer) { + if (!timer) { + _E("timer is null"); + return 0; + } + + return manager.GetInterval(reinterpret_cast(timer)); +} + +void tcore_timer_set_delay(Efl_Loop_Timer_Data* timer, unsigned int delay) { + if (!timer) { + _E("timer is null"); + return; + } + + manager.SetDelay(reinterpret_cast(timer), delay); +} + +void tcore_timer_reset(Efl_Loop_Timer_Data* timer) { + if (!timer) { + _E("timer is null"); + return; + } + + manager.Reset(reinterpret_cast(timer)); +} + +unsigned int tcore_timer_get_pending_time(Efl_Loop_Timer_Data* timer) { + if (!timer) { + _E("timer is null"); + return 0; + } + + return manager.GetPendingTime( + reinterpret_cast(timer)); +} + +void tcore_timer_freeze(Ecore_Timer* timer) { + if (!timer) { + _E("timer is null"); + return; + } + + manager.Freeze(reinterpret_cast(timer)); +} + +Eina_Bool tcore_timer_is_running(Ecore_Timer* timer) { + if (!timer) { + _E("timer is null"); + return false; + } + + return (Eina_Bool)manager.IsRunning( + reinterpret_cast(timer)); +} + +void tcore_timer_thaw(Ecore_Timer* timer) { + if (!timer) { + _E("timer is null"); + return; + } + + manager.Thaw(reinterpret_cast(timer)); +} diff --git a/src/lib/ecore/tizen-core/tcore_timer.h b/src/lib/ecore/tizen-core/tcore_timer.h new file mode 100644 index 0000000..810d7cb --- /dev/null +++ b/src/lib/ecore/tizen-core/tcore_timer.h @@ -0,0 +1,41 @@ +#ifndef _TCORE_TIMER_H +#define _TCORE_TIMER_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include + +#include "../Ecore.h" +#include "../ecore_private.h" +#include "tcore.h" + +Ecore_Timer* tcore_timer_add(unsigned int interval, Ecore_Task_Cb callback, + const void* user_data); + +void* tcore_timer_del(Ecore_Timer* timer); + +void tcore_timer_set_interval(Efl_Loop_Timer_Data* timer, + unsigned int interval); + +unsigned int tcore_timer_get_interval(Efl_Loop_Timer_Data* timer); + +void tcore_timer_set_delay(Efl_Loop_Timer_Data* timer, unsigned int delay); + +void tcore_timer_reset(Efl_Loop_Timer_Data* timer); + +unsigned int tcore_timer_get_pending_time(Efl_Loop_Timer_Data* timer); + +void tcore_timer_freeze(Ecore_Timer* timer); + +Eina_Bool tcore_timer_is_running(Ecore_Timer* timer); + +void tcore_timer_thaw(Ecore_Timer* timer); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _TCORE_TIMER_H */ -- 2.7.4