summaryrefslogtreecommitdiff
path: root/Source/WebKit2/Platform/efl/WorkQueueEfl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit2/Platform/efl/WorkQueueEfl.cpp')
-rw-r--r--Source/WebKit2/Platform/efl/WorkQueueEfl.cpp131
1 files changed, 95 insertions, 36 deletions
diff --git a/Source/WebKit2/Platform/efl/WorkQueueEfl.cpp b/Source/WebKit2/Platform/efl/WorkQueueEfl.cpp
index 41ffedf53..6c505b41c 100644
--- a/Source/WebKit2/Platform/efl/WorkQueueEfl.cpp
+++ b/Source/WebKit2/Platform/efl/WorkQueueEfl.cpp
@@ -20,34 +20,29 @@
#include "config.h"
#include "WorkQueue.h"
+#include <sys/timerfd.h>
#include <wtf/Assertions.h>
-
-class TimerWorkItem {
-public:
- TimerWorkItem(int timerID, const Function<void()>& function, WorkQueue* queue)
- : m_function(function)
- , m_queue(queue)
- , m_timerID(timerID)
- {
- }
- ~TimerWorkItem() { }
-
- Function<void()> function() const { return m_function; }
- WorkQueue* queue() const { return m_queue; }
-
- int timerID() const { return m_timerID; }
-
-private:
- Function<void()> m_function;
- WorkQueue* m_queue;
- int m_timerID;
-};
+#include <wtf/CurrentTime.h>
static const int invalidSocketDescriptor = -1;
static const int threadMessageSize = 1;
static const char finishThreadMessage[] = "F";
static const char wakupThreadMessage[] = "W";
+PassOwnPtr<WorkQueue::TimerWorkItem> WorkQueue::TimerWorkItem::create(Function<void()> function, double expireTime)
+{
+ if (expireTime < 0)
+ return nullptr;
+
+ return adoptPtr(new TimerWorkItem(function, expireTime));
+}
+
+WorkQueue::TimerWorkItem::TimerWorkItem(Function<void()> function, double expireTime)
+ : m_function(function)
+ , m_expireTime(expireTime)
+{
+}
+
void WorkQueue::platformInitialize(const char* name)
{
int fds[2];
@@ -91,7 +86,7 @@ void WorkQueue::performFileDescriptorWork()
{
fd_set readFileDescriptorSet = m_fileDescriptorSet;
- if (select(m_maxFileDescriptor + 1, &readFileDescriptorSet, 0, 0, 0) >= 0) {
+ if (select(m_maxFileDescriptor + 1, &readFileDescriptorSet, 0, 0, getNextTimeOut()) >= 0) {
if (FD_ISSET(m_readFromPipeDescriptor, &readFileDescriptorSet)) {
char readBuf[threadMessageSize];
if (read(m_readFromPipeDescriptor, readBuf, threadMessageSize) == -1)
@@ -105,6 +100,74 @@ void WorkQueue::performFileDescriptorWork()
}
}
+struct timeval* WorkQueue::getNextTimeOut()
+{
+ MutexLocker locker(m_timerWorkItemsLock);
+ if (m_timerWorkItems.isEmpty())
+ return 0;
+
+ static struct timeval timeValue;
+ timeValue.tv_sec = 0;
+ timeValue.tv_usec = 0;
+ double timeOut = m_timerWorkItems[0]->expireTime() - currentTime();
+ if (timeOut > 0) {
+ timeValue.tv_sec = static_cast<long>(timeOut);
+ timeValue.tv_usec = static_cast<long>((timeOut - timeValue.tv_sec) * 1000000);
+ }
+
+ return &timeValue;
+}
+
+void WorkQueue::insertTimerWorkItem(PassOwnPtr<TimerWorkItem> item)
+{
+ if (!item)
+ return;
+
+ size_t position = 0;
+
+ // m_timerWorkItems should be ordered by expire time.
+ for (; position < m_timerWorkItems.size(); ++position)
+ if (item->expireTime() < m_timerWorkItems[position]->expireTime())
+ break;
+
+ m_timerWorkItems.insert(position, item);
+}
+
+void WorkQueue::performTimerWork()
+{
+ // Protects m_timerWorkItems.
+ m_timerWorkItemsLock.lock();
+
+ if (m_timerWorkItems.isEmpty()) {
+ m_timerWorkItemsLock.unlock();
+ return;
+ }
+
+ double current = currentTime();
+ Vector<OwnPtr<TimerWorkItem> > timerWorkItems;
+
+ // Copies all the timer work items in m_timerWorkItems to local vector.
+ m_timerWorkItems.swap(timerWorkItems);
+
+ for (size_t i = 0; i < timerWorkItems.size(); ++i) {
+ if (!timerWorkItems[i]->expired(current)) {
+ // If a timer work item does not expired, keep it to the m_timerWorkItems.
+ // m_timerWorkItems should be ordered by expire time.
+ insertTimerWorkItem(timerWorkItems[i].release());
+ continue;
+ }
+
+ // If a timer work item expired, dispatch the function of the work item.
+ // Before dispatching, m_timerWorkItemsLock should unlock for preventing deadlock,
+ // because it can be accessed inside the function of the timer work item dispatched.
+ m_timerWorkItemsLock.unlock();
+ timerWorkItems[i]->dispatch();
+ m_timerWorkItemsLock.lock();
+ }
+
+ m_timerWorkItemsLock.unlock();
+}
+
void WorkQueue::sendMessageToThread(const char* message)
{
if (write(m_writeToPipeDescriptor, message, threadMessageSize) == -1)
@@ -115,6 +178,7 @@ void* WorkQueue::workQueueThread(WorkQueue* workQueue)
{
while (workQueue->m_threadLoop) {
workQueue->performWork();
+ workQueue->performTimerWork();
workQueue->performFileDescriptorWork();
}
@@ -153,21 +217,16 @@ void WorkQueue::dispatch(const Function<void()>& function)
sendMessageToThread(wakupThreadMessage);
}
-bool WorkQueue::timerFired(void* data)
+void WorkQueue::dispatchAfterDelay(const Function<void()>& function, double delay)
{
- TimerWorkItem* item = static_cast<TimerWorkItem*>(data);
- if (item && item->queue()->m_isValid) {
- item->queue()->dispatch(item->function());
- item->queue()->m_timers.take(item->timerID());
- delete item;
- }
+ if (delay < 0)
+ return;
- return ECORE_CALLBACK_CANCEL;
-}
+ MutexLocker locker(m_timerWorkItemsLock);
+ OwnPtr<TimerWorkItem> timerWorkItem = TimerWorkItem::create(function, currentTime() + delay);
+ if (!timerWorkItem)
+ return;
-void WorkQueue::dispatchAfterDelay(const Function<void()>& function, double delay)
-{
- static int timerId = 1;
- m_timers.set(timerId, adoptPtr(ecore_timer_add(delay, reinterpret_cast<Ecore_Task_Cb>(timerFired), new TimerWorkItem(timerId, function, this))));
- timerId++;
+ insertTimerWorkItem(timerWorkItem.release());
+ sendMessageToThread(wakupThreadMessage);
}