Refactor tcore 76/317576/10
authorpjh9216 <jh9216.park@samsung.com>
Fri, 3 Jan 2025 08:22:07 +0000 (17:22 +0900)
committerpjh9216 <jh9216.park@samsung.com>
Mon, 6 Jan 2025 07:08:18 +0000 (16:08 +0900)
Change-Id: Ief2d505b76db6d05e47762ddc847e73923a78006
Signed-off-by: pjh9216 <jh9216.park@samsung.com>
src/tizen-core/interface_loop.h
src/tizen-core/interface_source.h
src/tizen-core/source.cc
src/tizen-core/source.h
src/tizen-core/stub.cc
src/tizen-core/task.cc
src/tizen-core/task.h

index ae76ca86bc49e03b5ab4a7938690fe192809e733..fe8438b4b4ff93c19a62a9c4d9ad5c1b3c5eefd7 100644 (file)
@@ -33,10 +33,11 @@ class EXPORT_API ILoop {
   virtual void Run() = 0;
   virtual void Quit() = 0;
   virtual bool IsRunning() const = 0;
-  virtual std::shared_ptr<ISource> AddIdleJob(std::function<bool()> cb) = 0;
-  virtual std::shared_ptr<ISource> AddTimer(unsigned int interval,
+  virtual std::shared_ptr<ISource>& AddIdleJob(std::function<bool()> cb) = 0;
+  virtual std::shared_ptr<ISource>& AddTimer(unsigned int interval,
                                             std::function<bool()> cb) = 0;
   virtual void RemoveSource(std::shared_ptr<ISource> source) = 0;
+  virtual std::shared_ptr<ISource>& AddManagedSource(std::shared_ptr<ISource> source) = 0;
   virtual void AddSource(std::shared_ptr<ISource> source) = 0;
 };
 
index 8ca980797db5d527981d49f86d604e58a4b74995..1eaaae9a3666f6445b44c16f0c035418e6b86e65 100644 (file)
@@ -33,8 +33,6 @@ class EXPORT_API ISource {
   virtual void Attach(const std::shared_ptr<Context>& context) = 0;
   virtual void AddPoll(std::shared_ptr<PollFd> poll_fd) = 0;
   virtual void RemovePoll(const std::shared_ptr<PollFd>& poll_fd) = 0;
-  virtual void RefSelf() = 0;
-  virtual void UnrefSelf() = 0;
   virtual bool IsDisposing() const = 0;
   virtual void Dispose() = 0;
 };
index 9957bb7f2b239e96993b32691128c3117e7ed891..6414433b270a676f92fed0d74195bde44f915098 100644 (file)
@@ -133,16 +133,6 @@ bool Source::IsAttached() const { return attached_; }
 
 GSource* Source::GetHandle() const { return handle_; }
 
-void Source::RefSelf() {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  if (!self_) self_ = shared_from_this();
-}
-
-void Source::UnrefSelf() {
-  std::lock_guard<std::recursive_mutex> lock(GetMutex());
-  self_.reset();
-}
-
 void Source::SetPriority(int priority) {
   g_source_set_priority(handle_, priority);
 }
index 7a83b3f6e73aee302620e5c310ecd3e90a71a4bf..7871abce6c328aee46fae37174368deb7138bba7 100644 (file)
@@ -47,8 +47,6 @@ class EXPORT_API Source : public ISource,
   bool IsDisposing() const override;
   void Dispose() override;
   GSource* GetHandle() const;
-  void RefSelf() override;
-  void UnrefSelf() override;
   void SetPriority(int priority);
 
   virtual bool OnSourcePrepare(int* timeout);
@@ -68,7 +66,6 @@ class EXPORT_API Source : public ISource,
   std::atomic<bool> disposing_{false};
   GSource* handle_ = nullptr;
   bool attached_ = false;
-  std::shared_ptr<Source> self_;
   std::list<std::shared_ptr<PollFd>> poll_fds_;
   mutable std::recursive_mutex mutex_;
 };
index 2f0aeb7273ec65e613d4e668e8d1d7128b35990a..6f05fee87c2630dd99a552721478e600b64b0911 100644 (file)
  * limitations under the License.
  */
 
-#include "tizen-core/include/tizen_core.h"
-
 #include <atomic>
 #include <stdexcept>
 
-#include "tizen-core/include/tizen_core_internal.h"
 #include "tizen-core/context_manager.h"
+#include "tizen-core/include/tizen_core.h"
+#include "tizen-core/include/tizen_core_internal.h"
 #include "tizen-core/log_private.h"
-#include "tizen-core/task.h"
 #include "tizen-core/source.h"
+#include "tizen-core/task.h"
 #include "tizen-core/unix_signal.h"
 
 #undef EXPORT
-#define EXPORT __attribute__ ((visibility("default")))
+#define EXPORT __attribute__((visibility("default")))
 
 #undef API
 #define API extern "C" EXPORT
@@ -70,22 +69,19 @@ class SourceExt : public tizen_core::Source {
   }
 
   bool OnSourceCheck() override {
-    if (check_cb_ != nullptr)
-      return check_cb_(this, check_data_);
+    if (check_cb_ != nullptr) return check_cb_(this, check_data_);
 
     return false;
   }
 
   bool OnSourceDispatch() override {
-    if (dispatch_cb_ != nullptr)
-      return dispatch_cb_(this, dispatch_data_);
+    if (dispatch_cb_ != nullptr) return dispatch_cb_(this, dispatch_data_);
 
     return false;
   }
 
   void OnSourceFinalize() override {
-    if (finalize_cb_ != nullptr)
-      finalize_cb_(this, finalize_data_);
+    if (finalize_cb_ != nullptr) finalize_cb_(this, finalize_data_);
   }
   // LCOV_EXCL_STOP
 
@@ -109,10 +105,7 @@ API void tizen_core_init(void) {
 
     try {
       auto handle = tizen_core::Task::Create("main", false);
-      if (handle == nullptr)
-        _E("Out of memory");
-      else
-        handle->RefSelf();
+      if (handle == nullptr) _E("Out of memory");
     } catch (const std::invalid_argument& e) {
       _E("Exception occurs. error(%s)", e.what());
     }
@@ -120,18 +113,9 @@ API void tizen_core_init(void) {
 }
 
 API void tizen_core_shutdown(void) {
-  if (tizen_core_ref <= 0)
-    return;
+  if (tizen_core_ref <= 0) return;
 
   if (tizen_core_ref == 1) {
-    auto context = tizen_core::ContextManager::GetInst().Find("main");
-    if (context) {
-      auto handle =
-          std::static_pointer_cast<tizen_core::Task>(context->GetLoop());
-      if (handle->GetRefCount() == 1) handle->Dispose();
-      handle->UnrefSelf();
-    }
-
     tizen_core::UnixSignal::Shutdown();
     tizen_core::ContextManager::GetInst().DisposeAll();
   }
@@ -139,9 +123,7 @@ API void tizen_core_shutdown(void) {
   --tizen_core_ref;
 }
 
-API bool tizen_core_ready(void) {
-  return tizen_core_ref > 0;
-}
+API bool tizen_core_ready(void) { return tizen_core_ref > 0; }
 
 API int tizen_core_task_create(const char* name, bool use_thread,
                                tizen_core_task_h* task) {
@@ -150,29 +132,28 @@ API int tizen_core_task_create(const char* name, bool use_thread,
     return TIZEN_CORE_ERROR_INVALID_PARAMETER;
   }
 
-  if (!tizen_core_ready())
-    return TIZEN_CORE_ERROR_INVALID_CONTEXT;
+  if (!tizen_core_ready()) return TIZEN_CORE_ERROR_INVALID_CONTEXT;
 
   if (strcmp(name, "main") == 0 && !use_thread) {
     auto context = tizen_core::ContextManager::GetInst().Find("main");
     if (context) {
-      auto handle =
-          std::static_pointer_cast<tizen_core::Task>(context->GetLoop());
-      handle->RefSelf();
-      *task = static_cast<tizen_core_task_h>(handle.get());
+      auto loop = context->GetLoop();
+      auto* handle = new std::shared_ptr<tizen_core::Task>(
+          std::static_pointer_cast<tizen_core::Task>(loop));
+      *task = handle;
       return TIZEN_CORE_ERROR_NONE;
     }
   }
 
   try {
-    auto handle = tizen_core::Task::Create(name, use_thread);
-    if (handle == nullptr) {
+    auto t = tizen_core::Task::Create(name, use_thread);
+    if (!t) {
       _E("Out of memory");                    // LCOV_EXCL_LINE
       return TIZEN_CORE_ERROR_OUT_OF_MEMORY;  // LCOV_EXCL_LINE
     }
 
-    handle->RefSelf();
-    *task = static_cast<tizen_core_task_h>(handle.get());
+    auto* handle = new std::shared_ptr<tizen_core::Task>(t);
+    *task = handle;
   } catch (const std::invalid_argument& e) {
     _E("Exception occurs. error(%s)", e.what());
     return TIZEN_CORE_ERROR_INVALID_PARAMETER;
@@ -187,10 +168,11 @@ API int tizen_core_task_destroy(tizen_core_task_h task) {
     return TIZEN_CORE_ERROR_INVALID_PARAMETER;
   }
 
-  auto* handle = static_cast<tizen_core::Task*>(task);
-  if (handle->IsRunning()) handle->Quit();
-  if (handle->GetRefCount() == 1) handle->Dispose();
-  handle->UnrefSelf();
+  auto* handle = static_cast<std::shared_ptr<tizen_core::Task>*>(task);
+  if ((*handle)->IsRunning()) (*handle)->Quit();
+  (*handle)->Dispose();
+  delete handle;
+
   return TIZEN_CORE_ERROR_NONE;
 }
 
@@ -200,8 +182,8 @@ API int tizen_core_task_run(tizen_core_task_h task) {
     return TIZEN_CORE_ERROR_INVALID_PARAMETER;
   }
 
-  auto* handle = static_cast<tizen_core::Task*>(task);
-  handle->Run();
+  auto* handle = static_cast<std::shared_ptr<tizen_core::Task>*>(task);
+  (*handle)->Run();
   return TIZEN_CORE_ERROR_NONE;
 }
 
@@ -211,8 +193,8 @@ API int tizen_core_task_is_running(tizen_core_task_h task, bool* running) {
     return TIZEN_CORE_ERROR_INVALID_PARAMETER;
   }
 
-  auto* handle = static_cast<tizen_core::Task*>(task);
-  *running = handle->IsRunning();
+  auto* handle = static_cast<std::shared_ptr<tizen_core::Task>*>(task);
+  *running = (*handle)->IsRunning();
   return TIZEN_CORE_ERROR_NONE;
 }
 
@@ -222,8 +204,8 @@ API int tizen_core_task_quit(tizen_core_task_h task) {
     return TIZEN_CORE_ERROR_INVALID_PARAMETER;
   }
 
-  auto* handle = static_cast<tizen_core::Task*>(task);
-  handle->Quit();
+  auto* handle = static_cast<std::shared_ptr<tizen_core::Task>*>(task);
+  (*handle)->Quit();
   return TIZEN_CORE_ERROR_NONE;
 }
 
@@ -234,7 +216,9 @@ API int tizen_core_task_get_tizen_core(tizen_core_task_h task,
     return TIZEN_CORE_ERROR_INVALID_PARAMETER;
   }
 
-  *core = static_cast<tizen_core_h>(task);
+  auto* handle = static_cast<std::shared_ptr<tizen_core::Task>*>(task);
+
+  *core = static_cast<tizen_core_h>((*handle).get());
   return TIZEN_CORE_ERROR_NONE;
 }
 
@@ -244,8 +228,7 @@ API int tizen_core_find(const char* name, tizen_core_h* core) {
     return TIZEN_CORE_ERROR_INVALID_PARAMETER;
   }
 
-  if (!tizen_core_ready())
-    return TIZEN_CORE_ERROR_INVALID_CONTEXT;
+  if (!tizen_core_ready()) return TIZEN_CORE_ERROR_INVALID_CONTEXT;
 
   auto context = tizen_core::ContextManager::GetInst().Find(name);
   if (context == nullptr) {
@@ -263,8 +246,7 @@ API int tizen_core_find_from_this_thread(tizen_core_h* core) {
     return TIZEN_CORE_ERROR_INVALID_PARAMETER;
   }
 
-  if (!tizen_core_ready())
-    return TIZEN_CORE_ERROR_INVALID_CONTEXT;
+  if (!tizen_core_ready()) return TIZEN_CORE_ERROR_INVALID_CONTEXT;
 
   auto context = tizen_core::ContextManager::GetInst().FindFromThisThread();
   if (context == nullptr) {
@@ -284,13 +266,13 @@ API int tizen_core_add_idle_job(tizen_core_h core, tizen_core_task_cb callback,
   }
 
   auto* task = static_cast<tizen_core::Task*>(core);
-  auto idle_source = task->AddIdleJob([=]() { return callback(user_data); });
+  auto& idle_source = task->AddIdleJob([=]() { return callback(user_data); });
   if (idle_source == nullptr) {
     _E("Failed to add idle job");           // LCOV_EXCL_LINE
     return TIZEN_CORE_ERROR_OUT_OF_MEMORY;  // LCOV_EXCL_LINE
   }
 
-  *source = idle_source.get();
+  *source = &idle_source;
   return TIZEN_CORE_ERROR_NONE;
 }
 
@@ -303,14 +285,14 @@ API int tizen_core_add_timer(tizen_core_h core, unsigned int interval,
   }
 
   auto* task = static_cast<tizen_core::Task*>(core);
-  auto timer_source =
+  auto& timer_source =
       task->AddTimer(interval, [=]() { return callback(user_data); });
   if (timer_source == nullptr) {
     _E("Failed to add timer");              // LCOV_EXCL_LINE
     return TIZEN_CORE_ERROR_OUT_OF_MEMORY;  // LCOV_EXCL_LINE
   }
 
-  *source = timer_source.get();
+  *source = &timer_source;
   return TIZEN_CORE_ERROR_NONE;
 }
 
@@ -329,15 +311,13 @@ API int tizen_core_add_channel(tizen_core_h core,
       static_cast<tizen_core::channel::Receiver<void*>*>(receiver);
   auto channel_source = task->AddChannel<void*>(
       channel_receiver->shared_from_this(),
-      [callback, user_data](auto object) {
-        callback(&object, user_data);
-      });
+      [callback, user_data](auto object) { callback(&object, user_data); });
   if (channel_source == nullptr) {
     _E("Failed to add channel");            // LCOV_EXCL_LINE
     return TIZEN_CORE_ERROR_OUT_OF_MEMORY;  // LCOV_EXCL_LINE
   }
 
-  *source = channel_source.get();
+  *source = new std::shared_ptr<tizen_core::ISource>(channel_source);
   return TIZEN_CORE_ERROR_NONE;
 }
 
@@ -362,7 +342,7 @@ API int tizen_core_add_event(tizen_core_h core, tizen_core_event_h event,
     return TIZEN_CORE_ERROR_OUT_OF_MEMORY;  // LCOV_EXCL_LINE
   }
 
-  *source = event_source.get();
+  *source = new std::shared_ptr<tizen_core::ISource>(event_source);
   return TIZEN_CORE_ERROR_NONE;
 }
 
@@ -388,8 +368,9 @@ API int tizen_core_add_source(tizen_core_h core, tizen_core_source_h source) {
   }
 
   auto* task = static_cast<tizen_core::Task*>(core);
-  auto* core_source = static_cast<tizen_core::Source*>(source);
-  task->AddSource(core_source->shared_from_this());
+  auto* core_source =
+      static_cast<std::shared_ptr<tizen_core::ISource>*>(source);
+  task->AddSource(*core_source);
   return TIZEN_CORE_ERROR_NONE;
 }
 
@@ -400,28 +381,31 @@ API int tizen_core_remove_source(tizen_core_h core,
     return TIZEN_CORE_ERROR_INVALID_PARAMETER;
   }
 
-  auto* core_source = static_cast<tizen_core::Source*>(source);
+  auto* isource = static_cast<std::shared_ptr<tizen_core::ISource>*>(source);
+  auto core_source = std::static_pointer_cast<tizen_core::Source>(*isource);
+
   if (!core_source->IsAttached()) {
     _E("Source(%p) is not attached", source);
     return TIZEN_CORE_ERROR_INVALID_CONTEXT;
   }
 
   auto* task = static_cast<tizen_core::Task*>(core);
-  task->RemoveSource(core_source->shared_from_this());
+  task->RemoveSource(*isource);
+  delete isource;
+
   return TIZEN_CORE_ERROR_NONE;
 }
 
 // LCOV_EXCL_START
-API int tizen_core_set_cpu_boosting(
-    tizen_core_h core, tizen_core_cpu_boosting_level_e level) {
+API int tizen_core_set_cpu_boosting(tizen_core_h core,
+                                    tizen_core_cpu_boosting_level_e level) {
   if (core == nullptr) {
     _E("Invalid parameter");
     return TIZEN_CORE_ERROR_INVALID_PARAMETER;
   }
 
   auto* task = static_cast<tizen_core::Task*>(core);
-  if (!task->SetCpuBoosting(level))
-    return TIZEN_CORE_ERROR_INVALID_CONTEXT;
+  if (!task->SetCpuBoosting(level)) return TIZEN_CORE_ERROR_INVALID_CONTEXT;
 
   return TIZEN_CORE_ERROR_NONE;
 }
@@ -433,8 +417,7 @@ API int tizen_core_clear_cpu_boosting(tizen_core_h core) {
   }
 
   auto* task = static_cast<tizen_core::Task*>(core);
-  if (!task->ClearCpuBoosting())
-    return TIZEN_CORE_ERROR_INVALID_CONTEXT;
+  if (!task->ClearCpuBoosting()) return TIZEN_CORE_ERROR_INVALID_CONTEXT;
 
   return TIZEN_CORE_ERROR_NONE;
 }
@@ -446,17 +429,15 @@ API int tizen_core_source_create(tizen_core_source_h* source) {
     return TIZEN_CORE_ERROR_INVALID_PARAMETER;
   }
 
-  if (!tizen_core_ready())
-    return TIZEN_CORE_ERROR_INVALID_CONTEXT;
+  if (!tizen_core_ready()) return TIZEN_CORE_ERROR_INVALID_CONTEXT;
 
-  auto handle = std::make_shared<SourceExt>();
+  auto* handle = new std::shared_ptr<tizen_core::ISource>(new SourceExt());
   if (handle == nullptr) {
     _E("Out of memory");                    // LCOV_EXCL_LINE
     return TIZEN_CORE_ERROR_OUT_OF_MEMORY;  // LCOV_EXCL_STOP
   }
 
-  handle->RefSelf();
-  *source = static_cast<tizen_core_source_h>(handle.get());
+  *source = static_cast<tizen_core_source_h>(handle);
   return TIZEN_CORE_ERROR_NONE;
 }
 
@@ -466,8 +447,8 @@ API int tizen_core_source_destroy(tizen_core_source_h source) {
     return TIZEN_CORE_ERROR_INVALID_PARAMETER;
   }
 
-  auto handle = static_cast<SourceExt*>(source)->shared_from_this();
-  handle->UnrefSelf();
+  auto* handle = static_cast<std::shared_ptr<tizen_core::ISource>*>(source);
+  delete handle;
   return TIZEN_CORE_ERROR_NONE;
 }
 
@@ -478,14 +459,14 @@ API int tizen_core_source_add_poll(tizen_core_source_h source,
     return TIZEN_CORE_ERROR_INVALID_PARAMETER;
   }
 
-  auto* handle = static_cast<SourceExt*>(source);
+  auto* handle = static_cast<std::shared_ptr<tizen_core::ISource>*>(source);
   auto* pfd = static_cast<tizen_core::PollFd*>(poll_fd);
   if (pfd->GetSource() != nullptr) {
     _E("Invalid context");                    // LCOV_EXCL_LINE
     return TIZEN_CORE_ERROR_INVALID_CONTEXT;  // LCOV_EXCL_LINE
   }
 
-  handle->AddPoll(pfd->shared_from_this());
+  (*handle)->AddPoll(pfd->shared_from_this());
   return TIZEN_CORE_ERROR_NONE;
 }
 
@@ -496,14 +477,14 @@ API int tizen_core_source_remove_poll(tizen_core_source_h source,
     return TIZEN_CORE_ERROR_INVALID_PARAMETER;
   }
 
-  auto* handle = static_cast<SourceExt*>(source);
+  auto* handle = static_cast<std::shared_ptr<tizen_core::ISource>*>(source);
   auto* pfd = static_cast<tizen_core::PollFd*>(poll_fd);
   if (pfd->GetSource() == nullptr) {
     _E("Invalid context");
     return TIZEN_CORE_ERROR_INVALID_CONTEXT;
   }
 
-  handle->RemovePoll(pfd->shared_from_this());
+  (*handle)->RemovePoll(pfd->shared_from_this());
   return TIZEN_CORE_ERROR_NONE;
 }
 
@@ -515,8 +496,9 @@ API int tizen_core_source_set_prepare_cb(tizen_core_source_h source,
     return TIZEN_CORE_ERROR_INVALID_PARAMETER;
   }
 
-  auto* handle = static_cast<SourceExt*>(source);
-  handle->SetPrepareCb(callback, user_data);
+  auto* handle = static_cast<std::shared_ptr<tizen_core::ISource>*>(source);
+  auto se = std::static_pointer_cast<SourceExt>(*handle);
+  se->SetPrepareCb(callback, user_data);
   return TIZEN_CORE_ERROR_NONE;
 }
 
@@ -528,8 +510,9 @@ API int tizen_core_source_set_check_cb(tizen_core_source_h source,
     return TIZEN_CORE_ERROR_INVALID_PARAMETER;
   }
 
-  auto* handle = static_cast<SourceExt*>(source);
-  handle->SetCheckCb(callback, user_data);
+  auto* handle = static_cast<std::shared_ptr<tizen_core::ISource>*>(source);
+  auto se = std::static_pointer_cast<SourceExt>(*handle);
+  se->SetCheckCb(callback, user_data);
   return TIZEN_CORE_ERROR_NONE;
 }
 
@@ -541,8 +524,9 @@ API int tizen_core_source_set_dispatch_cb(
     return TIZEN_CORE_ERROR_INVALID_PARAMETER;
   }
 
-  auto* handle = static_cast<SourceExt*>(source);
-  handle->SetDispatchCb(callback, user_data);
+  auto* handle = static_cast<std::shared_ptr<tizen_core::ISource>*>(source);
+  auto se = std::static_pointer_cast<SourceExt>(*handle);
+  se->SetDispatchCb(callback, user_data);
   return TIZEN_CORE_ERROR_NONE;
 }
 
@@ -554,8 +538,9 @@ API int tizen_core_source_set_finalize_cb(
     return TIZEN_CORE_ERROR_INVALID_PARAMETER;
   }
 
-  auto* handle = static_cast<SourceExt*>(source);
-  handle->SetFinalizeCb(callback, user_data);
+  auto* handle = static_cast<std::shared_ptr<tizen_core::ISource>*>(source);
+  auto se = std::static_pointer_cast<SourceExt>(*handle);
+  se->SetFinalizeCb(callback, user_data);
   return TIZEN_CORE_ERROR_NONE;
 }
 
@@ -578,8 +563,9 @@ API int tizen_core_source_set_priority(tizen_core_source_h source,
     return TIZEN_CORE_ERROR_INVALID_PARAMETER;
   }
 
-  auto* handle = static_cast<SourceExt*>(source);
-  handle->SetPriority(static_cast<int>(priority));
+  auto* handle = static_cast<std::shared_ptr<tizen_core::ISource>*>(source);
+  auto se = std::static_pointer_cast<tizen_core::Source>(*handle);
+  se->SetPriority(static_cast<int>(priority));
   return TIZEN_CORE_ERROR_NONE;
 }
 
index 3751575f569252c170094e7986f933a2b32a5d5b..d6e9b51946191bbf3727c065d742f05bdbc9c9f1 100644 (file)
@@ -33,46 +33,88 @@ namespace {
 
 class IdleSource : public Source {
  public:
-  explicit IdleSource(std::function<bool()> cb)
-      : Source(g_idle_source_new()), cb_(std::move(cb)) {
-    g_source_set_callback(GetHandle(), IdleCb, this, nullptr);
+  explicit IdleSource(std::weak_ptr<Task> task)
+      : Source(g_idle_source_new()), task_(std::move(task)) {
+    _W("IdleSource() %p", this);
+  }
+
+  virtual ~IdleSource() {
+    _W("~IdleSource() %p", this);
+    if (pending_ptr_) delete pending_ptr_;
+  }
+
+  void SetCallback(std::function<bool()> cb) {
+    cb_ = std::move(cb);
+    auto* ptr = new std::weak_ptr<Source>(shared_from_this());
+    g_source_set_callback(GetHandle(), IdleCb, ptr, nullptr);
   }
 
  private:
   static gboolean IdleCb(gpointer user_data) {
-    auto* source = static_cast<IdleSource*>(user_data);
-    auto source_ptr = source->shared_from_this();
-    if (source->cb_())
-      return G_SOURCE_CONTINUE;
+    auto* source = static_cast<std::weak_ptr<Source>*>(user_data);
+    auto src = (*source).lock();
+    if (!src) return G_SOURCE_REMOVE;
+
+    auto idle_src = std::static_pointer_cast<IdleSource>(src);
+    if (idle_src->cb_()) return G_SOURCE_CONTINUE;
 
-    source->UnrefSelf();
+    auto task = idle_src->task_.lock();
+    if (task) {
+      task->RemoveSource(idle_src->shared_from_this());
+    }
+
+    idle_src->pending_ptr_ = nullptr;
+    delete source;
     return G_SOURCE_REMOVE;
   }
 
  private:
   std::function<bool()> cb_;
+  std::weak_ptr<Task> task_;
+  std::weak_ptr<Source>* pending_ptr_ = nullptr;
 };
 
 class TimeoutSource : public Source {
  public:
-  TimeoutSource(unsigned int interval, std::function<bool()> cb)
-      : Source(g_timeout_source_new(interval)), cb_(std::move(cb)) {
-    g_source_set_callback(GetHandle(), TimeoutCb, this, nullptr);
+  TimeoutSource(unsigned int interval, std::weak_ptr<Task> task)
+      : Source(g_timeout_source_new(interval)), task_(std::move(task)) {
+    _W("TimeoutSource() %p", this);
+  }
+
+  virtual ~TimeoutSource() {
+    _W("~TimeoutSource() %p", this);
+    if (pending_ptr_) delete pending_ptr_;
+  }
+
+  void SetCallback(std::function<bool()> cb) {
+    cb_ = std::move(cb);
+    auto* ptr = new std::weak_ptr<Source>(shared_from_this());
+    g_source_set_callback(GetHandle(), TimeoutCb, ptr, nullptr);
   }
 
  private:
   static gboolean TimeoutCb(gpointer user_data) {
-    auto* source = static_cast<TimeoutSource*>(user_data);
-    auto source_ptr = source->shared_from_this();
-    if (source->cb_())
-      return G_SOURCE_CONTINUE;
+    auto* source = static_cast<std::weak_ptr<Source>*>(user_data);
+    auto src = (*source).lock();
+    if (!src) return G_SOURCE_REMOVE;
+
+    auto timeout_src = std::static_pointer_cast<TimeoutSource>(src);
+    if (timeout_src->cb_()) return G_SOURCE_CONTINUE;
+
+    auto task = timeout_src->task_.lock();
+    if (task) {
+      task->RemoveSource(timeout_src->shared_from_this());
+    }
 
-    source->UnrefSelf();
+    timeout_src->pending_ptr_ = nullptr;
+    delete source;
     return G_SOURCE_REMOVE;
   }
 
  private:
   std::function<bool()> cb_;
+  std::weak_ptr<Task> task_;
+  std::weak_ptr<Source>* pending_ptr_ = nullptr;
 };
 
 template <class T>
@@ -85,11 +127,14 @@ class ChannelSource : public Source {
         receiver_(std::move(receiver)),
         cb_(std::move(cb)),
         poll_fd_(new PollFd()) {
+    _W("ChannelSource() %p", this);
     poll_fd_->SetFd(receiver_->GetFd());
     poll_fd_->SetEvents(POLLIN);
     AddPoll(poll_fd_);
   }
 
+  virtual ~ChannelSource() { _W("~ChannelSource() %p", this); }
+
  private:
   bool OnSourcePrepare(int* timeout) override {
     *timeout = -1;
@@ -121,22 +166,19 @@ class EventSource : public Source {
       : task_(std::move(task)),
         broker_(std::move(broker)),
         poll_fd_(new PollFd()) {
+    _W("EventSource() %p", this);
     broker_->SetAttached(true);
     poll_fd_->SetFd(broker_->GetFd());
     poll_fd_->SetEvents(POLLIN);
     AddPoll(poll_fd_);
   }
 
+  virtual ~EventSource() { _W("~EventSource() %p", this); }
+
   void Emit(std::shared_ptr<event::EventObject<T>> object) {
     broker_->Emit(std::move(object));
   }
 
-  // LCOV_EXCL_START
-  void UnrefSelf() override {
-    task_->RemoveEventSource(shared_from_this());
-    Source::UnrefSelf();
-  }
-  // LCOV_EXCL_STOP
  private:
   bool OnSourcePrepare(int* timeout) override {
     *timeout = -1;
@@ -196,7 +238,7 @@ const char* CpuBoostingLevelToStr(tizen_core_cpu_boosting_level_e level) {
 
 Task::Task(std::string name, bool use_thread)
     : name_(std::move(name)), use_thread_(use_thread) {
-  _W("Task: %s", name_.c_str());
+  _W("Task: %s %p", name_.c_str(), this);
   if (name_ == "main" && use_thread_)
     throw std::invalid_argument("main task must not use a thread");
 
@@ -206,7 +248,7 @@ Task::Task(std::string name, bool use_thread)
 }
 
 Task::~Task() {
-  _W("~Task: %s", name_.c_str());
+  _W("~Task: %s %p", name_.c_str(), this);
   if (use_thread_ && thread_.joinable()) {
     if (pthread_self() == thread_.native_handle())
       thread_.detach();
@@ -226,35 +268,29 @@ std::shared_ptr<Task> Task::Create(std::string name, bool use_thread) {
 }
 
 void Task::Dispose() {
-  if(use_thread_) {
+  if (use_thread_) {
     std::unique_lock<std::mutex> quit_lock(loop_mutex_);
-    cond_var_.wait(quit_lock, [this]() {
-        return (loop_ == nullptr);
-    });
+    cond_var_.wait(quit_lock, [this]() { return (loop_ == nullptr); });
   }
   context_->SetLoop(nullptr);
   ContextManager::GetInst().Dispose(name_);
 }
 
-std::shared_ptr<Context> Task::GetContext() const {
-  return context_;
-}
+std::shared_ptr<Context> Task::GetContext() const { return context_; }
 
 void Task::Quit() {
-  if(use_thread_) {
+  if (use_thread_) {
     std::unique_lock<std::mutex> quit_lock(loop_mutex_);
-    if (loop_ && g_main_loop_is_running(loop_))
-      g_main_loop_quit(loop_);
+    if (loop_ && g_main_loop_is_running(loop_)) g_main_loop_quit(loop_);
   } else {
-    if (loop_ && g_main_loop_is_running(loop_))
-      g_main_loop_quit(loop_);
+    if (loop_ && g_main_loop_is_running(loop_)) g_main_loop_quit(loop_);
   }
 }
 
 void Task::Run() {
   if (use_thread_) {
     std::unique_lock<std::mutex> lock(loop_mutex_);
-    if(loop_ != nullptr) {
+    if (loop_ != nullptr) {
       _W("Task GMainLoop already in progress");
       return;
     }
@@ -269,7 +305,7 @@ void Task::Run() {
     });
     cond_var_.wait(lock, [this]() { return idle_entered_; });
   } else {
-    if(loop_ != nullptr) {
+    if (loop_ != nullptr) {
       _W("Task GMainLoop already in progress");
       return;
     }
@@ -287,7 +323,7 @@ void Task::Run() {
 }
 
 bool Task::IsRunning() const {
-  if(use_thread_) {
+  if (use_thread_) {
     std::unique_lock<std::mutex> loop_lock(loop_mutex_);
     return (loop_ && g_main_loop_is_running(loop_));
   } else {
@@ -295,33 +331,33 @@ bool Task::IsRunning() const {
   }
 }
 
-std::shared_ptr<ISource> Task::AddIdleJob(std::function<bool()> job) {
-  auto source = std::make_shared<IdleSource>(std::move(job));
-  AddSource(source);
-  return source;
+std::shared_ptr<ISource>& Task::AddIdleJob(std::function<bool()> job) {
+  auto source = std::make_shared<IdleSource>(shared_from_this());
+  source->SetCallback(std::move(job));
+  return AddManagedSource(source);
 }
 
-std::shared_ptr<ISource> Task::AddTimer(unsigned int interval,
-                                        std::function<bool()> cb) {
-  auto source = std::make_shared<TimeoutSource>(interval, std::move(cb));
-  AddSource(source);
-  return source;
+std::shared_ptr<ISource>& Task::AddTimer(unsigned int interval,
+                                         std::function<bool()> cb) {
+  auto source = std::make_shared<TimeoutSource>(interval, shared_from_this());
+  source->SetCallback(std::move(cb));
+  return AddManagedSource(source);
 }
 
 void Task::RemoveSource(std::shared_ptr<ISource> source) {
   RemoveEventSource(source);
   source->Dispose();
-  auto idler = std::make_shared<IdleSource>([source]() {
-    source->UnrefSelf();
-    return false;
-  });
-  idler->SetPriority(TIZEN_CORE_PRIORITY_HIGH);
-  AddSource(idler);
+  managed_sources_.remove(std::move(source));
+}
+
+std::shared_ptr<ISource>& Task::AddManagedSource(std::shared_ptr<ISource> source) {
+  source->Attach(context_);
+  managed_sources_.push_back(std::move(source));
+  return managed_sources_.back();
 }
 
 void Task::AddSource(std::shared_ptr<ISource> source) {
   source->Attach(context_);
-  source->RefSelf();
 }
 
 template <typename T>
@@ -349,8 +385,7 @@ void Task::EmitEvent(std::shared_ptr<event::EventObject<T>> object) {
   std::lock_guard<std::recursive_mutex> lock(mutex_);
   for (auto& source : event_sources_) {
     auto* event_source = dynamic_cast<EventSource<T>*>(source.get());
-    if (event_source == nullptr)
-      continue;
+    if (event_source == nullptr) continue;
 
     event_source->Emit(object);
   }
@@ -364,8 +399,7 @@ bool Task::SetCpuBoosting(tizen_core_cpu_boosting_level_e level) {
     return false;
   }
 
-  if (cpu_boosting_level_ == level)
-    return true;
+  if (cpu_boosting_level_ == level) return true;
 
   resource_pid_t res_pid = {
       .pid = 0,
@@ -382,7 +416,7 @@ bool Task::SetCpuBoosting(tizen_core_cpu_boosting_level_e level) {
   }
 
   _I("Set cpu boosting level(%s -> %s).",
-      CpuBoostingLevelToStr(cpu_boosting_level_), CpuBoostingLevelToStr(level));
+     CpuBoostingLevelToStr(cpu_boosting_level_), CpuBoostingLevelToStr(level));
   cpu_boosting_level_ = level;
   return true;
 }
@@ -418,15 +452,16 @@ void Task::ThreadLoop() {
     std::unique_lock<std::mutex> lock(loop_mutex_);
     GSource* source = g_idle_source_new();
     g_source_set_callback(
-        source, [](gpointer user_data) {
+        source,
+        [](gpointer user_data) {
           auto* task = static_cast<Task*>(user_data);
           std::unique_lock<std::mutex> idler_lock(task->loop_mutex_);
           _W("thread loop is running");
           task->idle_entered_ = true;
           task->cond_var_.notify_one();
           return G_SOURCE_REMOVE;
-        }, this,
-        nullptr);
+        },
+        this, nullptr);
     g_source_set_priority(source, G_PRIORITY_HIGH);
     g_source_attach(source, context_->GetHandle());
     g_source_unref(source);
@@ -461,18 +496,6 @@ void Task::RemoveEventSource(std::shared_ptr<ISource> source) {
   event_sources_.remove(source);
 }
 
-void Task::RefSelf() {
-  ref_count_++;
-  if (!self_) self_ = shared_from_this();
-}
-
-void Task::UnrefSelf() {
-  ref_count_--;
-  if (ref_count_ == 0 && self_) self_.reset();
-}
-
-uint32_t Task::GetRefCount() const { return ref_count_; }
-
 template std::shared_ptr<ISource> Task::AddChannel<void*>(
     std::shared_ptr<channel::Receiver<void*>> receiver,
     std::move_only_function<void(channel::ChannelObject<void*>)> cb);
index aa468e5033b5cd42b2773e813d8d05630441806f..0460625e9fd84a45f26f2b3187c3492e12b0f6f8 100644 (file)
@@ -57,10 +57,11 @@ class EXPORT_API Task : public ILoop,
   void Run() override;
   bool IsRunning() const override;
 
-  std::shared_ptr<ISource> AddIdleJob(std::function<bool()> cb) override;
-  std::shared_ptr<ISource> AddTimer(unsigned int interval,
+  std::shared_ptr<ISource>& AddIdleJob(std::function<bool()> cb) override;
+  std::shared_ptr<ISource>& AddTimer(unsigned int interval,
                                     std::function<bool()> cb) override;
   void RemoveSource(std::shared_ptr<ISource> source) override;
+  std::shared_ptr<ISource>& AddManagedSource(std::shared_ptr<ISource> source) override;
   void AddSource(std::shared_ptr<ISource> source) override;
 
   template <typename T>
@@ -79,10 +80,6 @@ class EXPORT_API Task : public ILoop,
   void AddEventSource(std::shared_ptr<ISource> source);
   void RemoveEventSource(std::shared_ptr<ISource> source);
 
-  void RefSelf();
-  void UnrefSelf();
-  uint32_t GetRefCount() const;
-
  private:
   void ThreadLoop();
 
@@ -99,8 +96,8 @@ class EXPORT_API Task : public ILoop,
   GMainLoop* loop_ = nullptr;
   bool idle_entered_ = false;
   std::list<std::shared_ptr<ISource>> event_sources_;
+  std::list<std::shared_ptr<ISource>> managed_sources_;
   mutable std::recursive_mutex mutex_;
-  std::shared_ptr<Task> self_;
   std::atomic<uint32_t> ref_count_{0};
 };