summaryrefslogtreecommitdiffstats
path: root/xmrstak/net/msgstruct.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'xmrstak/net/msgstruct.hpp')
-rw-r--r--xmrstak/net/msgstruct.hpp136
1 files changed, 136 insertions, 0 deletions
diff --git a/xmrstak/net/msgstruct.hpp b/xmrstak/net/msgstruct.hpp
new file mode 100644
index 0000000..f3a39b2
--- /dev/null
+++ b/xmrstak/net/msgstruct.hpp
@@ -0,0 +1,136 @@
+#pragma once
+#include <string>
+#include <string.h>
+#include <assert.h>
+
+// Structures that we use to pass info between threads constructors are here just to make
+// the stack allocation take up less space, heap is a shared resouce that needs locks too of course
+
+struct pool_job
+{
+ char sJobID[64];
+ uint8_t bWorkBlob[112];
+ uint64_t iTarget;
+ // \todo remove workaround needed for amd
+ uint32_t iTarget32;
+ uint32_t iWorkLen;
+ uint32_t iResumeCnt;
+
+ pool_job() : iWorkLen(0), iResumeCnt(0) {}
+ pool_job(const char* sJobID, uint64_t iTarget, const uint8_t* bWorkBlob, uint32_t iWorkLen) :
+ iTarget(iTarget), iWorkLen(iWorkLen), iResumeCnt(0)
+ {
+ assert(iWorkLen <= sizeof(pool_job::bWorkBlob));
+ memcpy(this->sJobID, sJobID, sizeof(pool_job::sJobID));
+ memcpy(this->bWorkBlob, bWorkBlob, iWorkLen);
+ }
+};
+
+struct job_result
+{
+ uint8_t bResult[32];
+ char sJobID[64];
+ uint32_t iNonce;
+
+ job_result() {}
+ job_result(const char* sJobID, uint32_t iNonce, const uint8_t* bResult) : iNonce(iNonce)
+ {
+ memcpy(this->sJobID, sJobID, sizeof(job_result::sJobID));
+ memcpy(this->bResult, bResult, sizeof(job_result::bResult));
+ }
+};
+
+
+enum ex_event_name { EV_INVALID_VAL, EV_SOCK_READY, EV_SOCK_ERROR,
+ EV_POOL_HAVE_JOB, EV_MINER_HAVE_RESULT, EV_PERF_TICK, EV_RECONNECT,
+ EV_SWITCH_POOL, EV_DEV_POOL_EXIT, EV_USR_HASHRATE, EV_USR_RESULTS, EV_USR_CONNSTAT,
+ EV_HASHRATE_LOOP, EV_HTML_HASHRATE, EV_HTML_RESULTS, EV_HTML_CONNSTAT, EV_HTML_JSON };
+
+/*
+ This is how I learned to stop worrying and love c++11 =).
+ Ghosts of endless heap allocations have finally been exorcised. Thanks
+ to the nifty magic of move semantics, string will only be allocated
+ once on the heap. Considering that it makes a jorney across stack,
+ heap alloced queue, to another stack before being finally processed
+ I think it is kind of nifty, don't you?
+ Also note that for non-arg events we only copy two qwords
+*/
+
+struct ex_event
+{
+ ex_event_name iName;
+ size_t iPoolId;
+
+ union
+ {
+ pool_job oPoolJob;
+ job_result oJobResult;
+ std::string sSocketError;
+ };
+
+ ex_event() { iName = EV_INVALID_VAL; iPoolId = 0;}
+ ex_event(std::string&& err, size_t id) : iName(EV_SOCK_ERROR), iPoolId(id), sSocketError(std::move(err)) { }
+ ex_event(job_result dat, size_t id) : iName(EV_MINER_HAVE_RESULT), iPoolId(id), oJobResult(dat) {}
+ ex_event(pool_job dat, size_t id) : iName(EV_POOL_HAVE_JOB), iPoolId(id), oPoolJob(dat) {}
+ ex_event(ex_event_name ev, size_t id = 0) : iName(ev), iPoolId(id) {}
+
+ // Delete the copy operators to make sure we are moving only what is needed
+ ex_event(ex_event const&) = delete;
+ ex_event& operator=(ex_event const&) = delete;
+
+ ex_event(ex_event&& from)
+ {
+ iName = from.iName;
+ iPoolId = from.iPoolId;
+
+ switch(iName)
+ {
+ case EV_SOCK_ERROR:
+ new (&sSocketError) std::string(std::move(from.sSocketError));
+ break;
+ case EV_MINER_HAVE_RESULT:
+ oJobResult = from.oJobResult;
+ break;
+ case EV_POOL_HAVE_JOB:
+ oPoolJob = from.oPoolJob;
+ break;
+ default:
+ break;
+ }
+ }
+
+ ex_event& operator=(ex_event&& from)
+ {
+ assert(this != &from);
+
+ if(iName == EV_SOCK_ERROR)
+ sSocketError.~basic_string();
+
+ iName = from.iName;
+ iPoolId = from.iPoolId;
+
+ switch(iName)
+ {
+ case EV_SOCK_ERROR:
+ new (&sSocketError) std::string();
+ sSocketError = std::move(from.sSocketError);
+ break;
+ case EV_MINER_HAVE_RESULT:
+ oJobResult = from.oJobResult;
+ break;
+ case EV_POOL_HAVE_JOB:
+ oPoolJob = from.oPoolJob;
+ break;
+ default:
+ break;
+ }
+
+ return *this;
+ }
+
+ ~ex_event()
+ {
+ if(iName == EV_SOCK_ERROR)
+ sSocketError.~basic_string();
+ }
+};
OpenPOWER on IntegriCloud