}
template <>
-gboolean TaskQueue::AfterWorkCallback<void>(gpointer data) {
+gboolean TaskQueue::WorkCallback<void>(gpointer data) {
QueueData<void>* d = static_cast<QueueData<void>*>(data);
if (nullptr != d) {
- d->after_work_callback_();
+ d->work_callback_();
delete d;
}
return FALSE;
}
-template <>
-void* TaskQueue::WorkCallback<void>(void* data) {
- QueueData<void>* d = static_cast<QueueData<void>*>(data);
- if (nullptr != d) {
- d->work_callback_();
- if (d->after_work_callback_) {
- g_idle_add(AfterWorkCallback<void>, d);
- }
- }
- return nullptr;
+void TaskQueue::Queue(const std::function<void()>& work, const std::function<void()>& after_work) {
+ auto do_work = [work, after_work]() {
+ work();
+ after_work();
+ };
+ this->queue_worker_.add_job(do_work);
}
-void TaskQueue::Queue(const std::function<void()>& work, const std::function<void()>& after_work) {
- QueueData<void>* d = new QueueData<void>();
- d->work_callback_ = work;
- d->after_work_callback_ = after_work;
+void TaskQueue::Async(const std::function<void()>& work) {
+ this->async_worker_.add_job(work);
+}
- if (pthread_create(&d->thread_, nullptr, WorkCallback<void>, d) != 0) {
- LoggerE("Failed to create a background thread.");
- delete d;
- } else {
- pthread_detach(d->thread_);
+void TaskQueue::Async(const std::function<void(const common::AsyncToken& token)>& work,
+ const common::AsyncToken& token) {
+ auto do_work = [work, token]() { work(token); };
+ Async(do_work);
+}
+
+void TaskQueue::DeleteJobs() {
+ {
+ std::lock_guard<std::mutex> lck{this->queue_worker_.jobs_mtx};
+ this->queue_worker_.jobs.clear();
+ }
+ {
+ std::lock_guard<std::mutex> lck{this->async_worker_.jobs_mtx};
+ this->async_worker_.jobs.clear();
}
}
-void TaskQueue::Async(const std::function<void()>& work) {
+void TaskQueue::Stop() {
+ LoggerI("Stopping TaskQueue workers");
+ queue_worker_.stop();
+ async_worker_.stop();
+}
+
+void TaskQueue::ScheduleWorkInMainThread(const std::function<void()>& work) {
QueueData<void>* d = new QueueData<void>();
- d->after_work_callback_ = work;
- g_idle_add(AfterWorkCallback<void>, d);
+ d->work_callback_ = work;
+ g_idle_add(WorkCallback<void>, d);
}
} // namespace common
#include <functional>
#include <memory>
-#include "logger.h"
+#include "tizen_instance.h"
+#include "worker.h"
namespace common {
+/**
+ * TaskQueue is a class, which aggregates two instances of Worker class.
+ * The class contains two workers to prevent from blocking jobs, which should execute and return
+ * results after a few seconds.
+ */
class TaskQueue {
- public:
- TaskQueue(const TaskQueue&) = delete;
- TaskQueue& operator=(const TaskQueue&) = delete;
+ private:
+ TaskQueue() {
+ }
+ /**
+ * Worker for asynchronous 'quick' jobs.
+ * This queue is supposed to hold jobs, which are expected to take 'a little' time.
+ */
+ Worker async_worker_;
+ /**
+ * Worker for asynchronous 'long' jobs.
+ * This queue is supposed to hold jobs, which are expected to take 'long' time.
+ */
+ Worker queue_worker_;
+
+ public:
static TaskQueue& GetInstance();
+ ~TaskQueue() {
+ }
+
+ /**
+ * Method used to clear all delegated jobs during lifetime of UtilsInstance class.
+ * The UtilsInstance class is the first constructed and the last destructed instance of Instance
+ * class, which determines the lifetime of frame in the page.
+ */
+ void DeleteJobs();
+
+ /**
+ * Stops the workers. This method should be called only once, before shutting down the process.
+ * After that time, no more messages will be sent to Crosswalk.
+ */
+ void Stop();
/**
- * @brief Schedules work to be executed in a separate thread, after_work is going
- * to be called in main glib loop.
+ * @brief Schedule a 'long' job
*
- * @param[in] work - callback is going to be called in a separate thread
- * @param[in] after_work - callback is going to be called in main glib loop
+ * @param[in] work - callback is going to be called in a worker's thread
+ * @param[in] after_work - callback is going to be called after work
* @param[in] data - data passed to both callbacks
*/
template <class T>
const std::shared_ptr<T>& data);
/**
- * @brief Schedules work to be executed in a separate thread, after_work is going
- * to be called in main glib loop.
+ * @brief Schedule a 'long' job
*
- * @param[in] work - callback is going to be called in a separate thread
- * @param[in] after_work - callback is going to be called in main glib loop
+ * @param[in] work - callback is going to be called in a worker's thread
+ * @param[in] after_work - callback is going to be called after work function
*/
- void Queue(const std::function<void()>& work,
- const std::function<void()>& after_work = std::function<void()>());
+ void Queue(const std::function<void()>& work, const std::function<void()>& after_work = [] {});
/**
- * @brief Schedules work to be executed in main glib loop.
+ * @brief Schedule a 'quick' job
*
- * @param[in] work - callback is going to be called in main glib loop
+ * @param[in] work - callback is going to be called in a worker's thread
* @param[in] data - data passed to callback
*/
template <class T>
const std::shared_ptr<T>& data);
/**
- * @brief Schedules work to be executed in main glib loop.
+ * @brief Schedule a 'quick' job
*
- * @param[in] work - callback is going to be called in main glib loop
+ * @param[in] work - callback is going to be called in a worker's thread
*/
void Async(const std::function<void()>& work);
- private:
- TaskQueue() {
- }
+ /**
+ * @brief Schedule a 'quick' job requiring AsyncToken
+ *
+ * @param[in] work - callback is going to be called in a worker's thread
+ * @param[in] token - token passed to the work function
+ */
+ void Async(const std::function<void(const common::AsyncToken& token)>& work,
+ const common::AsyncToken& token);
+
+ /**
+ * @brief Schedules work to be executed in main glib loop
+ *
+ * This method should be used only for jobs, which HAVE to be executed in main loop of the
+ * process.
+ *
+ * @param[in] work - callback is going to be called in main glib loop
+ * @param[in] data - data passed to callback
+ */
+ template <class T>
+ void ScheduleWorkInMainThread(const std::function<void(const std::shared_ptr<T>&)>& work,
+ const std::shared_ptr<T>& data);
+ /**
+ * @brief Schedules work to be executed in main glib loop
+ *
+ * This method should be used only for jobs, which HAVE to be executed in main loop of the
+ * process.
+ *
+ * @param[in] work - callback is going to be called in main glib loop
+ */
+ void ScheduleWorkInMainThread(const std::function<void()>& work);
template <class T>
struct QueueData {
- pthread_t thread_;
std::function<void(const std::shared_ptr<T>&)> work_callback_;
- std::function<void(const std::shared_ptr<T>&)> after_work_callback_;
std::shared_ptr<T> data_;
};
template <class T>
- static void* WorkCallback(void* data);
+ static gboolean WorkCallback(gpointer data);
- template <class T>
- static gboolean AfterWorkCallback(gpointer data);
+ TaskQueue(const TaskQueue&) = delete;
+ TaskQueue& operator=(const TaskQueue&) = delete;
+ TaskQueue(TaskQueue&&) = delete;
+ TaskQueue& operator=(TaskQueue&&) = delete;
};
template <>
struct TaskQueue::QueueData<void> {
- pthread_t thread_;
std::function<void()> work_callback_;
- std::function<void()> after_work_callback_;
};
template <class T>
-gboolean TaskQueue::AfterWorkCallback(gpointer data) {
+gboolean TaskQueue::WorkCallback(gpointer data) {
QueueData<T>* d = static_cast<QueueData<T>*>(data);
if (nullptr != d) {
- d->after_work_callback_(d->data_);
+ d->work_callback_(d->data_);
delete d;
}
return FALSE;
}
-template <class T>
-void* TaskQueue::WorkCallback(void* data) {
- QueueData<T>* d = static_cast<QueueData<T>*>(data);
- if (nullptr != d) {
- d->work_callback_(d->data_);
- g_idle_add(AfterWorkCallback<T>, d);
- }
- return nullptr;
-}
-
template <class T>
void TaskQueue::Queue(const std::function<void(const std::shared_ptr<T>&)>& work,
const std::function<void(const std::shared_ptr<T>&)>& after_work,
const std::shared_ptr<T>& data) {
- QueueData<T>* d = new QueueData<T>();
- d->work_callback_ = work;
- d->after_work_callback_ = after_work;
- d->data_ = data;
-
- if (pthread_create(&d->thread_, nullptr, WorkCallback<T>, d) != 0) {
- LoggerE("Failed to create a background thread.");
- delete d;
- } else {
- pthread_detach(d->thread_);
- }
+ auto do_work = [data, work, after_work]() {
+ work(data);
+ after_work(data);
+ };
+ this->queue_worker_.add_job(do_work);
}
template <class T>
void TaskQueue::Async(const std::function<void(const std::shared_ptr<T>&)>& work,
const std::shared_ptr<T>& data) {
+ auto do_work = [data, work]() { work(data); };
+ this->async_worker_.add_job(do_work);
+}
+
+template <class T>
+void TaskQueue::ScheduleWorkInMainThread(const std::function<void(const std::shared_ptr<T>&)>& work,
+ const std::shared_ptr<T>& data) {
QueueData<T>* d = new QueueData<T>();
- d->after_work_callback_ = work;
+ d->work_callback_ = work;
d->data_ = data;
- g_idle_add(AfterWorkCallback<T>, d);
+ g_idle_add(WorkCallback<T>, d);
}
} // namespace common