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
15
17// Define Global instance
19
22
25//
26// Task Implementation
27//
30
31long Task::m_nTaskCount = 0;
32
34//
36
37Task::Task(const QString &debugName)
38 : ReferenceCounter(debugName),
39 m_nTaskId(m_nTaskCount++)
40{
41}
42
45//
46// Task Queue Implementation
47//
50
52//
54
56{
57 QMutexLocker locker(&g_pTaskQueueCreationLock);
59}
60
62//
64
66{
67 QMutexLocker locker(&g_pTaskQueueCreationLock);
68 delete g_pTaskQueue;
69 g_pTaskQueue = nullptr;
70}
71
73//
75
77{
78 LOG(VB_UPNP, LOG_INFO, "Starting TaskQueue Thread...");
79
80 start();
81
82 LOG(VB_UPNP, LOG_INFO, "TaskQueue Thread Started.");
83}
84
86//
88
90{
91 m_bTermRequested = true;
92
93 wait();
94
95 Clear();
96}
97
99{
100 m_bTermRequested = true;
101}
102
104//
106
108{
109 RunProlog();
110
111 LOG(VB_UPNP, LOG_INFO, "TaskQueue Thread Running.");
112
113 while ( !m_bTermRequested )
114 {
115 // ------------------------------------------------------------------
116 // Process Any Tasks that may need to be executed.
117 // ------------------------------------------------------------------
118
119 auto ttNow = nowAsDuration<std::chrono::microseconds>();
120
121 Task *pTask = GetNextExpiredTask( ttNow );
122 if (pTask != nullptr)
123 {
124 try
125 {
126 pTask->Execute( this );
127 pTask->DecrRef();
128 }
129 catch( ... )
130 {
131 LOG(VB_GENERAL, LOG_ERR, "Call to Execute threw an exception.");
132 }
133
134 }
135 // Make sure to throttle our processing.
136
137 usleep( 100ms );
138 }
139
140 RunEpilog();
141}
142
144//
146
148{
149 m_mutex.lock();
150
151 for (auto & task : m_mapTasks)
152 {
153 if (task.second != nullptr)
154 task.second->DecrRef();
155 }
156
157 m_mapTasks.clear();
158
159 m_mutex.unlock();
160}
161
167
168void TaskQueue::AddTask( std::chrono::milliseconds msec, Task *pTask )
169{
170 auto tt = nowAsDuration<std::chrono::microseconds>() + msec;
171
172 AddTaskAbsolute( tt, pTask );
173}
174
180
181void TaskQueue::AddTaskAbsolute( std::chrono::microseconds ttKey, Task *pTask )
182{
183 if (pTask != nullptr)
184 {
185 m_mutex.lock();
186 pTask->IncrRef();
187 m_mapTasks.insert( TaskMap::value_type( ttKey, pTask ));
188 m_mutex.unlock();
189 }
190}
191
196
198{
199
200 if (pTask != nullptr)
201 {
202 auto tt = nowAsDuration<std::chrono::microseconds>();
203
204 AddTaskAbsolute( tt, pTask );
205 }
206}
207
209//
211
212Task *TaskQueue::GetNextExpiredTask( std::chrono::microseconds tt, std::chrono::milliseconds nWithinMilliSecs /*=50*/ )
213{
214 Task *pTask = nullptr;
215
216 tt += nWithinMilliSecs ;
217
218 m_mutex.lock();
219
220 auto it = m_mapTasks.begin();
221 if (it != m_mapTasks.end())
222 {
223 std::chrono::microseconds ttTask = (*it).first;
224
225 if (ttTask < tt)
226 {
227 // Do not release here... caller must call release.
228
229 pTask = (*it).second;
230
231 m_mapTasks.erase( it );
232 }
233 }
234 m_mutex.unlock();
235
236 return pTask;
237}
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:196
static void usleep(std::chrono::microseconds time)
Definition: mthread.cpp:335
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:283
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:209
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:300
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:181
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:107
static void Shutdown()
Definition: taskqueue.cpp:65
Task * GetNextExpiredTask(std::chrono::microseconds tt, std::chrono::milliseconds nWithinMilliSecs=50ms)
Definition: taskqueue.cpp:212
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:89
static TaskQueue * g_pTaskQueue
Definition: taskqueue.h:80
void RequestTerminate()
Definition: taskqueue.cpp:98
void Clear()
Definition: taskqueue.cpp:147
void AddTask(std::chrono::milliseconds msec, Task *pTask)
Add a task to run in the future.
Definition: taskqueue.cpp:168
static TaskQueue * Instance()
Definition: taskqueue.cpp:55
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:37
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
static QMutex g_pTaskQueueCreationLock
Definition: taskqueue.cpp:20