*/
+
/** @file src/job.h
* @brief A parent class to represent long-running tasks which are run in their own thread.
*/
+
#ifndef DCPOMATIC_JOB_H
#define DCPOMATIC_JOB_H
+
#include "signaller.h"
-#include <boost/thread/mutex.hpp>
-#include <boost/enable_shared_from_this.hpp>
+#include <boost/atomic.hpp>
#include <boost/signals2.hpp>
#include <boost/thread.hpp>
+#include <boost/thread/mutex.hpp>
#include <string>
+
class Film;
+
/** @class Job
* @brief A parent class to represent long-running tasks which are run in their own thread.
*/
-class Job : public boost::enable_shared_from_this<Job>, public Signaller, public boost::noncopyable
+class Job : public std::enable_shared_from_this<Job>, public Signaller
{
public:
- explicit Job (boost::shared_ptr<const Film> film);
+ explicit Job (std::shared_ptr<const Film> film);
virtual ~Job ();
+ Job (Job const&) = delete;
+ Job& operator= (Job const&) = delete;
+
/** @return user-readable name of this job */
virtual std::string name () const = 0;
virtual std::string json_name () const = 0;
/** Run this job in the current thread. */
virtual void run () = 0;
+ /** @return true if it should be possible to notify when this job finishes */
+ virtual bool enable_notify () const {
+ return false;
+ }
void start ();
bool pause_by_user ();
void set_progress (float, bool force = false);
void sub (std::string);
boost::optional<float> progress () const;
+ boost::optional<float> seconds_since_last_progress_update () const;
- boost::shared_ptr<const Film> film () const {
+ std::shared_ptr<const Film> film () const {
return _film;
}
- void when_finished (boost::signals2::connection& connection, boost::function<void()> finished);
+ enum class Result {
+ RESULT_OK,
+ RESULT_ERROR, // we can't have plain ERROR on Windows
+ RESULT_CANCELLED
+ };
+
+ void when_finished(boost::signals2::connection& connection, std::function<void(Result)> finished);
+
+ void set_rate_limit_progress(bool rate_limit);
boost::signals2::signal<void()> Progress;
/** Emitted from the UI thread when the job is finished */
- boost::signals2::signal<void()> Finished;
+ boost::signals2::signal<void (Result)> Finished;
/** Emitted from the job thread when the job is finished */
- boost::signals2::signal<void()> FinishedImmediate;
+ boost::signals2::signal<void (Result)> FinishedImmediate;
protected:
FINISHED_CANCELLED ///< the job was cancelled
};
+ Result state_to_result(State state) const;
void set_state (State);
- void set_error (std::string s, std::string d);
+ void set_error (std::string s, std::string d = "");
void set_message (std::string m);
int elapsed_sub_time () const;
void check_for_interruption_or_pause ();
void stop_thread ();
- boost::shared_ptr<const Film> _film;
+ std::shared_ptr<const Film> _film;
+
+ time_t _start_time = 0;
+ time_t _finish_time = 0;
private:
void run_wrapper ();
void set_progress_common (boost::optional<float> p);
- boost::thread* _thread;
+ boost::thread _thread;
/** mutex for _state, _error*, _message */
mutable boost::mutex _state_mutex;
/** a message that should be given to the user when the job finishes */
boost::optional<std::string> _message;
- /** time that this job was started */
- time_t _start_time;
/** time that this sub-job was started */
time_t _sub_start_time;
std::string _sub_name;
boost::optional<float> _progress;
boost::optional<struct timeval> _last_progress_update;
+ /** true to limit emissions of the progress signal so that they don't
+ * come too often.
+ */
+ boost::atomic<bool> _rate_limit_progress;
+
/** condition to signal changes to pause/resume so that we know when to wake;
this could be a general _state_change if it made more sense.
*/
boost::condition_variable _pause_changed;
-
- int _ran_for;
};
#endif