tizen-core: Apply tizen-core to ecore timer 29/306029/23
authorjusung son <jusung07.son@samsung.com>
Thu, 15 Feb 2024 08:27:20 +0000 (17:27 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Thu, 28 Mar 2024 01:12:49 +0000 (10:12 +0900)
Change-Id: Ib2d5a127f16cb7abfed941bdc7f869bf941b367a
Signed-off-by: jusung son <jusung07.son@samsung.com>
src/lib/ecore/ecore_timer.c
src/lib/ecore/meson.build
src/lib/ecore/tizen-core/tcore_timer.cc [new file with mode: 0644]
src/lib/ecore/tizen-core/tcore_timer.h [new file with mode: 0644]

index 8740b1a..a79ffee 100644 (file)
 #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));
 }
index 40ec5c1..d4b2541 100644 (file)
@@ -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 (file)
index 0000000..8946cd9
--- /dev/null
@@ -0,0 +1,315 @@
+#include "tcore_timer.h"
+
+#include <tizen_core.h>
+
+#include <chrono>
+#include <memory>
+
+#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<void*>(data)) {}
+
+    bool Tick() {
+      SetNextTick();
+
+      if (!cb_) return false;
+
+      return static_cast<bool>(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<TimerTask*>(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<std::chrono::milliseconds>(
+                       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<std::chrono::milliseconds>(
+                           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<Ecore_Timer*>(
+      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<TimerManager::TimerTask*>(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<TimerManager::TimerTask*>(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<TimerManager::TimerTask*>(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<TimerManager::TimerTask*>(timer), delay);
+}
+
+void tcore_timer_reset(Efl_Loop_Timer_Data* timer) {
+  if (!timer) {
+    _E("timer is null");
+    return;
+  }
+
+  manager.Reset(reinterpret_cast<TimerManager::TimerTask*>(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<TimerManager::TimerTask*>(timer));
+}
+
+void tcore_timer_freeze(Ecore_Timer* timer) {
+  if (!timer) {
+    _E("timer is null");
+    return;
+  }
+
+  manager.Freeze(reinterpret_cast<TimerManager::TimerTask*>(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<TimerManager::TimerTask*>(timer));
+}
+
+void tcore_timer_thaw(Ecore_Timer* timer) {
+  if (!timer) {
+    _E("timer is null");
+    return;
+  }
+
+  manager.Thaw(reinterpret_cast<TimerManager::TimerTask*>(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 (file)
index 0000000..810d7cb
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef _TCORE_TIMER_H
+#define _TCORE_TIMER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <Eo.h>
+#include <stdbool.h>
+
+#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 */