24 #include <condition_variable>
27 #include <boost/thread.hpp>
69 std::size_t
count()
const {
return m_queue.size(); }
71 std::size_t
size()
const {
return m_size; }
73 bool isEmpty()
const {
return m_queue.empty(); }
75 h256 nextHash()
const {
return m_queue.front().verified.info.sha3Uncles(); }
77 T
const&
next()
const {
return m_queue.front(); }
87 m_queue.emplace_back(std::move(_t));
88 m_size += m_queue.back().blockData.size();
96 m_size -= t.blockData.size();
103 return removeRange(m_queue.begin(), m_queue.begin() + _n);
108 std::vector<T> removed =
removeIf(sha3UnclesEquals(_hash));
109 return !removed.empty();
115 auto const removedBegin = std::remove_if(m_queue.begin(), m_queue.end(), _pred);
117 return removeRange(removedBegin, m_queue.end());
122 auto const it = std::find_if(m_queue.begin(), m_queue.end(), sha3UnclesEquals(_hash));
124 if (it == m_queue.end())
127 m_size -= it->blockData.size();
128 m_size += _t.blockData.size();
135 static std::function<bool(T
const&)> sha3UnclesEquals(
h256 const& _hash)
137 return [&_hash](T
const& _t) {
return _t.verified.info.sha3Uncles() == _hash; };
140 std::vector<T> removeRange(
typename std::deque<T>::iterator _begin,
typename std::deque<T>::iterator _end)
142 std::vector<T> ret(std::make_move_iterator(_begin), std::make_move_iterator(_end));
144 for (
auto it = ret.begin(); it != ret.end(); ++it)
145 m_size -= it->blockData.size();
147 m_queue.erase(_begin, _end);
151 std::deque<T> m_queue;
152 std::atomic<size_t> m_size = {0};
155 template<
class KeyType>
159 std::size_t
count()
const {
return m_map.size(); }
161 std::size_t
size()
const {
return m_size; }
163 bool isEmpty()
const {
return m_map.empty(); }
165 KeyType
firstKey()
const {
return m_map.begin()->first; }
175 auto hashAndBlock = std::make_pair(_hash, std::move(_blockData));
176 auto keyAndValue = std::make_pair(_key, std::move(hashAndBlock));
177 m_map.insert(std::move(keyAndValue));
178 m_size += _blockData.size();
184 auto const equalRange = m_map.equal_range(_key);
185 return removeRange(equalRange.first, equalRange.second);
191 return removeRange(m_map.begin(), m_map.upper_bound(_key));
196 using BlockMultimap = std::multimap<KeyType, std::pair<h256, bytes>>;
198 std::vector<std::pair<h256, bytes>> removeRange(
typename BlockMultimap::iterator _begin,
typename BlockMultimap::iterator _end)
200 std::vector<std::pair<h256, bytes>> removed;
201 std::size_t removedSize = 0;
202 for (
auto it = _begin; it != _end; ++it)
204 removed.push_back(std::move(it->second));
205 removedSize += removed.back().second.size();
208 m_size -= removedSize;
209 m_map.erase(_begin, _end);
215 std::atomic<size_t> m_size = {0};
239 void drain(std::vector<VerifiedBlock>& o_out,
unsigned _max);
252 std::pair<unsigned, unsigned>
items()
const {
ReadGuard l(m_lock);
return std::make_pair(m_readySet.size(), m_unknownSet.size()); }
272 template <
class T>
void setOnBad(T
const& _t) { m_onBad = _t; }
280 struct UnverifiedBlock
287 void noteReady_WITH_LOCK(
h256 const& _b);
289 bool invariants()
const override;
292 void collectUnknownBad_WITH_BOTH_LOCKS(
h256 const& _bad);
293 void updateBad_WITH_LOCK(
h256 const& _bad);
294 void drainVerified_WITH_BOTH_LOCKS();
296 std::size_t knownSize()
const;
297 std::size_t knownCount()
const;
298 std::size_t unknownSize()
const;
299 std::size_t unknownCount()
const;
301 BlockChain
const* m_bc;
303 mutable boost::shared_mutex m_lock;
307 SizedBlockMap<h256> m_unknown;
309 SizedBlockMap<time_t> m_future;
312 Signal<> m_onRoomAvailable;
314 mutable Mutex m_verification;
315 std::condition_variable m_moreToVerify;
316 SizedBlockQueue<VerifiedBlock> m_verified;
317 SizedBlockQueue<VerifiedBlock> m_verifying;
318 SizedBlockQueue<UnverifiedBlock> m_unverified;
320 std::vector<std::thread> m_verifiers;
321 std::atomic<bool> m_deleting = {
false};
323 std::function<void(Exception&)> m_onBad;
325 u256 m_drainingDifficulty;
331 std::ostream&
operator<<(std::ostream& _out, BlockQueueStatus
const& _s);