1 // Copyright (c) 2016 The Zcash developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or https://www.opensource.org/licenses/mit-license.php .
6 #ifndef ASYNCRPCOPERATION_H
7 #define ASYNCRPCOPERATION_H
23 * AsyncRPCOperation objects are submitted to the AsyncRPCQueue for processing.
25 * To subclass AsyncRPCOperation, implement the main() method.
26 * Update the operation status as work is underway and completes.
27 * If main() can be interrupted, implement the cancel() method.
30 typedef std::string AsyncRPCOperationId;
32 typedef enum class operationStateEnum {
40 class AsyncRPCOperation {
43 virtual ~AsyncRPCOperation();
45 // You must implement this method in your subclass.
48 // Override this method if you can interrupt execution of main() in your subclass.
51 // Getters and setters
53 OperationStatus getState() const {
57 AsyncRPCOperationId getId() const {
61 int64_t getCreationTime() const {
62 return creation_time_;
65 // Override this method to add data to the default status object.
66 virtual UniValue getStatus() const;
68 UniValue getError() const;
70 UniValue getResult() const;
72 std::string getStateAsString() const;
74 int getErrorCode() const {
75 std::lock_guard<std::mutex> guard(lock_);
79 std::string getErrorMessage() const {
80 std::lock_guard<std::mutex> guard(lock_);
81 return error_message_;
84 bool isCancelled() const {
85 return OperationStatus::CANCELLED == getState();
88 bool isExecuting() const {
89 return OperationStatus::EXECUTING == getState();
92 bool isReady() const {
93 return OperationStatus::READY == getState();
96 bool isFailed() const {
97 return OperationStatus::FAILED == getState();
100 bool isSuccess() const {
101 return OperationStatus::SUCCESS == getState();
105 // The state_ is atomic because only it can be mutated externally.
106 // For example, the user initiates a shut down of the application, which closes
107 // the AsyncRPCQueue, which in turn invokes cancel() on all operations.
108 // The member variables below are protected rather than private in order to
109 // allow subclasses of AsyncRPCOperation the ability to access and update
110 // internal state. Currently, all operations are executed in a single-thread
111 // by a single worker.
112 mutable std::mutex lock_; // lock on this when read/writing non-atomics
115 std::string error_message_;
116 std::atomic<OperationStatus> state_;
117 std::chrono::time_point<std::chrono::system_clock> start_time_, end_time_;
119 void start_execution_clock();
120 void stop_execution_clock();
122 void set_state(OperationStatus state) {
123 this->state_.store(state);
126 void set_error_code(int errorCode) {
127 std::lock_guard<std::mutex> guard(lock_);
128 this->error_code_ = errorCode;
131 void set_error_message(std::string errorMessage) {
132 std::lock_guard<std::mutex> guard(lock_);
133 this->error_message_ = errorMessage;
136 void set_result(UniValue v) {
137 std::lock_guard<std::mutex> guard(lock_);
143 // Derived classes should write their own copy constructor and assignment operators
144 AsyncRPCOperation(const AsyncRPCOperation& orig);
145 AsyncRPCOperation& operator=( const AsyncRPCOperation& other );
147 // Initialized in the operation constructor, never to be modified again.
148 AsyncRPCOperationId id_;
149 int64_t creation_time_;
152 #endif /* ASYNCRPCOPERATION_H */