1 /*=============================================================================
2 
3   Library: CTK
4 
5   Copyright (c) German Cancer Research Center,
6     Division of Medical and Biological Informatics
7 
8   Licensed under the Apache License, Version 2.0 (the "License");
9   you may not use this file except in compliance with the License.
10   You may obtain a copy of the License at
11 
12     http://www.apache.org/licenses/LICENSE-2.0
13 
14   Unless required by applicable law or agreed to in writing, software
15   distributed under the License is distributed on an "AS IS" BASIS,
16   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   See the License for the specific language governing permissions and
18   limitations under the License.
19 
20 =============================================================================*/
21 
22 #ifndef CTKCMDLINEMODULEFUTUREINTERFACE_H
23 #define CTKCMDLINEMODULEFUTUREINTERFACE_H
24 
25 #include <ctkCommandLineModulesCoreExport.h>
26 
27 #include "ctkCmdLineModuleResult.h"
28 
29 #include <QFutureInterface>
30 #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
31 #include <QtCore>
32 #else
33 #include <QtConcurrent>
34 #include <qresultstore.h>
35 #endif
36 
37 
38 class ctkCmdLineModuleFuture;
39 class ctkCmdLineModuleFutureInterfacePrivate;
40 
41 /**
42  * \ingroup CommandLineModulesCore_API
43  *
44  * \brief A QFutureInterface specialization.
45  *
46  * This QFutureInterface must be used by custom backend implementations to retrieve
47  * a suitable QFuture object and to report state changes to it via this interface.
48  */
49 template <>
50 class CTK_CMDLINEMODULECORE_EXPORT QFutureInterface<ctkCmdLineModuleResult> : public QFutureInterfaceBase
51 {
52 
53 public:
54 
55   QFutureInterface(State initialState = NoState);
56 
57   QFutureInterface(const QFutureInterface &other);
58 
59   ~QFutureInterface();
60 
61   static QFutureInterface canceledResult();
62 
63   QFutureInterface& operator=(const QFutureInterface& other);
64 
65   inline ctkCmdLineModuleFuture future(); // implemented in ctkCmdLineModuleFuture.h
66 
67   bool canCancel() const;
68   void setCanCancel(bool canCancel);
69   bool canPause() const;
70   void setCanPause(bool canPause);
71 
72   inline void reportResult(const ctkCmdLineModuleResult *result, int index = -1);
73   inline void reportResult(const ctkCmdLineModuleResult &result, int index = -1);
74   inline void reportResults(const QVector<ctkCmdLineModuleResult> &results, int beginIndex = -1, int count = -1);
75   inline void reportFinished(const ctkCmdLineModuleResult *result = 0);
76 
77   void reportOutputData(const QByteArray& outputData);
78   void reportErrorData(const QByteArray& errorData);
79 
80   inline const ctkCmdLineModuleResult &resultReference(int index) const;
81   inline const ctkCmdLineModuleResult *resultPointer(int index) const;
82   inline QList<ctkCmdLineModuleResult> results();
83 
84   QByteArray outputData(int position = 0, int size = -1) const;
85   QByteArray errorData(int position = 0, int size = -1) const;
86 
87 private:
88 
89   friend struct ctkCmdLineModuleFutureWatcherPrivate;
90 
91 #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
resultStore()92   QtConcurrent::ResultStore<ctkCmdLineModuleResult> &resultStore()
93   { return static_cast<QtConcurrent::ResultStore<ctkCmdLineModuleResult> &>(resultStoreBase()); }
resultStore()94   const QtConcurrent::ResultStore<ctkCmdLineModuleResult> &resultStore() const
95   { return static_cast<const QtConcurrent::ResultStore<ctkCmdLineModuleResult> &>(resultStoreBase()); }
96 #elif (QT_VERSION < QT_VERSION_CHECK(5, 9, 0))
resultStore()97   QtPrivate::ResultStore<ctkCmdLineModuleResult> &resultStore()
98   { return static_cast<QtPrivate::ResultStore<ctkCmdLineModuleResult> &>(resultStoreBase()); }
resultStore()99   const QtPrivate::ResultStore<ctkCmdLineModuleResult> &resultStore() const
100   { return static_cast<const QtPrivate::ResultStore<ctkCmdLineModuleResult> &>(resultStoreBase()); }
101 #else
resultStore()102   QtPrivate::ResultStoreBase &resultStore()
103   { return static_cast<QtPrivate::ResultStoreBase &>(resultStoreBase()); }
resultStore()104   const QtPrivate::ResultStoreBase &resultStore() const
105   { return static_cast<const QtPrivate::ResultStoreBase &>(resultStoreBase()); }
106 #endif
107 
108   ctkCmdLineModuleFutureInterfacePrivate* d;
109 };
110 
reportResult(const ctkCmdLineModuleResult * result,int index)111 inline void QFutureInterface<ctkCmdLineModuleResult>::reportResult(const ctkCmdLineModuleResult *result, int index)
112 {
113     QMutexLocker locker(mutex());
114     if (this->queryState(Canceled) || this->queryState(Finished)) {
115         return;
116     }
117 
118 #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
119     QtConcurrent::ResultStore<ctkCmdLineModuleResult> &store = resultStore();
120 #elif (QT_VERSION < QT_VERSION_CHECK(5, 9, 0))
121     QtPrivate::ResultStore<ctkCmdLineModuleResult> &store = resultStore();
122 #else
123     QtPrivate::ResultStoreBase &store = resultStore();
124 #endif
125 
126     if (store.filterMode()) {
127         const int resultCountBefore = store.count();
128         store.addResult(index, result);
129         this->reportResultsReady(resultCountBefore, resultCountBefore + store.count());
130     } else {
131         const int insertIndex = store.addResult(index, result);
132         this->reportResultsReady(insertIndex, insertIndex + 1);
133     }
134 }
135 
reportResult(const ctkCmdLineModuleResult & result,int index)136 inline void QFutureInterface<ctkCmdLineModuleResult>::reportResult(const ctkCmdLineModuleResult &result, int index)
137 {
138     reportResult(&result, index);
139 }
140 
reportResults(const QVector<ctkCmdLineModuleResult> & _results,int beginIndex,int count)141 inline void QFutureInterface<ctkCmdLineModuleResult>::reportResults(const QVector<ctkCmdLineModuleResult> &_results, int beginIndex, int count)
142 {
143     QMutexLocker locker(mutex());
144     if (this->queryState(Canceled) || this->queryState(Finished)) {
145         return;
146     }
147 
148 #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
149     QtConcurrent::ResultStore<ctkCmdLineModuleResult> &store = resultStore();
150 #elif (QT_VERSION < QT_VERSION_CHECK(5, 9, 0))
151     QtPrivate::ResultStore<ctkCmdLineModuleResult> &store = resultStore();
152 #else
153     QtPrivate::ResultStoreBase &store = resultStore();
154 #endif
155 
156     if (store.filterMode()) {
157         const int resultCountBefore = store.count();
158         store.addResults(beginIndex, &_results, count);
159         this->reportResultsReady(resultCountBefore, store.count());
160     } else {
161         const int insertIndex = store.addResults(beginIndex, &_results, count);
162         this->reportResultsReady(insertIndex, insertIndex + _results.count());
163     }
164 }
165 
reportFinished(const ctkCmdLineModuleResult * result)166 inline void QFutureInterface<ctkCmdLineModuleResult>::reportFinished(const ctkCmdLineModuleResult *result)
167 {
168     if (result)
169         reportResult(result);
170     QFutureInterfaceBase::reportFinished();
171 }
172 
resultReference(int index)173 inline const ctkCmdLineModuleResult &QFutureInterface<ctkCmdLineModuleResult>::resultReference(int index) const
174 {
175     QMutexLocker lock(mutex());
176 #if (QT_VERSION < QT_VERSION_CHECK(5, 9, 0))
177     return resultStore().resultAt(index).value();
178 #else
179     return resultStore().resultAt(index).value<ctkCmdLineModuleResult>();
180 #endif
181 }
182 
resultPointer(int index)183 inline const ctkCmdLineModuleResult *QFutureInterface<ctkCmdLineModuleResult>::resultPointer(int index) const
184 {
185     QMutexLocker lock(mutex());
186 #if (QT_VERSION < QT_VERSION_CHECK(5, 9, 0))
187     return resultStore().resultAt(index).pointer();
188 #else
189     return resultStore().resultAt(index).pointer<ctkCmdLineModuleResult>();
190 #endif
191 }
192 
results()193 inline QList<ctkCmdLineModuleResult> QFutureInterface<ctkCmdLineModuleResult>::results()
194 {
195     if (this->isCanceled()) {
196         exceptionStore().throwPossibleException();
197         return QList<ctkCmdLineModuleResult>();
198     }
199     QFutureInterfaceBase::waitForResult(-1);
200 
201     QList<ctkCmdLineModuleResult> res;
202     QMutexLocker lock(mutex());
203 
204 #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
205     QtConcurrent::ResultIterator<ctkCmdLineModuleResult> it = resultStore().begin();
206 #elif (QT_VERSION < QT_VERSION_CHECK(5, 9, 0))
207     QtPrivate::ResultIterator<ctkCmdLineModuleResult> it = resultStore().begin();
208 #else
209     QtPrivate::ResultIteratorBase it = resultStore().begin();
210 #endif
211     while (it != resultStore().end()) {
212 #if (QT_VERSION < QT_VERSION_CHECK(5, 9, 0))
213         res.append(it.value());
214 #else
215         res.append(it.value<ctkCmdLineModuleResult>());
216 #endif
217         ++it;
218     }
219 
220     return res;
221 }
222 
223 typedef QFutureInterface<ctkCmdLineModuleResult> ctkCmdLineModuleFutureInterface;
224 
225 #endif // CTKCMDLINEMODULEFUTUREINTERFACE_H
226