swift
promise.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (C) 2017 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #ifndef SWIFT_MISC_PROMISE_H
7 #define SWIFT_MISC_PROMISE_H
8 
9 #include <utility>
10 
11 #include <QCoreApplication>
12 #include <QFuture>
13 #include <QFutureWatcher>
14 #include <QObject>
15 #include <QSharedPointer>
16 
17 namespace swift::misc
18 {
19 
20  namespace private_ns
21  {
25  template <typename T>
26  class CPromiseData final : public QFutureInterface<T>
27  {
28  public:
29  CPromiseData() { this->reportStarted(); }
30  ~CPromiseData()
31  {
32  if (this->isRunning()) { this->cancel(); }
33  }
34 
35  CPromiseData(const CPromiseData &) = delete;
36  CPromiseData &operator=(const CPromiseData &) = delete;
37  };
38 
40  template <typename T, typename F>
41  void doAfter(QFuture<T> future, QObject *context, F &&func)
42  {
43  QSharedPointer<QFutureWatcher<T>> watcher(new QFutureWatcher<T>, &QObject::deleteLater);
44  if (!context) { context = watcher.data(); }
45  QObject::connect(watcher.data(), &QFutureWatcher<T>::finished, context,
46  [watcher, func = std::forward<F>(func)]() mutable {
47  if (!watcher->isCanceled()) { func(watcher->future()); }
48  watcher.reset();
49  });
50  watcher->setFuture(future);
51  QCoreApplication::sendPostedEvents(watcher.data());
52  }
53  } // namespace private_ns
54 
58  template <typename T, typename F>
59  void doAfter(QFuture<T> future, QObject *context, F &&func)
60  {
61  private_ns::doAfter(future, context, std::forward<F>(func));
62  }
63 
67  template <typename F>
68  void doAfter(QFuture<void> future, QObject *context, F &&func)
69  {
70  private_ns::doAfter(future, context, [func = std::forward<F>(func)](auto &&) { func(); });
71  }
72 
76  template <typename T>
77  class CPromise
78  {
79  public:
81  QFuture<T> future() { return m_data->future(); }
82 
84  void abandon()
85  {
86  m_data->cancel();
87  m_data->reportFinished();
88  }
89 
91  void setResult(const T &value) { m_data->reportFinished(&value); }
92 
94  template <typename U>
95  void setResult(QFuture<U> future)
96  {
97  future.waitForFinished();
98  future.isCanceled() ? abandon() : setResult(future.result());
99  }
100 
102  template <typename U>
103  void chainResult(QFuture<U> future)
104  {
105  doAfter(future, nullptr, [*this](auto &&f) mutable { setResult(f); });
106  }
107 
110  template <typename F>
111  void setResultFrom(F &&func)
112  {
113  setResult(std::forward<F>(func)());
114  }
115 
116  private:
117  QSharedPointer<private_ns::CPromiseData<T>> m_data { new private_ns::CPromiseData<T> };
118  };
119 
123  template <>
124  class CPromise<void>
125  {
126  public:
128  QFuture<void> future() { return m_data->future(); }
129 
131  void abandon()
132  {
133  m_data->cancel();
134  m_data->reportFinished();
135  }
136 
138  void setResult() { m_data->reportFinished(); }
139 
141  template <typename U>
142  void setResult(QFuture<U> future)
143  {
144  future.waitForFinished();
145  future.isCanceled() ? abandon() : setResult();
146  }
147 
149  template <typename U>
150  void chainResult(QFuture<U> future)
151  {
152  doAfter(future, nullptr, [this](auto &&f) { setResult(f); });
153  }
154 
157  template <typename F>
158  void setResultFrom(F &&func)
159  {
160  std::forward<F>(func)();
161  setResult();
162  }
163 
164  private:
165  QSharedPointer<private_ns::CPromiseData<void>> m_data { new private_ns::CPromiseData<void> };
166  };
167 
168 } // namespace swift::misc
169 
170 #endif // SWIFT_MISC_PROMISE_H
void setResultFrom(F &&func)
Invoke a functor and mark the task as complete.
Definition: promise.h:158
void setResult(QFuture< U > future)
Wait for the given future, then mark the task as complete.
Definition: promise.h:142
void abandon()
Mark the task as cancelled.
Definition: promise.h:131
QFuture< void > future()
Return a future that can be used to detect when the task is complete.
Definition: promise.h:128
void setResult()
Mark the task as complete.
Definition: promise.h:138
void chainResult(QFuture< U > future)
When the given future is ready, mark this promise as complete.
Definition: promise.h:150
A promise-based interface to QFuture, similar to std::promise for std::future.
Definition: promise.h:78
void chainResult(QFuture< U > future)
When the given future is ready, use its result to set the result of this promise.
Definition: promise.h:103
QFuture< T > future()
Return a future that can be used to access the result.
Definition: promise.h:81
void setResultFrom(F &&func)
Invoke a functor and use its return value to set the result.
Definition: promise.h:111
void setResult(QFuture< U > future)
Set the result value from the given future. Will block if future is not ready.
Definition: promise.h:95
void setResult(const T &value)
Set the result value that will be made available through the future.
Definition: promise.h:91
void abandon()
Mark the result as cancelled.
Definition: promise.h:84
Free functions in swift::misc.
void doAfter(QFuture< T > future, QObject *context, F &&func)
Connect a slot or function to be invoked in the given context when a QFuture is finished.
Definition: promise.h:59
void doAfter(QFuture< void > future, QObject *context, F &&func)
Connect a slot or function to be invoked in the given context when a void QFuture is finished.
Definition: promise.h:68