Fixes: Replace STL empty() with Qt style isEmpty()
[qtcontacts-tracker:qtcontacts-tracker.git] / src / engine / queue.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the Qt Mobility Components.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "queue.h"
43 #include "engine.h"
44
45 #include <lib/logger.h>
46 #include <lib/threadutils.h>
47
48 ////////////////////////////////////////////////////////////////////////////////
49
50 class QctQueueData : public QSharedData
51 {
52 public:
53     QQueue<QctTask*> m_queue;
54     QMutex m_queueMutex;
55 };
56
57 ////////////////////////////////////////////////////////////////////////////////
58
59 QctTask::QctTask(QObject *parent)
60     : QObject(parent)
61 {
62 }
63
64 QctTask::~QctTask()
65 {
66 }
67
68 ////////////////////////////////////////////////////////////////////////////////
69
70 QctQueue::QctQueue(QObject *parent)
71     : QObject(parent)
72     , d(new QctQueueData)
73 {
74 }
75
76 QctQueue::~QctQueue()
77 {
78 }
79
80 void
81 QctQueue::enqueue(QctTask *task)
82 {
83     QCT_SYNCHRONIZED(&d->m_queueMutex);
84
85     d->m_queue.enqueue(task);
86
87     // We need a direct connection to work without a global mainloop
88     connect(task, SIGNAL(finished()), this, SLOT(taskFinished()), Qt::DirectConnection);
89
90     if (d->m_queue.size() == 1) {
91         processQueue();
92     }
93 }
94
95 void
96 QctQueue::dequeue(QctTask *task)
97 {
98     QCT_SYNCHRONIZED(&d->m_queueMutex);
99     dequeueUnlocked(task);
100 }
101
102 void
103 QctQueue::dequeueUnlocked(QctTask *task)
104 {
105     if (d->m_queue.isEmpty()) {
106         return;
107     }
108
109     const QctTask *const head = d->m_queue.head();
110
111     if (not d->m_queue.removeOne(task)) {
112         return;
113     }
114
115     task->disconnect(this);
116
117     if (task == head) {
118         processQueue();
119     }
120 }
121
122 void
123 QctQueue::processQueue()
124 {
125     if (d->m_queue.isEmpty()) {
126         return;
127     }
128
129     const bool locked = d->m_queueMutex.tryLock();
130
131     if (locked) {
132         qctWarn("Queue must be called with the queue locked!");
133     }
134
135     QctTask *const task = d->m_queue.head();
136
137     // task->run should NEVER call any act on the queue before the mainloop
138     // returns, else it's a deadlock. If you want to remove the task immediately
139     // from the run() function, return false
140     if (not task->run()) {
141         dequeueUnlocked(task);
142     }
143
144     if (locked) {
145         d->m_queueMutex.unlock();
146     }
147 }
148
149 void
150 QctQueue::taskFinished()
151 {
152     QMutexLocker locker(&d->m_queueMutex);
153     Q_UNUSED(locker);
154
155     QctTask *const task = qobject_cast<QctTask*>(sender());
156
157     if (task == 0) {
158         qctWarn("Invalid sender");
159         return;
160     }
161
162     dequeueUnlocked(task);
163 }
164