MythTV master
taskqueue.cpp
Go to the documentation of this file.
1
2// Program Name: taskqueue.cpp
3// Created : Oct. 24, 2005
4//
5// Purpose : Used to process delayed tasks
6//
7// Copyright (c) 2005 David Blain <dblain@mythtv.org>
8//
9// Licensed under the GPL v2 or later, see LICENSE for details
10//
12#include "taskqueue.h"
13
14#include <thread>
15
17
19// Define Global instance
21
24
27//
28// Task Implementation
29//
32
33long Task::m_nTaskCount = 0;
34
36//
38
39Task::Task(const QString &debugName)
40 : ReferenceCounter(debugName),
41 m_nTaskId(m_nTaskCount++)
42{
43}
44
47//
48// Task Queue Implementation
49//
52
54//
56
58{
59 QMutexLocker locker(&g_pTaskQueueCreationLock);
61}
62
64//
66
68{
69 QMutexLocker locker(&g_pTaskQueueCreationLock);
70 delete g_pTaskQueue;
71 g_pTaskQueue = nullptr;
72}
73
75//
77
79{
80 LOG(VB_UPNP, LOG_INFO, "Starting TaskQueue Thread...");
81
82 start();
83
84 LOG(VB_UPNP, LOG_INFO, "TaskQueue Thread Started.");
85}
86
88//
90
92{
93 m_bTermRequested = true;
94
95 wait();
96
97 Clear();
98}
99
101{
102 m_bTermRequested = true;
103}
104
106//
108
110{
111 RunProlog();
112
113 LOG(VB_UPNP, LOG_INFO, "TaskQueue Thread Running.");
114
115 while ( !m_bTermRequested )
116 {
117 // ------------------------------------------------------------------
118 // Process Any Tasks that may need to be executed.
119 // ------------------------------------------------------------------
120
121 auto ttNow = nowAsDuration<std::chrono::microseconds>();
122
123 Task *pTask = GetNextExpiredTask( ttNow );
124 if (pTask != nullptr)
125 {
126 try
127 {
128 pTask->Execute( this );
129 pTask->DecrRef();
130 }
131 catch( ... )
132 {
133 LOG(VB_GENERAL, LOG_ERR, "Call to Execute threw an exception.");
134 }
135
136 }
137 // Make sure to throttle our processing.
138
139 std::this_thread::sleep_for(100ms);
140 }
141
142 RunEpilog();
143}
144
146//
148
150{
151 m_mutex.lock();
152
153 for (auto & task : m_mapTasks)
154 {
155 if (task.second != nullptr)
156 task.second->DecrRef();
157 }
158
159 m_mapTasks.clear();
160
161 m_mutex.unlock();
162}
163
169
170void TaskQueue::AddTask( std::chrono::milliseconds msec, Task *pTask )
171{
172 auto tt = nowAsDuration<std::chrono::microseconds>() + msec;
173
174 AddTaskAbsolute( tt, pTask );
175}
176
182
183void TaskQueue::AddTaskAbsolute( std::chrono::microseconds ttKey, Task *pTask )
184{
185 if (pTask != nullptr)
186 {
187 m_mutex.lock();
188 pTask->IncrRef();
189 m_mapTasks.insert( TaskMap::value_type( ttKey, pTask ));
190 m_mutex.unlock();
191 }
192}
193
198
200{
201
202 if (pTask != nullptr)
203 {
204 auto tt = nowAsDuration<std::chrono::microseconds>();
205
206 AddTaskAbsolute( tt, pTask );
207 }
208}
209
211//
213
214Task *TaskQueue::GetNextExpiredTask( std::chrono::microseconds tt, std::chrono::milliseconds nWithinMilliSecs /*=50*/ )
215{
216 Task *pTask = nullptr;
217
218 tt += nWithinMilliSecs ;
219
220 m_mutex.lock();
221
222 auto it = m_mapTasks.begin();
223 if (it != m_mapTasks.end())
224 {
225 std::chrono::microseconds ttTask = (*it).first;
226
227 if (ttTask < tt)
228 {
229 // Do not release here... caller must call release.
230
231 pTask = (*it).second;
232
233 m_mapTasks.erase( it );
234 }
235 }
236 m_mutex.unlock();
237
238 return pTask;
239}
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:49
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:180
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:267
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:193
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:284
General purpose reference counter.
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
virtual int IncrRef(void)
Increments reference count.
void AddTaskAbsolute(std::chrono::microseconds tt, Task *pTask)
Add a task to run at a specific time.
Definition: taskqueue.cpp:183
void run() override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: taskqueue.cpp:109
static void Shutdown()
Definition: taskqueue.cpp:67
Task * GetNextExpiredTask(std::chrono::microseconds tt, std::chrono::milliseconds nWithinMilliSecs=50ms)
Definition: taskqueue.cpp:214
bool m_bTermRequested
Definition: taskqueue.h:86
TaskMap m_mapTasks
Definition: taskqueue.h:84
QMutex m_mutex
Definition: taskqueue.h:85
~TaskQueue() override
Definition: taskqueue.cpp:91
static TaskQueue * g_pTaskQueue
Definition: taskqueue.h:80
void RequestTerminate()
Definition: taskqueue.cpp:100
void Clear()
Definition: taskqueue.cpp:149
void AddTask(std::chrono::milliseconds msec, Task *pTask)
Add a task to run in the future.
Definition: taskqueue.cpp:170
static TaskQueue * Instance()
Definition: taskqueue.cpp:57
Definition: taskqueue.h:48
static long m_nTaskCount
Definition: taskqueue.h:50
virtual void Execute(TaskQueue *pQueue)=0
Task(const QString &debugName)
Definition: taskqueue.cpp:39
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
static QMutex g_pTaskQueueCreationLock
Definition: taskqueue.cpp:22