1 // Copyright 2014-2016 the openage authors. See copying.md for legal info.
2 
3 #pragma once
4 
5 #include <exception>
6 #include <memory>
7 
8 #include "typed_job_state_base.h"
9 
10 namespace openage {
11 namespace job {
12 
13 class JobGroup;
14 class JobManager;
15 
16 /**
17  * A job is a wrapper around a shared job state object and is returned by the
18  * job manager. It can be used to retrieve the current state of the job and its
19  * result.
20  * A job is a lightweight object which only contains a pointer to its internal
21  * shared state. Thus it can be copied around without worrying about
22  * performance. Further it is not necessary to create or pass pointers to job
23  * objects.
24  *
25  * @param T the job's result type
26  */
27 template<class T>
28 class Job {
29 private:
30 	/** A shared pointer to the job's shared state. */
31 	std::shared_ptr<TypedJobStateBase<T>> state;
32 
33 public:
34 	/**
35 	 * Creates an empty job object that is not bound to any state. Should only
36 	 * be used as dummy object.
37 	 */
38 	Job() = default;
39 
40 	/**
41 	 * Returns whether this job has finished. If this job wrapper has no
42 	 * assigned background job, true will be returned.
43 	 */
is_finished()44 	bool is_finished() const {
45 		if (this->state) {
46 			return this->state->finished.load();
47 		}
48 		return true;
49 	}
50 
51 	/**
52 	 * Returns this job's result if the background execution was successful. If
53 	 * an exception has happened, it will be rethrown. This method must not be
54 	 * called, if the job's execution has not yet finished.
55 	 */
get_result()56 	T get_result() {
57 		ENSURE(this->state, "getting result of a destroyed or uninitialised job");
58 		ENSURE(this->state->finished.load(), "trying to report a result of an unfinished job");
59 		if (this->state->exception != nullptr) {
60 			std::rethrow_exception(this->state->exception);
61 		} else {
62 			return std::move(this->state->result);
63 		}
64 	}
65 
66 private:
67 	/**
68 	 * Creates a job with the given shared state. This method may only be called
69 	 * by the job manager.
70 	 */
Job(std::shared_ptr<TypedJobStateBase<T>> state)71 	Job(std::shared_ptr<TypedJobStateBase<T>> state)
72 		:
73 		state{state} {
74 	}
75 
76 	/*
77 	 * Job manager and job group have to be friends of job in order to access the
78 	 * private constructor.
79 	 */
80 	friend class JobGroup;
81 	friend class JobManager;
82 };
83 
84 }
85 }
86