1/*
2 * Copyright (C) 2015, 2016 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include "Timer.h"
29#include <wtf/Deque.h>
30#include <wtf/Function.h>
31#include <wtf/WeakPtr.h>
32
33namespace WTF {
34class Lock;
35};
36
37namespace WebCore {
38
39template <typename T>
40class TaskDispatcher {
41public:
42 TaskDispatcher(T* context)
43 : m_context(context)
44 {
45 }
46
47 void postTask(WTF::Function<void()>&& f)
48 {
49 ASSERT(m_context);
50 m_context->postTask(WTFMove(f));
51 }
52
53private:
54 T* m_context;
55};
56
57template<>
58class TaskDispatcher<Timer> : public CanMakeWeakPtr<TaskDispatcher<Timer>> {
59public:
60 TaskDispatcher();
61 void postTask(WTF::Function<void()>&&);
62
63private:
64 static Timer& sharedTimer();
65 static WTF::Lock& sharedLock();
66 static void sharedTimerFired();
67 static Deque<WeakPtr<TaskDispatcher<Timer>>>& pendingDispatchers();
68
69 void dispatchOneTask();
70
71 Deque<WTF::Function<void()>> m_pendingTasks;
72};
73
74template <typename T, typename C = unsigned>
75class GenericTaskQueue : public CanMakeWeakPtr<GenericTaskQueue<T, C>> {
76public:
77 GenericTaskQueue()
78 : m_dispatcher()
79 {
80 }
81
82 GenericTaskQueue(T& t)
83 : m_dispatcher(&t)
84 {
85 }
86
87 GenericTaskQueue(T* t)
88 : m_dispatcher(t)
89 , m_isClosed(!t)
90 {
91 }
92
93 typedef WTF::Function<void ()> TaskFunction;
94
95 void enqueueTask(TaskFunction&& task)
96 {
97 if (m_isClosed)
98 return;
99
100 ++m_pendingTasks;
101 m_dispatcher.postTask([weakThis = makeWeakPtr(*this), task = WTFMove(task)] {
102 if (!weakThis)
103 return;
104 ASSERT(weakThis->m_pendingTasks);
105 --weakThis->m_pendingTasks;
106 task();
107 });
108 }
109
110 void close()
111 {
112 cancelAllTasks();
113 m_isClosed = true;
114 }
115
116 void cancelAllTasks()
117 {
118 CanMakeWeakPtr<GenericTaskQueue<T>>::weakPtrFactory().revokeAll();
119 m_pendingTasks = 0;
120 }
121
122 bool hasPendingTasks() const { return m_pendingTasks; }
123 bool isClosed() const { return m_isClosed; }
124
125private:
126 TaskDispatcher<T> m_dispatcher;
127 C m_pendingTasks { 0 };
128 bool m_isClosed { false };
129};
130
131}
132