10 changed files with 22 additions and 297 deletions
@ -1,94 +0,0 @@ |
|||||
/*
|
|
||||
This file is part of cpp-ethereum. |
|
||||
|
|
||||
cpp-ethereum is free software: you can redistribute it and/or modify |
|
||||
it under the terms of the GNU General Public License as published by |
|
||||
the Free Software Foundation, either version 3 of the License, or |
|
||||
(at your option) any later version. |
|
||||
|
|
||||
cpp-ethereum is distributed in the hope that it will be useful, |
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
GNU General Public License for more details. |
|
||||
|
|
||||
You should have received a copy of the GNU General Public License |
|
||||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|
||||
*/ |
|
||||
/** @file Miner.cpp
|
|
||||
* @author Gav Wood <i@gavwood.com> |
|
||||
* @author Giacomo Tazzari |
|
||||
* @date 2014 |
|
||||
*/ |
|
||||
|
|
||||
#include "Miner.h" |
|
||||
|
|
||||
#include <libdevcore/CommonIO.h> |
|
||||
#include "State.h" |
|
||||
using namespace std; |
|
||||
using namespace dev; |
|
||||
using namespace dev::eth; |
|
||||
|
|
||||
OldMiner::~OldMiner() {} |
|
||||
|
|
||||
LocalMiner::LocalMiner(MinerHost* _host, unsigned _id) |
|
||||
{ |
|
||||
setup(_host, _id); |
|
||||
} |
|
||||
|
|
||||
void LocalMiner::setup(MinerHost* _host, unsigned _id) |
|
||||
{ |
|
||||
AsyncMiner::setup(_host, _id); |
|
||||
setName("miner-" + toString(m_id)); |
|
||||
m_pow.reset(_host->turbo() ? new Ethash : (Ethash*)new EthashCPU); |
|
||||
} |
|
||||
|
|
||||
void LocalMiner::doWork() |
|
||||
{ |
|
||||
// Do some mining.
|
|
||||
if (m_miningStatus != Waiting && m_miningStatus != Mined) |
|
||||
{ |
|
||||
if (m_miningStatus == Preparing) |
|
||||
{ |
|
||||
m_host->setupState(m_mineState); |
|
||||
if (m_host->force() || m_mineState.pending().size()) |
|
||||
m_miningStatus = Mining; |
|
||||
else |
|
||||
m_miningStatus = Waiting; |
|
||||
|
|
||||
{ |
|
||||
Guard l(x_mineInfo); |
|
||||
m_mineProgress.best = (double)-1; |
|
||||
m_mineProgress.hashes = 0; |
|
||||
m_mineProgress.ms = 0; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (m_miningStatus == Mining) |
|
||||
{ |
|
||||
// Mine for a while.
|
|
||||
MineInfo mineInfo = m_mineState.mine(m_pow.get()); |
|
||||
|
|
||||
{ |
|
||||
Guard l(x_mineInfo); |
|
||||
m_mineProgress.best = min(m_mineProgress.best, mineInfo.best); |
|
||||
m_mineProgress.current = mineInfo.best; |
|
||||
m_mineProgress.requirement = mineInfo.requirement; |
|
||||
m_mineProgress.ms += 100; |
|
||||
m_mineProgress.hashes += mineInfo.hashes; |
|
||||
m_mineHistory.push_back(mineInfo); |
|
||||
} |
|
||||
if (mineInfo.completed) |
|
||||
{ |
|
||||
m_mineState.completeMine(); |
|
||||
m_host->onComplete(); |
|
||||
m_miningStatus = Mined; |
|
||||
} |
|
||||
else |
|
||||
m_host->onProgressed(); |
|
||||
} |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
this_thread::sleep_for(chrono::milliseconds(100)); |
|
||||
} |
|
||||
} |
|
@ -1,166 +0,0 @@ |
|||||
/*
|
|
||||
This file is part of cpp-ethereum. |
|
||||
|
|
||||
cpp-ethereum is free software: you can redistribute it and/or modify |
|
||||
it under the terms of the GNU General Public License as published by |
|
||||
the Free Software Foundation, either version 3 of the License, or |
|
||||
(at your option) any later version. |
|
||||
|
|
||||
cpp-ethereum is distributed in the hope that it will be useful, |
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
GNU General Public License for more details. |
|
||||
|
|
||||
You should have received a copy of the GNU General Public License |
|
||||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|
||||
*/ |
|
||||
/** @file Miner.h
|
|
||||
* @author Alex Leverington <nessence@gmail.com> |
|
||||
* @author Gav Wood <i@gavwood.com> |
|
||||
* @date 2014 |
|
||||
*/ |
|
||||
|
|
||||
#pragma once |
|
||||
|
|
||||
#include <thread> |
|
||||
#include <list> |
|
||||
#include <atomic> |
|
||||
#include <libdevcore/Common.h> |
|
||||
#include <libdevcore/Worker.h> |
|
||||
#include <libethcore/Common.h> |
|
||||
#include <libethcore/Miner.h> |
|
||||
#include "State.h" |
|
||||
|
|
||||
namespace dev |
|
||||
{ |
|
||||
|
|
||||
namespace eth |
|
||||
{ |
|
||||
|
|
||||
/**
|
|
||||
* @brief Class for hosting one or more Miners. |
|
||||
* @warning Must be implemented in a threadsafe manner since it will be called from multiple |
|
||||
* miner threads. |
|
||||
*/ |
|
||||
class MinerHost |
|
||||
{ |
|
||||
public: |
|
||||
virtual void setupState(State& _s) = 0; ///< Reset the given State object to the one that should be being mined.
|
|
||||
virtual void onProgressed() {} ///< Called once some progress has been made.
|
|
||||
virtual void onComplete() {} ///< Called once a block is found.
|
|
||||
virtual bool force() const = 0; ///< @returns true iff the Miner should mine regardless of the number of transactions.
|
|
||||
virtual bool turbo() const = 0; ///< @returns true iff the Miner should use GPU if possible.
|
|
||||
}; |
|
||||
|
|
||||
class OldMiner |
|
||||
{ |
|
||||
public: |
|
||||
virtual ~OldMiner(); |
|
||||
|
|
||||
virtual void noteStateChange() = 0; |
|
||||
virtual bool isComplete() const = 0; |
|
||||
virtual bytes const& blockData() const = 0; |
|
||||
}; |
|
||||
|
|
||||
class AsyncMiner: public OldMiner |
|
||||
{ |
|
||||
public: |
|
||||
/// Null constructor.
|
|
||||
AsyncMiner(): m_host(nullptr) {} |
|
||||
|
|
||||
/// Constructor.
|
|
||||
AsyncMiner(MinerHost* _host, unsigned _id = 0): m_host(_host), m_id(_id) {} |
|
||||
|
|
||||
/// Setup its basics.
|
|
||||
void setup(MinerHost* _host, unsigned _id = 0) { m_host = _host; m_id = _id; } |
|
||||
|
|
||||
/// Start mining.
|
|
||||
virtual void start() {} |
|
||||
|
|
||||
/// Stop mining.
|
|
||||
virtual void stop() {} |
|
||||
|
|
||||
/// @returns true iff the mining has been start()ed. It may still not be actually mining, depending on the host's turbo() & force().
|
|
||||
virtual bool isRunning() const { return false; } |
|
||||
|
|
||||
protected: |
|
||||
MinerHost* m_host = nullptr; ///< Our host.
|
|
||||
unsigned m_id = 0; ///< Our unique id.
|
|
||||
}; |
|
||||
|
|
||||
/**
|
|
||||
* @brief Implements Miner. |
|
||||
* To begin mining, use start() & stop(). noteStateChange() can be used to reset the mining and set up the |
|
||||
* State object according to the host. Use isRunning() to determine if the miner has been start()ed. |
|
||||
* Use isComplete() to determine if the miner has finished mining. |
|
||||
* |
|
||||
* blockData() can be used to retrieve the complete block, ready for insertion into the BlockChain. |
|
||||
* |
|
||||
* Information on the mining can be queried through miningProgress() and miningHistory(). |
|
||||
* @threadsafe |
|
||||
* @todo Signal Miner to restart once with condition variables. |
|
||||
*/ |
|
||||
class LocalMiner: public AsyncMiner, Worker |
|
||||
{ |
|
||||
public: |
|
||||
/// Null constructor.
|
|
||||
LocalMiner() {} |
|
||||
|
|
||||
/// Constructor.
|
|
||||
LocalMiner(MinerHost* _host, unsigned _id = 0); |
|
||||
|
|
||||
/// Move-constructor.
|
|
||||
LocalMiner(LocalMiner&& _m): Worker((Worker&&)_m) { std::swap(m_host, _m.m_host); std::swap(m_pow, _m.m_pow); } |
|
||||
|
|
||||
/// Move-assignment.
|
|
||||
LocalMiner& operator=(LocalMiner&& _m) { Worker::operator=((Worker&&)_m); std::swap(m_host, _m.m_host); std::swap(m_pow, _m.m_pow); return *this; } |
|
||||
|
|
||||
/// Destructor. Stops miner.
|
|
||||
~LocalMiner() { stop(); } |
|
||||
|
|
||||
/// Setup its basics.
|
|
||||
void setup(MinerHost* _host, unsigned _id = 0); |
|
||||
|
|
||||
/// Start mining.
|
|
||||
void start() { startWorking(); } |
|
||||
|
|
||||
/// Stop mining.
|
|
||||
void stop() { stopWorking(); } |
|
||||
|
|
||||
/// Call to notify Miner of a state change.
|
|
||||
virtual void noteStateChange() override { m_miningStatus = Preparing; } |
|
||||
|
|
||||
/// @returns true iff the mining has been start()ed. It may still not be actually mining, depending on the host's turbo() & force().
|
|
||||
bool isRunning() const override { return isWorking(); } |
|
||||
|
|
||||
/// @returns true if mining is complete.
|
|
||||
virtual bool isComplete() const override { return m_miningStatus == Mined; } |
|
||||
|
|
||||
/// @returns the internal State object.
|
|
||||
virtual bytes const& blockData() const override { return m_mineState.blockData(); } |
|
||||
|
|
||||
/// Check the progress of the mining.
|
|
||||
MineProgress miningProgress() const { Guard l(x_mineInfo); return m_mineProgress; } |
|
||||
|
|
||||
/// Get and clear the mining history.
|
|
||||
std::list<MineInfo> miningHistory() { Guard l(x_mineInfo); auto ret = m_mineHistory; m_mineHistory.clear(); return ret; } |
|
||||
|
|
||||
/// @returns the state on which we mined.
|
|
||||
State const& state() const { return m_mineState; } |
|
||||
|
|
||||
private: |
|
||||
/// Do some work on the mining.
|
|
||||
virtual void doWork(); |
|
||||
|
|
||||
enum MiningStatus { Waiting, Preparing, Mining, Mined, Stopping, Stopped }; |
|
||||
MiningStatus m_miningStatus = Waiting; ///< TODO: consider mutex/atomic variable.
|
|
||||
State m_mineState; ///< The state on which we are mining, generally equivalent to m_postMine.
|
|
||||
std::unique_ptr<EthashPoW> m_pow; ///< Our miner.
|
|
||||
|
|
||||
mutable Mutex x_mineInfo; ///< Lock for the mining progress & history.
|
|
||||
MineProgress m_mineProgress; ///< What's our progress?
|
|
||||
std::list<MineInfo> m_mineHistory; ///< What the history of our mining?
|
|
||||
}; |
|
||||
|
|
||||
} |
|
||||
} |
|
Loading…
Reference in new issue