diff options
Diffstat (limited to 'Source/WebKit2/Platform/efl/WorkQueueEfl.cpp')
-rw-r--r-- | Source/WebKit2/Platform/efl/WorkQueueEfl.cpp | 131 |
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); } |