KASync

future.h
1 /*
2  * Copyright 2014 Daniel Vrátil <[email protected]>
3  * Copyright 2016 Daniel Vrátil <[email protected]>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public License as
7  * published by the Free Software Foundation; either version 2 of
8  * the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef FUTURE_H
20 #define FUTURE_H
21 
22 #include "kasync_export.h"
23 
24 class QEventLoop;
25 
26 #include <type_traits>
27 
28 #include <QSharedDataPointer>
29 #include <QPointer>
30 #include <QVector>
31 #include <QEventLoop>
32 
33 namespace KAsync {
34 
35 //@cond PRIVATE
36 
37 class FutureWatcherBase;
38 template<typename T>
39 class FutureWatcher;
40 
41 namespace Private {
42 struct Execution;
43 class ExecutorBase;
44 
45 typedef QSharedPointer<Execution> ExecutionPtr;
46 } // namespace Private
47 
48 struct KASYNC_EXPORT Error
49 {
50  Error() : errorCode(0) {};
51  explicit Error(const char *message) : errorCode(1), errorMessage(QString::fromLatin1(message)) {}
52  Error(int code, const char *message) : errorCode(code), errorMessage(QString::fromLatin1(message)) {}
53  Error(int code, const QString &message) : errorCode(code), errorMessage(message) {}
54 
55  bool operator ==(const Error &other) const {
56  return (errorCode == other.errorCode) && (errorMessage == other.errorMessage);
57  }
58 
59  bool operator !=(const Error &other) const {
60  return !(*this == other);
61  }
62 
63  operator bool() const {
64  return (errorCode != 0);
65  }
66 
67  int errorCode;
69 private:
70  //Disable all implicit conversions except to bool, to avoid accidentally implicitly casting an error to a continuation argument.
71  //This becomes an issue if you forget to specify all template arguments, as the template argument deduction may employ a nonsensical implicit conversion from i.e. error to int. So as long as the Error object is used in the Job::then overload resolution no implicit conversions here.
72  //Of course this "solution" still breaks if you forget the template argument with a boolean parameter....
73  template <typename T>
74  operator T() const;
75 };
76 
77 class KASYNC_EXPORT FutureBase
78 {
79  friend struct KAsync::Private::Execution;
80  friend class FutureWatcherBase;
81 
82 public:
83  virtual ~FutureBase();
84 
85 
86  void setFinished();
87  bool isFinished() const;
88 
89  void setError(int code = 1, const QString &message = QString());
90  void setError(const Error &error);
91  void addError(const Error &error);
92  void clearErrors();
93  bool hasError() const;
94  int errorCode() const;
95  QString errorMessage() const;
96  QVector<Error> errors() const;
97 
98  void setProgress(qreal progress);
99  void setProgress(int processed, int total);
100 
101 protected:
102  class KASYNC_EXPORT PrivateBase : public QSharedData
103  {
104  public:
105  explicit PrivateBase(const KAsync::Private::ExecutionPtr &execution);
106  virtual ~PrivateBase();
107 
108  void releaseExecution();
109 
110  bool finished;
111  QVector<Error> errors;
112 
114  private:
116  };
117 
118  explicit FutureBase();
119  explicit FutureBase(FutureBase::PrivateBase *dd);
120  FutureBase(const FutureBase &other);
121  FutureBase &operator=(const FutureBase &other) = default;
122 
123  void addWatcher(KAsync::FutureWatcherBase *watcher);
124  void releaseExecution();
125 
126 protected:
128 };
129 
130 template<typename T>
131 class FutureWatcher;
132 
133 template<typename T>
134 class Future;
135 
136 template<typename T>
137 class FutureGeneric : public FutureBase
138 {
139  friend class FutureWatcher<T>;
140 
141 public:
142 
143  void waitForFinished() const
144  {
145  if (isFinished()) {
146  return;
147  }
148  FutureWatcher<T> watcher;
149  QEventLoop eventLoop;
151  &eventLoop, &QEventLoop::quit);
152  watcher.setFuture(*static_cast<const KAsync::Future<T>*>(this));
153  eventLoop.exec();
154  }
155 
156 protected:
157  //@cond PRIVATE
158  explicit FutureGeneric(const KAsync::Private::ExecutionPtr &execution)
159  : FutureBase(new Private(execution))
160  {}
161 
162  FutureGeneric(const FutureGeneric &) = default;
163  FutureGeneric &operator=(const FutureGeneric &) = default;
164 
165 protected:
166  class Private : public FutureBase::PrivateBase
167  {
168  public:
169  explicit Private(const KAsync::Private::ExecutionPtr &execution)
170  : FutureBase::PrivateBase(execution)
171  {}
172 
173  std::conditional_t<std::is_void<T>::value, int /* dummy */, T> value;
174  };
175 };
176 //@endcond
177 
178 
179 
195 template<typename T>
196 class Future : public FutureGeneric<T>
197 {
198  //@cond PRIVATE
199  friend class KAsync::Private::ExecutorBase;
200 
201  template<typename T_>
202  friend class KAsync::FutureWatcher;
203  //@endcond
204 public:
208  explicit Future()
209  : FutureGeneric<T>(KAsync::Private::ExecutionPtr())
210  {}
211 
215  Future(const Future<T> &other)
216  : FutureGeneric<T>(other)
217  {}
218 
230  void setValue(const T &value)
231  {
232  dataImpl()->value = value;
233  }
234 
240  T value() const
241  {
242  return dataImpl()->value;
243  }
244 
245  T *operator->()
246  {
247  return &(dataImpl()->value);
248  }
249 
250  const T *operator->() const
251  {
252  return &(dataImpl()->value);
253  }
254 
255  T &operator*()
256  {
257  return dataImpl()->value;
258  }
259 
260  const T &operator*() const
261  {
262  return dataImpl()->value;
263  }
264 
265 #ifdef ONLY_DOXYGEN
266 
275  void waitForFinished() const;
276 
288  void setFinished();
289 
295  bool isFinished() const;
296 
313  void setError(int code = 1, const QString &message = QString());
314 
321  int errorCode() const;
322 
329  QString errorMessage() const;
330 
339  void setProgress(int processed, int total);
340 
346  void setProgress(qreal progress);
347 
348 #endif // ONLY_DOXYGEN
349  void setResult(const T &value)
350  {
351  dataImpl()->value = value;
352  FutureBase::setFinished();
353  }
354 
355 protected:
356  //@cond PRIVATE
357  Future(const KAsync::Private::ExecutionPtr &execution)
358  : FutureGeneric<T>(execution)
359  {}
360  //@endcond
361 
362 private:
363  inline auto dataImpl()
364  {
365  return static_cast<typename FutureGeneric<T>::Private*>(this->d.data());
366  }
367 
368  inline auto dataImpl() const
369  {
370  return static_cast<typename FutureGeneric<T>::Private*>(this->d.data());
371  }
372 };
373 
385 template<>
386 class Future<void> : public FutureGeneric<void>
387 {
388  friend class KAsync::Private::ExecutorBase;
389 
390 public:
395  : FutureGeneric<void>(KAsync::Private::ExecutionPtr())
396  {}
397 
398 protected:
399  //@cond PRIVATE
400  Future(const KAsync::Private::ExecutionPtr &execution)
401  : FutureGeneric<void>(execution)
402  {}
403  //@endcond
404 };
405 
406 
407 
408 
409 //@cond PRIVATE
410 class KASYNC_EXPORT FutureWatcherBase : public QObject
411 {
412  Q_OBJECT
413 
414  friend class FutureBase;
415 
416 Q_SIGNALS:
417  void futureReady();
418  void futureProgress(qreal progress);
419 
420 protected:
421  FutureWatcherBase(QObject *parent = nullptr);
422 
423  virtual ~FutureWatcherBase();
424 
425  void futureReadyCallback();
426  void futureProgressCallback(qreal progress);
427 
428  void setFutureImpl(const KAsync::FutureBase &future);
429 
430 protected:
431  class Private {
432  public:
433  KAsync::FutureBase future;
434  };
435 
436  Private * const d;
437 
438 private:
439  Q_DISABLE_COPY(FutureWatcherBase)
440 };
441 //@endcond
442 
443 
455 template<typename T>
456 class FutureWatcher : public FutureWatcherBase
457 {
458  //@cond PRIVATE
459  friend class KAsync::FutureGeneric<T>;
460  //@endcond
461 
462 public:
466  FutureWatcher(QObject *parent = nullptr)
467  : FutureWatcherBase(parent)
468  {}
469 
470  ~FutureWatcher()
471  {}
472 
478  void setFuture(const KAsync::Future<T> &future)
479  {
480  setFutureImpl(*static_cast<const KAsync::FutureBase*>(&future));
481  }
482 
487  {
488  return *static_cast<KAsync::Future<T>*>(&d->future);
489  }
490 
491 #ifdef ONLY_DOXYGEN
492 Q_SIGNALS:
499  void futureReady();
500 
508  void futureProgress(qreal progress);
509 #endif
510 
511 private:
512  Q_DISABLE_COPY(FutureWatcher<T>)
513 };
514 
515 } // namespace Async
516 
517 KASYNC_EXPORT QDebug& operator<<(QDebug &dbg, const KAsync::Error &error);
518 
519 #endif // FUTURE_H
KCALENDARCORE_EXPORT QDataStream & operator<<(QDataStream &out, const KCalendarCore::Alarm::Ptr &)
void quit()
T value() const
Retrieve the result of the Future.
Definition: future.h:240
void setFuture(const KAsync::Future< T > &future)
Set future to watch.
Definition: future.h:478
FutureWatcher(QObject *parent=nullptr)
Constructs a new FutureWatcher that can watch for status of Future<T>.
Definition: future.h:466
void setValue(const T &value)
Set the result of the Future.
Definition: future.h:230
Future(const Future< T > &other)
Copy constructor.
Definition: future.h:215
int exec(QEventLoop::ProcessEventsFlags flags)
KCALUTILS_EXPORT QString errorMessage(const KCalendarCore::Exception &exception)
Future is a promise that is used by Job to deliver result of an asynchronous execution.
Definition: future.h:196
Future()
Constructor.
Definition: future.h:208
Definition: async.h:68
KDEGAMES_EXPORT bool hasError()
KAsync::Future< T > future() const
Returns currently watched future.
Definition: future.h:486
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
The FutureWatcher allows monitoring of Job results using signals and slots.
Definition: future.h:456
Future()
Constructor.
Definition: future.h:394
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Fri Jun 5 2020 22:57:35 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.