2016-08-16 10:33:04 -07:00
|
|
|
// 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>
|
2016-09-08 12:32:29 -07:00
|
|
|
#include <memory>
|
|
|
|
#include <thread>
|
|
|
|
#include <utility>
|
|
|
|
#include <future>
|
2016-08-16 10:33:04 -07:00
|
|
|
|
|
|
|
#include "json/json_spirit_value.h"
|
|
|
|
#include "json/json_spirit_utils.h"
|
|
|
|
#include "json/json_spirit_reader_template.h"
|
|
|
|
#include "json/json_spirit_writer_template.h"
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace json_spirit;
|
|
|
|
|
|
|
|
/**
|
2016-08-28 19:50:39 -07:00
|
|
|
* AsyncRPCOperation objects are submitted to the AsyncRPCQueue for processing.
|
2016-08-16 10:33:04 -07:00
|
|
|
*
|
2016-08-28 19:50:39 -07:00
|
|
|
* To subclass AsyncRPCOperation, implement the main() method.
|
2016-08-16 10:33:04 -07:00
|
|
|
* Update the operation status as work is underway and completes.
|
2016-08-28 19:50:39 -07:00
|
|
|
* If main() can be interrupted, inmplement the cancel() method.
|
2016-08-16 10:33:04 -07:00
|
|
|
*/
|
|
|
|
|
|
|
|
typedef std::string AsyncRPCOperationId;
|
|
|
|
|
|
|
|
typedef enum class operationStateEnum {
|
|
|
|
READY = 0,
|
|
|
|
EXECUTING,
|
|
|
|
CANCELLED,
|
|
|
|
FAILED,
|
|
|
|
SUCCESS
|
|
|
|
} OperationStatus;
|
|
|
|
|
|
|
|
class AsyncRPCOperation {
|
|
|
|
public:
|
|
|
|
AsyncRPCOperation();
|
|
|
|
virtual ~AsyncRPCOperation();
|
|
|
|
|
2016-08-28 19:50:39 -07:00
|
|
|
// You must implement this method in your subclass.
|
2016-08-16 10:33:04 -07:00
|
|
|
virtual void main();
|
|
|
|
|
2016-08-28 19:50:39 -07:00
|
|
|
// Override this method if you can interrupt execution of main() in your subclass.
|
2016-08-16 10:33:04 -07:00
|
|
|
void cancel();
|
|
|
|
|
|
|
|
// Getters and setters
|
|
|
|
|
|
|
|
OperationStatus getState() const {
|
2016-08-28 19:50:39 -07:00
|
|
|
return state_.load();
|
2016-08-16 10:33:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
AsyncRPCOperationId getId() const {
|
2016-08-28 19:50:39 -07:00
|
|
|
return id_;
|
2016-08-16 10:33:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
int64_t getCreationTime() const {
|
2016-08-28 19:50:39 -07:00
|
|
|
return creation_time_;
|
2016-08-16 10:33:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
Value getStatus() const;
|
|
|
|
|
|
|
|
Value getError() const;
|
|
|
|
|
|
|
|
Value getResult() const;
|
2016-08-22 09:15:22 -07:00
|
|
|
|
|
|
|
std::string getStateAsString() const;
|
2016-08-16 10:33:04 -07:00
|
|
|
|
|
|
|
int getErrorCode() const {
|
2016-09-08 12:32:29 -07:00
|
|
|
std::lock_guard<std::mutex> guard(lock_);
|
2016-08-28 19:50:39 -07:00
|
|
|
return error_code_;
|
2016-08-16 10:33:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string getErrorMessage() const {
|
2016-09-08 12:32:29 -07:00
|
|
|
std::lock_guard<std::mutex> guard(lock_);
|
2016-08-28 19:50:39 -07:00
|
|
|
return error_message_;
|
2016-08-16 10:33:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
bool isCancelled() const {
|
2016-09-07 19:39:33 -07:00
|
|
|
return OperationStatus::CANCELLED == getState();
|
2016-08-16 10:33:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
bool isExecuting() const {
|
2016-09-07 19:39:33 -07:00
|
|
|
return OperationStatus::EXECUTING == getState();
|
2016-08-16 10:33:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
bool isReady() const {
|
2016-09-07 19:39:33 -07:00
|
|
|
return OperationStatus::READY == getState();
|
2016-08-16 10:33:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
bool isFailed() const {
|
2016-09-07 19:39:33 -07:00
|
|
|
return OperationStatus::FAILED == getState();
|
2016-08-16 10:33:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
bool isSuccess() const {
|
2016-09-07 19:39:33 -07:00
|
|
|
return OperationStatus::SUCCESS == getState();
|
2016-08-16 10:33:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
2016-09-07 19:39:33 -07:00
|
|
|
// 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.
|
2016-09-08 12:32:29 -07:00
|
|
|
mutable std::mutex lock_; // lock on this when read/writing non-atomics
|
2016-08-28 19:50:39 -07:00
|
|
|
Value result_;
|
|
|
|
int error_code_;
|
|
|
|
std::string error_message_;
|
|
|
|
std::atomic<OperationStatus> state_;
|
|
|
|
std::chrono::time_point<std::chrono::system_clock> start_time_, end_time_;
|
2016-08-16 10:33:04 -07:00
|
|
|
|
2016-08-28 19:50:39 -07:00
|
|
|
void start_execution_clock();
|
|
|
|
void stop_execution_clock();
|
2016-08-16 10:33:04 -07:00
|
|
|
|
2016-08-28 19:50:39 -07:00
|
|
|
void set_state(OperationStatus state) {
|
|
|
|
this->state_.store(state);
|
2016-08-16 10:33:04 -07:00
|
|
|
}
|
|
|
|
|
2016-08-28 19:50:39 -07:00
|
|
|
void set_error_code(int errorCode) {
|
2016-09-08 12:32:29 -07:00
|
|
|
std::lock_guard<std::mutex> guard(lock_);
|
2016-08-28 19:50:39 -07:00
|
|
|
this->error_code_ = errorCode;
|
2016-08-16 10:33:04 -07:00
|
|
|
}
|
|
|
|
|
2016-08-28 19:50:39 -07:00
|
|
|
void set_error_message(std::string errorMessage) {
|
2016-09-08 12:32:29 -07:00
|
|
|
std::lock_guard<std::mutex> guard(lock_);
|
2016-08-28 19:50:39 -07:00
|
|
|
this->error_message_ = errorMessage;
|
2016-08-16 10:33:04 -07:00
|
|
|
}
|
|
|
|
|
2016-08-28 19:50:39 -07:00
|
|
|
void set_result(Value v) {
|
2016-09-08 12:32:29 -07:00
|
|
|
std::lock_guard<std::mutex> guard(lock_);
|
2016-08-28 19:50:39 -07:00
|
|
|
this->result_ = v;
|
2016-08-16 10:33:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2016-08-28 19:50:39 -07:00
|
|
|
|
|
|
|
// Derived classes should write their own copy constructor and assignment operators
|
|
|
|
AsyncRPCOperation(const AsyncRPCOperation& orig);
|
|
|
|
AsyncRPCOperation& operator=( const AsyncRPCOperation& other );
|
2016-08-16 10:33:04 -07:00
|
|
|
|
2016-09-08 12:32:29 -07:00
|
|
|
// Initialized in the operation constructor, never to be modified again.
|
2016-08-28 19:50:39 -07:00
|
|
|
AsyncRPCOperationId id_;
|
|
|
|
int64_t creation_time_;
|
2016-08-16 10:33:04 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif /* ASYNCRPCOPERATION_H */
|
|
|
|
|