forked from zcash/zcash
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathasyncrpcoperation.h
153 lines (116 loc) · 4.02 KB
/
asyncrpcoperation.h
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// Copyright (c) 2016 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef ASYNCRPCOPERATION_H
#define ASYNCRPCOPERATION_H
#include <string>
#include <atomic>
#include <map>
#include <chrono>
#include <memory>
#include <thread>
#include <utility>
#include <future>
#include <univalue.h>
using namespace std;
/**
* AsyncRPCOperation objects are submitted to the AsyncRPCQueue for processing.
*
* To subclass AsyncRPCOperation, implement the main() method.
* Update the operation status as work is underway and completes.
* If main() can be interrupted, implement the cancel() method.
*/
typedef std::string AsyncRPCOperationId;
typedef enum class operationStateEnum {
READY = 0,
EXECUTING,
CANCELLED,
FAILED,
SUCCESS
} OperationStatus;
class AsyncRPCOperation {
public:
AsyncRPCOperation();
virtual ~AsyncRPCOperation();
// You must implement this method in your subclass.
virtual void main();
// Override this method if you can interrupt execution of main() in your subclass.
void cancel();
// Getters and setters
OperationStatus getState() const {
return state_.load();
}
AsyncRPCOperationId getId() const {
return id_;
}
int64_t getCreationTime() const {
return creation_time_;
}
// Override this method to add data to the default status object.
virtual UniValue getStatus() const;
UniValue getError() const;
UniValue getResult() const;
std::string getStateAsString() const;
int getErrorCode() const {
std::lock_guard<std::mutex> guard(lock_);
return error_code_;
}
std::string getErrorMessage() const {
std::lock_guard<std::mutex> guard(lock_);
return error_message_;
}
bool isCancelled() const {
return OperationStatus::CANCELLED == getState();
}
bool isExecuting() const {
return OperationStatus::EXECUTING == getState();
}
bool isReady() const {
return OperationStatus::READY == getState();
}
bool isFailed() const {
return OperationStatus::FAILED == getState();
}
bool isSuccess() const {
return OperationStatus::SUCCESS == getState();
}
protected:
// The state_ is atomic because only it can be mutated externally.
// For example, the user initiates a shut down of the application, which closes
// the AsyncRPCQueue, which in turn invokes cancel() on all operations.
// The member variables below are protected rather than private in order to
// allow subclasses of AsyncRPCOperation the ability to access and update
// internal state. Currently, all operations are executed in a single-thread
// by a single worker.
mutable std::mutex lock_; // lock on this when read/writing non-atomics
UniValue result_;
int error_code_;
std::string error_message_;
std::atomic<OperationStatus> state_;
std::chrono::time_point<std::chrono::system_clock> start_time_, end_time_;
void start_execution_clock();
void stop_execution_clock();
void set_state(OperationStatus state) {
this->state_.store(state);
}
void set_error_code(int errorCode) {
std::lock_guard<std::mutex> guard(lock_);
this->error_code_ = errorCode;
}
void set_error_message(std::string errorMessage) {
std::lock_guard<std::mutex> guard(lock_);
this->error_message_ = errorMessage;
}
void set_result(UniValue v) {
std::lock_guard<std::mutex> guard(lock_);
this->result_ = v;
}
private:
// Derived classes should write their own copy constructor and assignment operators
AsyncRPCOperation(const AsyncRPCOperation& orig);
AsyncRPCOperation& operator=( const AsyncRPCOperation& other );
// Initialized in the operation constructor, never to be modified again.
AsyncRPCOperationId id_;
int64_t creation_time_;
};
#endif /* ASYNCRPCOPERATION_H */