libquentier  0.8.0
The library for rich desktop clients of Evernote service
Qt5Promise.h
1 /*
2  * Copyright 2021-2024 Dmitry Ivanov
3  *
4  * This file is part of libquentier
5  *
6  * libquentier is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, version 3 of the License.
9  *
10  * libquentier 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 Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with libquentier. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #pragma once
20 
21 #include <QFutureInterface>
22 
23 #include <type_traits>
24 
25 // Partial backport of QPromise from Qt6 to Qt5
26 template <typename T>
27 class QPromise
28 {
29  static_assert(
30  std::is_copy_constructible_v<T> || std::is_move_constructible_v<T> ||
31  std::is_same_v<T, void>,
32  "Type with copy or move constructors or type void is required");
33 
34 public:
35  QPromise() = default;
36 
37  Q_DISABLE_COPY(QPromise)
38 
39  QPromise(QPromise<T> && other) noexcept : d(other.d)
40  {
41  other.d = QFutureInterface<T>();
42  }
43 
44  QPromise(QFutureInterface<T> & other) : d(other) {}
45 
46  QPromise & operator=(QPromise<T> && other) noexcept
47  {
48  QPromise<T> tmp(std::move(other));
49  tmp.swap(*this);
50  return *this;
51  }
52 
53  ~QPromise()
54  {
55  // If QFutureInterface has no state, there is nothing to be done
56  if (d.queryState(QFutureInterfaceBase::State::NoState)) {
57  return;
58  }
59 
60  // Otherwise, if computation is not finished at this point, cancel
61  // potential waits
62  if (!d.queryState(QFutureInterfaceBase::State::Finished)) {
63  d.cancel();
64  finish(); // required to finalize the state
65  }
66  }
67 
68  // Core QPromise APIs
69  QFuture<T> future() const
70  {
71  return d.future();
72  }
73  template <
74  typename U,
75  typename = std::enable_if_t<
76  std::is_same_v<U, T> || std::is_convertible_v<U, T>>>
77  void addResult(U && result, int index = -1)
78  {
79  d.reportResult(std::forward<U>(result), index);
80  }
81 
82  void setException(const QException & e)
83  {
84  d.reportException(e);
85  }
86 
87  void start()
88  {
89  d.reportStarted();
90  }
91  void finish()
92  {
93  d.reportFinished();
94  }
95 
96  void suspendIfRequested()
97  {
98  d.suspendIfRequested();
99  }
100 
101  bool isCanceled() const
102  {
103  return d.isCanceled();
104  }
105 
106  // Progress methods
107  void setProgressRange(int minimum, int maximum)
108  {
109  d.setProgressRange(minimum, maximum);
110  }
111  void setProgressValue(int progressValue)
112  {
113  d.setProgressValue(progressValue);
114  }
115  void setProgressValueAndText(
116  int progressValue, const QString & progressText)
117  {
118  d.setProgressValueAndText(progressValue, progressText);
119  }
120 
121  void swap(QPromise<T> & other) noexcept
122  {
123  qSwap(this->d, other.d);
124  }
125 
126 private:
127  mutable QFutureInterface<T> d = QFutureInterface<T>();
128 };
129 
130 template <typename T>
131 inline void swap(QPromise<T> & a, QPromise<T> & b) noexcept
132 {
133  a.swap(b);
134 }
Definition: Qt5Promise.h:27