FutureWatcher.h 1.75 KB
Newer Older
Valentin Platzgummer's avatar
Valentin Platzgummer committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
#ifndef FUTUREWATCHER_H
#define FUTUREWATCHER_H

#include "FutureWatcherInterface.h"
#include <QTimer>
#include <future>

namespace nemo_interface {

//!
//! class similar to QFutureWatcher suitable for a std::future or
//! std::shared_future. \note For single thread use only.
//!
template <class T, template <class> class Future = std::future>
class FutureWatcher : public FutureWatcherInterface {
  enum class STATE { EMPTY, STARTED, FINISHED };

public:
  typedef Future<T> FutureType;

  explicit FutureWatcher(QObject *parent = nullptr)
      : FutureWatcherInterface(parent), _state(STATE::EMPTY) {
    _init();
  }

  FutureWatcher(const FutureType &f, QObject *parent = nullptr)
      : FutureWatcherInterface(parent), _future(f), _state(STATE::STARTED) {
    _init();
  }

  FutureType future() const { return _future; }

  void setFuture(const FutureType &future) {
    _future = future;
    _state = STATE::STARTED;
    _timer.start(1);
    emit started();
  }

  T result() { return _future.get(); }

  virtual void waitForFinished() override {
    if (_state == STATE::STARTED) {
      _timer.stop();
      _future.wait();
      _state = STATE::FINISHED;
    }
  }

  virtual bool isStarted() override { return _state == STATE::STARTED; }

  virtual bool isFinished() override { return _state == STATE::FINISHED; }

private:
  void _onTimeout() {
    if (_state == STATE::STARTED) {
      auto status = _future.wait_for(std::chrono::seconds(0));
      if (status == std::future_status::ready) {
        _state = STATE::FINISHED;
        emit finished();
      }
    }
  }

  void _init() {
    connect(&_timer, &QTimer::timeout, [this] { this->_onTimeout(); });
  }

  FutureType _future;
  QTimer _timer;
  STATE _state;
};
} // namespace nemo_interface
#endif // FUTUREWATCHER_H