Documentation of MARTY
A Modern ARtificial Theoretical phYsicist
resourcehandler.h
1 // This file is part of MARTY.
2 //
3 // MARTY is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
7 //
8 // MARTY is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with MARTY. If not, see <https://www.gnu.org/licenses/>.
15 
16  #ifndef RESSOURCEHANDLER_H
17 #define RESSOURCEHANDLER_H
18 
19 #include <iostream>
20 #include <functional>
21 #include <QFuture>
22 #include <QFutureWatcher>
23 #include <QMap>
24 #include <QString>
25 #include <QObject>
26 #include <QPixmap>
27 #include <QtConcurrent/QtConcurrent>
28 #include <cassert>
29 
30 class AutoMutex {
31 public:
32  AutoMutex() { mut.lock(); }
33  ~AutoMutex() { mut.unlock(); }
34 private:
35  QMutex mut;
36 };
37 
38 
39 class ResourceHandler: public QObject {
40 
41  Q_OBJECT
42 
43 public:
44  using Key = std::string;
45  using Value = QPixmap;
46 
47  using future_iterator
48  = typename QMap<Key, QFuture<Value>>::iterator;
49  using future_const_iterator
50  = typename QMap<Key, QFuture<Value>>::const_iterator;
51 
52  using iterator
53  = typename QMap<Key, Value>::iterator;
54  using const_iterator
55  = typename QMap<Key, Value>::const_iterator;
56 
57 public:
58  ResourceHandler(QObject *_parent)
59  :QObject(_parent)
60  {}
61 
62  ~ResourceHandler() override {}
63 
64  ResourceHandler(std::function<Value(Key const&)> const &t_builder)
65  {
66  setBuilder(t_builder);
67  }
68 
69  void setBuilder(std::function<Value(Key const&)> const &t_builder)
70  {
71  builder = t_builder;
72  }
73 
74  Value buildInMainThread(Key const &key) {
75  AutoMutex m;
76  if (auto pos = finalMap.find(key); pos != finalMap.end())
77  return pos.value();
78  finalMap[key] = builder(key);
79  return finalMap[key];
80  }
81 
82  bool isReady() const {
83  AutoMutex M;
84  return futureMap.empty();
85  }
86 
87  iterator find(Key const &key) {
88  auto res = finalMap.find(key);
89  return res;
90  }
91 
92  const_iterator find(Key const &key) const {
93  auto res = finalMap.find(key);
94  return res;
95  }
96 
97  future_iterator isFuture(Key const &key) {
98  AutoMutex M;
99  auto res = futureMap.find(key);
100  return res;
101  }
102 
103  future_const_iterator isFuture(Key const &key) const {
104  AutoMutex M;
105  auto res = futureMap.find(key);
106  return res;
107  }
108 
109  void sendKey(Key const &key) {
110  if (find(key) != finalMap.end())
111  return;
112  AutoMutex m;
113  if (isFuture(key) != futureMap.end())
114  return;
115  assert(builder);
116  QFutureWatcher<Value> *watcher = new QFutureWatcher<Value>;
117  futureMap[key] = QtConcurrent::run(builder, key);
118  auto endTask = [=]() { emit this->valueReady(key); };
119  connect(
120  watcher,
121  &QFutureWatcher<Value>::finished,
122  endTask
123  );
124  watcher->setFuture(futureMap[key]);
125  }
126 
127 signals:
128 
129  void valueReady(const std::string&);
130 
131 private:
132 
133  std::function<Value(Key const&)> builder;
134  QMap<Key, QFuture<Value>> futureMap;
135  QMap<Key, Value> finalMap;
136 };
137 
138 
139 #endif // RESSOURCEHANDLER_H
Definition: resourcehandler.h:30
Definition: resourcehandler.h:39