tizen-core: Modify fd handler implementation 94/305894/34
authorHwankyu Jhun <h.jhun@samsung.com>
Tue, 13 Feb 2024 02:30:34 +0000 (11:30 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Thu, 28 Mar 2024 01:13:03 +0000 (10:13 +0900)
The ecore_main_fd_handler implementation are changed using the tizen core.

Change-Id: I927b0010f38ac169c0295a82e798d3433f948cb7
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
src/lib/ecore/ecore_main.c
src/lib/ecore/meson.build
src/lib/ecore/tizen-core/tcore.cc
src/lib/ecore/tizen-core/tcore_fd_handler.cc [new file with mode: 0644]
src/lib/ecore/tizen-core/tcore_fd_handler.h [new file with mode: 0644]

index 841c36b..abb5e35 100644 (file)
@@ -24,6 +24,7 @@
 
 #ifdef USE_TIZEN_CORE
 #include "tizen-core/tcore.h"
+#include "tizen-core/tcore_fd_handler.h"
 #endif // USE_TIZEN_CORE
 
 #ifdef HAVE_IEEEFP_H
@@ -1478,6 +1479,12 @@ ecore_main_awake_handler_add(Ecore_Awake_Cb func, void *data)
    Ecore_Awake_Handler *handler;
 
    if (!func) return EINA_FALSE;
+#ifdef USE_TIZEN_CORE
+   if (tcore_ready())
+     {
+        return tcore_awake_handler_add(func, data);
+     }
+#endif // USE_TIZEN_CORE
 
    handler = calloc(1, sizeof *handler);
    if (!handler) return EINA_FALSE;
@@ -1496,6 +1503,13 @@ ecore_main_awake_handler_del(Ecore_Awake_Cb func)
    Eina_List *l, *ll;
 
    if (!func) return;
+#ifdef USE_TIZEN_CORE
+   if (tcore_ready())
+     {
+        tcore_awake_handler_del(func);
+        return;
+     }
+#endif // USE_TIZEN_CORE
 
    EINA_LIST_FOREACH_SAFE(awake_funcs, l, ll, handler)
      {
@@ -1514,6 +1528,14 @@ _ecore_main_awake_handler_call(void)
    Ecore_Awake_Handler *handler;
    Eina_List *l, *ll;
 
+#ifdef USE_TIZEN_CORE
+   if (tcore_ready())
+     {
+        tcore_awake_handler_call();
+        return;
+     }
+#endif // USE_TIZEN_CORE
+
    EINA_LIST_FOREACH_SAFE(awake_funcs, l, ll, handler)
      {
         if (handler->func)
@@ -1538,7 +1560,23 @@ _ecore_main_fd_handler_add(Eo                    *obj,
    Ecore_Fd_Handler *fdh = NULL;
 
    if ((fd < 0) || (flags == 0) || (!func)) return NULL;
+#ifdef USE_TIZEN_CORE
+   if (tcore_ready())
+     {
+        if (is_file)
+          {
+             return (Ecore_Fd_Handler *)tcore_fd_handler_file_add(fd,
+               (int)flags, (tcore_fd_cb)func, (void *)data,
+               (tcore_fd_cb)buf_func, (void *)buf_data);
+          }
 
+        return (Ecore_Fd_Handler *)tcore_fd_handler_add(fd, (int)flags,
+          (tcore_fd_cb)func, (void *)data, (tcore_fd_cb)buf_func,
+          (void *)buf_data);
+     }
+#endif // USE_TIZEN_CORE
+
+   WRN("[DEBUG] fd=%d, flags=%d", fd, flags);
    fdh = ecore_fd_handler_calloc(1);
    if (!fdh) return NULL;
    ECORE_MAGIC_SET(fdh, ECORE_MAGIC_FD_HANDLER);
@@ -1577,6 +1615,13 @@ _ecore_main_fd_handler_del(Eo *obj EINA_UNUSED,
                            Efl_Loop_Data *pd,
                            Ecore_Fd_Handler *fd_handler)
 {
+#ifdef USE_TIZEN_CORE
+   if (tcore_ready())
+     {
+        return tcore_fd_handler_del((tcore_fd_handler_h)fd_handler);
+     }
+#endif // USE_TIZEN_CORE
+
    void *r = fd_handler->data;
 
    DBG("_ecore_main_fd_handler_del %p", fd_handler);
@@ -1622,6 +1667,9 @@ ecore_main_fd_handler_add(int                    fd,
    fdh = _ecore_main_fd_handler_add(efl_main_loop_get(),
                                     ML_DAT, NULL, fd, flags, func, data,
                                     buf_func, buf_data, EINA_FALSE);
+#ifdef USE_TIZEN_CORE
+   if (tcore_ready()) return fdh;
+#endif // USE_TIZEN_CORE
    if (fdh) fdh->legacy = EINA_TRUE;
    return fdh;
 }
@@ -1645,6 +1693,12 @@ ecore_main_fd_handler_del(Ecore_Fd_Handler *fd_handler)
 {
    if (!fd_handler) return NULL;
    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
+#ifdef USE_TIZEN_CORE
+   if (tcore_ready())
+     {
+        return tcore_fd_handler_del(fd_handler);
+     }
+#endif // USE_TIZEN_CORE
 
    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
      {
@@ -1768,6 +1822,14 @@ ecore_main_fd_handler_prepare_callback_set(Ecore_Fd_Handler *fd_handler,
                                            const void       *data)
 {
    if (!fd_handler) return;
+#ifdef USE_TIZEN_CORE
+   if (tcore_ready())
+     {
+        tcore_fd_handler_prepare_callback_set((tcore_fd_handler_h)fd_handler,
+                                              (tcore_fd_prep_cb)func, data);
+        return;
+     }
+#endif // USE_TIZEN_CORE
    Efl_Loop_Data *pd = fd_handler->loop_data;
    EINA_MAIN_LOOP_CHECK_RETURN;
 
@@ -1793,6 +1855,12 @@ ecore_main_fd_handler_fd_get(Ecore_Fd_Handler *fd_handler)
    if (!fd_handler) return -1;
 
    EINA_MAIN_LOOP_CHECK_RETURN_VAL(-1);
+#ifdef USE_TIZEN_CORE
+   if (tcore_ready())
+     {
+        return tcore_fd_handler_fd_get((tcore_fd_handler_h)fd_handler);
+     }
+#endif // USE_TIZEN_CORE
 
    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
      {
@@ -1810,6 +1878,13 @@ ecore_main_fd_handler_active_get(Ecore_Fd_Handler      *fd_handler,
    int ret = EINA_FALSE;
 
    EINA_MAIN_LOOP_CHECK_RETURN_VAL(EINA_FALSE);
+#ifdef USE_TIZEN_CORE
+   if (tcore_ready())
+     {
+        return tcore_fd_handler_active_get((tcore_fd_handler_h)fd_handler,
+                                           (int)flags);
+     }
+#endif // USE_TIZEN_CORE
 
    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
      {
@@ -1828,6 +1903,13 @@ ecore_main_fd_handler_active_set(Ecore_Fd_Handler      *fd_handler,
                                  Ecore_Fd_Handler_Flags flags)
 {
    int ret = -1;
+#ifdef USE_TIZEN_CORE
+   if (tcore_ready())
+     {
+        tcore_fd_handler_active_set((tcore_fd_handler_h)fd_handler, (int)flags);
+        return;
+     }
+#endif // USE_TIZEN_CORE
 
    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
      {
index d4b2541..cdcc94c 100644 (file)
@@ -212,7 +212,8 @@ if get_option('tizen-core') == true
     'tizen-core/tcore.cc',
     'tizen-core/tcore_events.cc',
     'tizen-core/tcore_idler.cc',
-    'tizen-core/tcore_timer.cc'
+    'tizen-core/tcore_timer.cc',
+    'tizen-core/tcore_fd_handler.cc'
   ])
   config_h.set('USE_TIZEN_CORE', '1')
 endif
index 93728df..09f74ca 100644 (file)
@@ -4,7 +4,6 @@
 #include <tizen_core_internal.h>
 
 #include "log_private.h"
-#include "tcore_idler.h"
 
 namespace {
 
@@ -13,7 +12,6 @@ class TCore {
   bool Init() {
     if (!disposed_) return true;
 
-    _D("Init()");
     if (tizen_core_ready()) {
       int ret = tizen_core_task_create("main", false, &tizen_core_task_);
       if (ret != TIZEN_CORE_ERROR_NONE) {
@@ -31,7 +29,6 @@ class TCore {
   void Dispose() {
     if (disposed_) return;
 
-    _D("Dispose()");
     if (tizen_core_task_ != nullptr) {
       tizen_core_task_destroy(tizen_core_task_);
       tizen_core_task_ = nullptr;
diff --git a/src/lib/ecore/tizen-core/tcore_fd_handler.cc b/src/lib/ecore/tizen-core/tcore_fd_handler.cc
new file mode 100644 (file)
index 0000000..3700caa
--- /dev/null
@@ -0,0 +1,541 @@
+#include "tcore_fd_handler.h"
+
+#include <tizen_core.h>
+
+#include <list>
+#include <memory>
+#include <mutex>
+#include <new>
+#include <unordered_set>
+#include <vector>
+
+#include "log_private.h"
+
+namespace {
+
+enum EcoreFdEvent {
+  Read = 1,
+  Write = 2,
+  Error = 4,
+};
+
+int GetPollEventsFromEcoreFdEvents(int flags) {
+  int events = 0;
+  if (flags & static_cast<int>(EcoreFdEvent::Read))
+    events |= TIZEN_CORE_POLL_EVENT_IN | TIZEN_CORE_POLL_EVENT_HUP;
+  if (flags & static_cast<int>(EcoreFdEvent::Write))
+    events |= TIZEN_CORE_POLL_EVENT_OUT | TIZEN_CORE_POLL_EVENT_HUP;
+  if (flags & static_cast<int>(EcoreFdEvent::Error))
+    events |= TIZEN_CORE_POLL_EVENT_ERR | TIZEN_CORE_POLL_EVENT_HUP;
+  return events;
+}
+
+class FdHandler : public std::enable_shared_from_this<FdHandler> {
+ public:
+  FdHandler(int fd, int flags, tcore_fd_cb func, void* user_data,
+            tcore_fd_cb buf_func, void* buf_data, bool is_file = false);
+  ~FdHandler();
+
+  int AddPoll();
+  void RemovePoll();
+  void ModifyPoll(int flags);
+  bool IsFile() const;
+  tcore_fd_cb GetBufFunc() const;
+  tcore_fd_prep_cb GetPrepFunc() const;
+  void SetPrepFunc(tcore_fd_prep_cb prep_func, void* prep_data);
+  std::shared_ptr<FdHandler> GetSharedPtr();
+  void SetDeleteMe();
+  bool CanDeleteMe() const;
+  void* GetUserData() const;
+  bool MarkActive();
+  void ClearActive();
+  bool ReadActive() const;
+  bool WriteActive() const;
+  bool ErrorActive() const;
+  void Ref();
+  void Unref();
+  bool CallFunc();
+  bool CallBufFunc();
+  void CallPrepFunc();
+  void SetReadActive();
+  int GetFd() const;
+
+ private:
+  int fd_;
+  int flags_;
+  tcore_fd_cb func_;
+  void *user_data_;
+  tcore_fd_cb buf_func_;
+  void *buf_data_;
+  bool is_file_;
+  bool delete_me_ = false;
+  tcore_fd_prep_cb prep_func_ = nullptr;
+  void* prep_data_ = nullptr;
+  tizen_core_poll_fd_h poll_fd_ = nullptr;
+  bool read_active_ = false;
+  bool write_active_ = false;
+  bool error_active_ = false;
+  uint32_t ref_ = 0;
+};
+
+class AwakeHandler {
+ public:
+  AwakeHandler(tcore_awake_cb func, void* user_data);
+  void CallFunc();
+  tcore_awake_cb GetFunc() const;
+
+ private:
+  tcore_awake_cb func_;
+  void* user_data_;
+};
+
+class FdHandlerManager {
+ public:
+  FdHandlerManager();
+  ~FdHandlerManager();
+
+  void Init();
+  void AddFdHandler(std::shared_ptr<FdHandler> fd_handler);
+  void AddFdHandlerWithPrep(std::shared_ptr<FdHandler> fd_handler);
+  void RemoveFdHandler(std::shared_ptr<FdHandler> fd_handler);
+  bool Exist(FdHandler* fd_handler) const;
+  void AddAwakeHandler(std::shared_ptr<AwakeHandler> awake_handler);
+  void RemoveAwakeHandler(tcore_awake_cb func);
+  void CallAwakeFuncs();
+  tizen_core_source_h GetSource() const;
+
+ private:
+  static bool SourcePrepareCb(tizen_core_source_h source, int* timeout,
+                              void* user_data);
+  static bool SourceCheckCb(tizen_core_source_h source, void* user_data);
+  static bool SourceDispatchCb(tizen_core_source_h source, void* user_data);
+  void Dispose();
+  int MarkActive();
+  void CleanUpFdHandlers();
+  void CallFuncs();
+  int CallBufFuncs();
+  void CallPrepFuncs();
+
+ private:
+  bool disposed_ = true;
+  tizen_core_source_h source_ = nullptr;
+  std::unordered_set<std::shared_ptr<FdHandler>> fd_handlers_to_delete_;
+  std::unordered_set<std::shared_ptr<FdHandler>> fd_handlers_;
+  std::unordered_set<std::shared_ptr<FdHandler>> file_fd_handlers_;
+  std::unordered_set<std::shared_ptr<FdHandler>> fd_handlers_with_buffer_;
+  std::unordered_set<std::shared_ptr<FdHandler>> fd_handlers_with_prep_;
+  std::vector<std::shared_ptr<AwakeHandler>> awake_handlers_;
+  mutable std::recursive_mutex mutex_;
+};
+
+FdHandlerManager manager;
+
+// FdHandler
+FdHandler::FdHandler(int fd, int flags, tcore_fd_cb func, void* user_data,
+                     tcore_fd_cb buf_func, void* buf_data, bool is_file)
+    : fd_(fd),
+      flags_(flags),
+      func_(func),
+      user_data_(user_data),
+      buf_func_(buf_func),
+      buf_data_(buf_data),
+      is_file_(is_file) {}
+
+FdHandler::~FdHandler() { RemovePoll(); }
+
+int FdHandler::AddPoll() {
+  if (poll_fd_ != nullptr) return 0;
+
+  int ret = tizen_core_poll_fd_create(&poll_fd_);
+  if (ret != TIZEN_CORE_ERROR_NONE) return ret;
+
+  tizen_core_poll_fd_set_fd(poll_fd_, fd_);
+  tizen_core_poll_fd_set_events(poll_fd_,
+                                GetPollEventsFromEcoreFdEvents(flags_));
+  tizen_core_source_add_poll(manager.GetSource(), poll_fd_);
+  return ret;
+}
+
+void FdHandler::RemovePoll() {
+  if (poll_fd_ == nullptr) return;
+
+  tizen_core_source_remove_poll(manager.GetSource(), poll_fd_);
+  tizen_core_poll_fd_destroy(poll_fd_);
+  poll_fd_ = nullptr;
+}
+
+void FdHandler::ModifyPoll(int flags) {
+  if (flags == flags_) return;
+  flags_ = flags;
+  tizen_core_poll_fd_set_events(poll_fd_,
+                                GetPollEventsFromEcoreFdEvents(flags_));
+}
+
+bool FdHandler::IsFile() const { return is_file_; }
+
+tcore_fd_cb FdHandler::GetBufFunc() const { return buf_func_; }
+
+tcore_fd_prep_cb FdHandler::GetPrepFunc() const { return prep_func_; }
+
+void FdHandler::SetPrepFunc(tcore_fd_prep_cb prep_func, void* prep_data) {
+  prep_func_ = prep_func;
+  prep_data_ = prep_data;
+}
+
+std::shared_ptr<FdHandler> FdHandler::GetSharedPtr() {
+  return shared_from_this();
+}
+
+void FdHandler::SetDeleteMe() { delete_me_ = true; }
+
+bool FdHandler::CanDeleteMe() const { return delete_me_; }
+
+void* FdHandler::GetUserData() const { return user_data_; }
+
+bool FdHandler::MarkActive() {
+  uint16_t revents = 0;
+  tizen_core_poll_fd_get_returned_events(poll_fd_, &revents);
+  if ((flags_ & static_cast<int>(EcoreFdEvent::Read)) &&
+      (revents & TIZEN_CORE_POLL_EVENT_IN))
+    read_active_ = true;
+  if ((flags_ & static_cast<int>(EcoreFdEvent::Write)) &&
+      (revents & TIZEN_CORE_POLL_EVENT_OUT))
+    write_active_ = true;
+  if ((flags_ & static_cast<int>(EcoreFdEvent::Error)) &&
+      (revents & (TIZEN_CORE_POLL_EVENT_ERR | TIZEN_CORE_POLL_EVENT_HUP)))
+    error_active_ = true;
+
+  return (read_active_ || write_active_ || error_active_);
+}
+
+void FdHandler::ClearActive() {
+  read_active_ = false;
+  write_active_ = false;
+  error_active_ = false;
+}
+
+bool FdHandler::ReadActive() const { return read_active_; }
+
+bool FdHandler::WriteActive() const { return write_active_; }
+
+bool FdHandler::ErrorActive() const { return error_active_; }
+
+void FdHandler::Ref() { ref_++; }
+
+void FdHandler::Unref() { ref_--; }
+
+bool FdHandler::CallFunc() { return func_(user_data_, this); }
+
+bool FdHandler::CallBufFunc() { return buf_func_(buf_data_, this); }
+
+void FdHandler::CallPrepFunc() { prep_func_(prep_data_, this); }
+
+void FdHandler::SetReadActive() { read_active_ = true; }
+
+int FdHandler::GetFd() const { return fd_; }
+
+// AwakeHandler
+AwakeHandler::AwakeHandler(tcore_awake_cb func, void* user_data)
+    : func_(func), user_data_(user_data) {}
+
+void AwakeHandler::CallFunc() { func_(user_data_); }
+
+tcore_awake_cb AwakeHandler::GetFunc() const { return func_; }
+
+// FdHandlerManager
+FdHandlerManager::FdHandlerManager() = default;
+
+FdHandlerManager::~FdHandlerManager() { Dispose(); }
+
+void FdHandlerManager::AddFdHandler(std::shared_ptr<FdHandler> fd_handler) {
+  std::unique_lock<std::recursive_mutex> lock(mutex_);
+  fd_handlers_.insert(fd_handler);
+  if (fd_handler->IsFile()) file_fd_handlers_.insert(fd_handler);
+  if (fd_handler->GetBufFunc()) fd_handlers_with_buffer_.insert(fd_handler);
+}
+
+void FdHandlerManager::AddFdHandlerWithPrep(
+    std::shared_ptr<FdHandler> fd_handler) {
+  std::unique_lock<std::recursive_mutex> lock(mutex_);
+  fd_handlers_with_prep_.insert(fd_handler);
+}
+
+void FdHandlerManager::RemoveFdHandler(std::shared_ptr<FdHandler> fd_handler) {
+  std::unique_lock<std::recursive_mutex> lock(mutex_);
+  fd_handler->SetDeleteMe();
+  fd_handler->RemovePoll();
+  fd_handlers_to_delete_.insert(fd_handler);
+  if (fd_handler->GetPrepFunc()) fd_handlers_with_prep_.erase(fd_handler);
+  if (fd_handler->GetBufFunc()) fd_handlers_with_buffer_.erase(fd_handler);
+}
+
+void FdHandlerManager::AddAwakeHandler(
+    std::shared_ptr<AwakeHandler> awake_handler) {
+  std::unique_lock<std::recursive_mutex> lock(mutex_);
+  awake_handlers_.push_back(std::move(awake_handler));
+}
+
+void FdHandlerManager::RemoveAwakeHandler(tcore_awake_cb func) {
+  std::unique_lock<std::recursive_mutex> lock(mutex_);
+  auto iter = awake_handlers_.begin();
+  while (iter != awake_handlers_.end()) {
+    if ((*iter)->GetFunc() == func) {
+      iter = awake_handlers_.erase(iter);
+      break;
+    }
+
+    iter++;
+  }
+}
+
+void FdHandlerManager::CallAwakeFuncs() {
+  std::unique_lock<std::recursive_mutex> lock(mutex_);
+  auto iter = awake_handlers_.begin();
+  while (iter != awake_handlers_.end()) {
+    auto& awake_handler = *iter;
+    iter++;
+    awake_handler->CallFunc();
+  }
+}
+
+tizen_core_source_h FdHandlerManager::GetSource() const { return source_; }
+
+bool FdHandlerManager::SourcePrepareCb(tizen_core_source_h source, int* timeout,
+                                     void* user_data) {
+  auto* fh_manager = static_cast<FdHandlerManager*>(user_data);
+  fh_manager->CallBufFuncs();
+  fh_manager->CallPrepFuncs();
+  return false;
+}
+
+bool FdHandlerManager::SourceCheckCb(tizen_core_source_h source,
+                                     void* user_data) {
+  auto* fh_manager = static_cast<FdHandlerManager*>(user_data);
+  bool ret = fh_manager->MarkActive() > 0;
+  fh_manager->CallAwakeFuncs();
+  fh_manager->CleanUpFdHandlers();
+  return ret;
+}
+
+bool FdHandlerManager::SourceDispatchCb(tizen_core_source_h source,
+                                        void* user_data) {
+  auto* fh_manager = static_cast<FdHandlerManager*>(user_data);
+  fh_manager->CallFuncs();
+  fh_manager->CallBufFuncs();
+  fh_manager->CleanUpFdHandlers();
+  return true;
+}
+
+void FdHandlerManager::Init() {
+  std::unique_lock<std::recursive_mutex> lock(mutex_);
+  if (!disposed_) return;
+
+  tizen_core_source_create(&source_);
+  tizen_core_source_set_prepare_cb(source_, SourcePrepareCb, this);
+  tizen_core_source_set_check_cb(source_, SourceCheckCb, this);
+  tizen_core_source_set_dispatch_cb(source_, SourceDispatchCb, this);
+  tizen_core_add_source(tcore_get_core(), source_);
+  disposed_ = false;
+}
+
+void FdHandlerManager::Dispose() {
+  std::unique_lock<std::recursive_mutex> lock(mutex_);
+  if (disposed_) return;
+
+  if (source_) {
+    tizen_core_remove_source(tcore_get_core(), source_);
+    source_ = nullptr;
+  }
+
+  disposed_ = true;
+}
+
+int FdHandlerManager::MarkActive() {
+  std::unique_lock<std::recursive_mutex> lock(mutex_);
+  int ret = 0;
+  for (auto& fd_handler : fd_handlers_) {
+    if (fd_handler->CanDeleteMe()) continue;
+    if (fd_handler->MarkActive()) ret++;
+  }
+
+  return ret;
+}
+
+void FdHandlerManager::CleanUpFdHandlers() {
+  std::unique_lock<std::recursive_mutex> lock(mutex_);
+  auto iter = fd_handlers_to_delete_.begin();
+  while (iter != fd_handlers_to_delete_.end()) {
+    auto& fd_handler = *iter;
+    fd_handlers_.erase(fd_handler);
+    fd_handlers_with_prep_.erase(fd_handler);
+    fd_handlers_with_buffer_.erase(fd_handler);
+    iter = fd_handlers_to_delete_.erase(iter);
+  }
+
+  if (fd_handlers_.empty()) Dispose();
+}
+
+void FdHandlerManager::CallFuncs() {
+  std::unique_lock<std::recursive_mutex> lock(mutex_);
+  for (auto& fd_handler : fd_handlers_) {
+    if (fd_handler->CanDeleteMe()) continue;
+
+    if (fd_handler->ReadActive() || fd_handler->WriteActive() ||
+        fd_handler->ErrorActive()) {
+      fd_handler->Ref();
+      if (!fd_handler->CallFunc()) {
+        if (!fd_handler->CanDeleteMe()) {
+          fd_handler->SetDeleteMe();
+          fd_handler->RemovePoll();
+          fd_handlers_to_delete_.insert(fd_handler);
+        }
+      }
+      fd_handler->Unref();
+      fd_handler->ClearActive();
+    }
+  }
+}
+
+int FdHandlerManager::CallBufFuncs() {
+  std::unique_lock<std::recursive_mutex> lock(mutex_);
+  int ret = 0;
+  for (auto& fd_handler : fd_handlers_with_buffer_) {
+    if (fd_handler->CanDeleteMe()) continue;
+    fd_handler->Ref();
+    if (fd_handler->CallBufFunc()) {
+      ret |= fd_handler->CallFunc();
+      fd_handler->SetReadActive();
+    }
+    fd_handler->Unref();
+  }
+
+  return ret;
+}
+
+void FdHandlerManager::CallPrepFuncs() {
+  std::unique_lock<std::recursive_mutex> lock(mutex_);
+  auto iter = fd_handlers_with_prep_.begin();
+  while (iter != fd_handlers_with_prep_.end()) {
+    auto& fd_handler = *iter;
+    if (!fd_handler->CanDeleteMe() && fd_handler->GetPrepFunc()) {
+      fd_handler->Ref();
+      fd_handler->CallPrepFunc();
+      fd_handler->Unref();
+      iter++;
+    } else {
+      iter = fd_handlers_with_prep_.erase(iter);
+    }
+  }
+}
+
+}  // namespace
+
+tcore_fd_handler_h tcore_fd_handler_add(int fd, int flags, tcore_fd_cb func,
+                                        void* user_data, tcore_fd_cb buf_func,
+                                        void* buf_data) {
+  manager.Init();
+  auto fd_handler = std::make_shared<FdHandler>(fd, flags, func, user_data,
+                                                buf_func, buf_data);
+  if (fd_handler == nullptr) return nullptr;
+
+  if (fd_handler->AddPoll() != 0) return nullptr;
+
+  auto* handler = fd_handler.get();
+  manager.AddFdHandler(std::move(fd_handler));
+  return handler;
+}
+
+tcore_fd_handler_h tcore_fd_handler_file_add(int fd, int flags,
+                                             tcore_fd_cb func, void *user_data,
+                                             tcore_fd_cb buf_func,
+                                             void *buf_data) {
+  manager.Init();
+  auto fd_handler = std::make_shared<FdHandler>(fd, flags, func, user_data,
+                                                buf_func, buf_data, true);
+  if (fd_handler == nullptr) return nullptr;
+
+  if (fd_handler->AddPoll() != 0) return nullptr;
+
+  auto* handler = fd_handler.get();
+  manager.AddFdHandler(std::move(fd_handler));
+  return handler;
+}
+
+void* tcore_fd_handler_del(tcore_fd_handler_h fd_handler) {
+  auto* handler = static_cast<FdHandler*>(fd_handler);
+  if (handler->CanDeleteMe()) {
+    _E("fd_handler is already deleted");
+    return nullptr;
+  }
+
+  auto* user_data = handler->GetUserData();
+  manager.RemoveFdHandler(handler->GetSharedPtr());
+  return user_data;
+}
+
+void tcore_fd_handler_prepare_callback_set(tcore_fd_handler_h fd_handler,
+                                           tcore_fd_prep_cb func,
+                                           void *user_data) {
+  auto* handler = static_cast<FdHandler*>(fd_handler);
+  if (handler->CanDeleteMe()) {
+    _E("fd_handler is already deleted");
+    return;
+  }
+
+  handler->SetPrepFunc(func, user_data);
+  manager.AddFdHandlerWithPrep(handler->GetSharedPtr());
+}
+
+int tcore_fd_handler_fd_get(tcore_fd_handler_h fd_handler) {
+  auto* handler = static_cast<FdHandler*>(fd_handler);
+  if (handler->CanDeleteMe()) {
+    _E("fd_handler is already deleted");
+    return -1;
+  }
+
+  return handler->GetFd();
+}
+
+bool tcore_fd_handler_active_get(tcore_fd_handler_h fd_handler, int flags) {
+  auto* handler = static_cast<FdHandler*>(fd_handler);
+  if (handler->CanDeleteMe()) {
+    _E("fd_handler is already deleted");
+    return false;
+  }
+
+  bool ret = false;
+  if (flags & static_cast<int>(EcoreFdEvent::Read) && handler->ReadActive())
+    ret = true;
+  if (flags & static_cast<int>(EcoreFdEvent::Write) && handler->WriteActive())
+    ret = true;
+  if (flags & static_cast<int>(EcoreFdEvent::Error) && handler->ErrorActive())
+    ret = true;
+  return ret;
+}
+
+void tcore_fd_handler_active_set(tcore_fd_handler_h fd_handler, int flags) {
+  auto* handler = static_cast<FdHandler*>(fd_handler);
+  if (handler->CanDeleteMe()) {
+    _E("fd_handler is already deleted");
+    return;
+  }
+
+  handler->ModifyPoll(flags);
+}
+
+bool tcore_awake_handler_add(tcore_awake_cb func, void* user_data) {
+  auto handler = std::make_shared<AwakeHandler>(func, user_data);
+  if (handler == nullptr) {
+    _E("Out of memory");
+    return false;
+  }
+
+  manager.AddAwakeHandler(std::move(handler));
+  return true;
+}
+
+void tcore_awake_handler_del(tcore_awake_cb func) {
+  manager.RemoveAwakeHandler(func);
+}
+
+void tcore_awake_handler_call(void) { manager.CallAwakeFuncs(); }
diff --git a/src/lib/ecore/tizen-core/tcore_fd_handler.h b/src/lib/ecore/tizen-core/tcore_fd_handler.h
new file mode 100644 (file)
index 0000000..6ce7a85
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef _TCORE_FD_HANDLER_H
+#define _TCORE_FD_HANDLER_H
+
+#include <stdbool.h>
+
+#include "tcore.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef void *tcore_fd_handler_h;
+
+typedef bool (*tcore_fd_cb)(void* user_data, tcore_fd_handler_h fd_handler);
+
+typedef void (*tcore_fd_prep_cb)(void *user_data,
+                                 tcore_fd_handler_h fd_handler);
+
+typedef void (*tcore_awake_cb)(void* user_data);
+
+tcore_fd_handler_h tcore_fd_handler_add(int fd, int flags, tcore_fd_cb func,
+                                        void *user_data, tcore_fd_cb buf_func,
+                                        void *buf_data);
+
+tcore_fd_handler_h tcore_fd_handler_file_add(int fd, int flags,
+                                             tcore_fd_cb func, void *user_data,
+                                             tcore_fd_cb buf_func,
+                                             void *buf_data);
+
+void *tcore_fd_handler_del(tcore_fd_handler_h fd_handler);
+
+void tcore_fd_handler_prepare_callback_set(tcore_fd_handler_h fd_handler,
+                                           tcore_fd_prep_cb func,
+                                           void *user_data);
+
+int tcore_fd_handler_fd_get(tcore_fd_handler_h fd_handler);
+
+bool tcore_fd_handler_active_get(tcore_fd_handler_h fd_handler, int flags);
+
+void tcore_fd_handler_active_set(tcore_fd_handler_h fd_handler, int flags);
+
+bool tcore_awake_handler_add(tcore_awake_cb func, void* user_data);
+
+void tcore_awake_handler_del(tcore_awake_cb func);
+
+void tcore_awake_handler_call(void);
+
+#ifdef __cplusplus
+}
+#endif /*  __cplusplus */
+
+#endif /* _TCORE_FD_HANDLER_H */