Renaming nano::prioritization to nano::scheduler::buckets. (#4274)

This puts the class in the correct component namespace and better describes what the class is modeling.
This commit is contained in:
clemahieu 2023-09-01 13:22:45 +01:00 committed by Colin LeMahieu
commit f400b28aa5
No known key found for this signature in database
GPG key ID: 43708520C8DFB938
7 changed files with 298 additions and 296 deletions

View file

@ -38,7 +38,7 @@ add_executable(
processing_queue.cpp
processor_service.cpp
peer_container.cpp
prioritization.cpp
scheduler_buckets.cpp
request_aggregator.cpp
signal_manager.cpp
signing.cpp

View file

@ -1,253 +0,0 @@
#include <nano/node/prioritization.hpp>
#include <nano/secure/common.hpp>
#include <gtest/gtest.h>
#include <unordered_set>
nano::keypair & keyzero ()
{
static nano::keypair result;
return result;
}
nano::keypair & key0 ()
{
static nano::keypair result;
return result;
}
nano::keypair & key1 ()
{
static nano::keypair result;
return result;
}
nano::keypair & key2 ()
{
static nano::keypair result;
return result;
}
nano::keypair & key3 ()
{
static nano::keypair result;
return result;
}
std::shared_ptr<nano::state_block> & blockzero ()
{
nano::block_builder builder;
static auto result = builder
.state ()
.account (keyzero ().pub)
.previous (0)
.representative (keyzero ().pub)
.balance (0)
.link (0)
.sign (keyzero ().prv, keyzero ().pub)
.work (0)
.build_shared ();
return result;
}
std::shared_ptr<nano::state_block> & block0 ()
{
nano::block_builder builder;
static auto result = builder
.state ()
.account (key0 ().pub)
.previous (0)
.representative (key0 ().pub)
.balance (nano::Gxrb_ratio)
.link (0)
.sign (key0 ().prv, key0 ().pub)
.work (0)
.build_shared ();
return result;
}
std::shared_ptr<nano::state_block> & block1 ()
{
nano::block_builder builder;
static auto result = builder
.state ()
.account (key1 ().pub)
.previous (0)
.representative (key1 ().pub)
.balance (nano::Mxrb_ratio)
.link (0)
.sign (key1 ().prv, key1 ().pub)
.work (0)
.build_shared ();
return result;
}
std::shared_ptr<nano::state_block> & block2 ()
{
nano::block_builder builder;
static auto result = builder
.state ()
.account (key2 ().pub)
.previous (0)
.representative (key2 ().pub)
.balance (nano::Gxrb_ratio)
.link (0)
.sign (key2 ().prv, key2 ().pub)
.work (0)
.build_shared ();
return result;
}
std::shared_ptr<nano::state_block> & block3 ()
{
nano::block_builder builder;
static auto result = builder
.state ()
.account (key3 ().pub)
.previous (0)
.representative (key3 ().pub)
.balance (nano::Mxrb_ratio)
.link (0)
.sign (key3 ().prv, key3 ().pub)
.work (0)
.build_shared ();
return result;
}
TEST (prioritization, construction)
{
nano::prioritization prioritization;
ASSERT_EQ (0, prioritization.size ());
ASSERT_TRUE (prioritization.empty ());
ASSERT_EQ (62, prioritization.bucket_count ());
}
TEST (prioritization, index_min)
{
nano::prioritization prioritization;
ASSERT_EQ (0, prioritization.index (std::numeric_limits<nano::uint128_t>::min ()));
}
TEST (prioritization, index_max)
{
nano::prioritization prioritization;
ASSERT_EQ (prioritization.bucket_count () - 1, prioritization.index (std::numeric_limits<nano::uint128_t>::max ()));
}
TEST (prioritization, insert_Gxrb)
{
nano::prioritization prioritization;
prioritization.push (1000, block0 (), nano::Gxrb_ratio);
ASSERT_EQ (1, prioritization.size ());
ASSERT_EQ (1, prioritization.bucket_size (48));
}
TEST (prioritization, insert_Mxrb)
{
nano::prioritization prioritization;
prioritization.push (1000, block1 (), nano::Mxrb_ratio);
ASSERT_EQ (1, prioritization.size ());
ASSERT_EQ (1, prioritization.bucket_size (13));
}
// Test two blocks with the same priority
TEST (prioritization, insert_same_priority)
{
nano::prioritization prioritization;
prioritization.push (1000, block0 (), nano::Gxrb_ratio);
prioritization.push (1000, block2 (), nano::Gxrb_ratio);
ASSERT_EQ (2, prioritization.size ());
ASSERT_EQ (2, prioritization.bucket_size (48));
}
// Test the same block inserted multiple times
TEST (prioritization, insert_duplicate)
{
nano::prioritization prioritization;
prioritization.push (1000, block0 (), nano::Gxrb_ratio);
prioritization.push (1000, block0 (), nano::Gxrb_ratio);
ASSERT_EQ (1, prioritization.size ());
ASSERT_EQ (1, prioritization.bucket_size (48));
}
TEST (prioritization, insert_older)
{
nano::prioritization prioritization;
prioritization.push (1000, block0 (), nano::Gxrb_ratio);
prioritization.push (1100, block2 (), nano::Gxrb_ratio);
ASSERT_EQ (block0 (), prioritization.top ());
prioritization.pop ();
ASSERT_EQ (block2 (), prioritization.top ());
prioritization.pop ();
}
TEST (prioritization, pop)
{
nano::prioritization prioritization;
ASSERT_TRUE (prioritization.empty ());
prioritization.push (1000, block0 (), nano::Gxrb_ratio);
ASSERT_FALSE (prioritization.empty ());
prioritization.pop ();
ASSERT_TRUE (prioritization.empty ());
}
TEST (prioritization, top_one)
{
nano::prioritization prioritization;
prioritization.push (1000, block0 (), nano::Gxrb_ratio);
ASSERT_EQ (block0 (), prioritization.top ());
}
TEST (prioritization, top_two)
{
nano::prioritization prioritization;
prioritization.push (1000, block0 (), nano::Gxrb_ratio);
prioritization.push (1, block1 (), nano::Mxrb_ratio);
ASSERT_EQ (block0 (), prioritization.top ());
prioritization.pop ();
ASSERT_EQ (block1 (), prioritization.top ());
prioritization.pop ();
ASSERT_TRUE (prioritization.empty ());
}
TEST (prioritization, top_round_robin)
{
nano::prioritization prioritization;
prioritization.push (1000, blockzero (), 0);
ASSERT_EQ (blockzero (), prioritization.top ());
prioritization.push (1000, block0 (), nano::Gxrb_ratio);
prioritization.push (1000, block1 (), nano::Mxrb_ratio);
prioritization.push (1100, block3 (), nano::Mxrb_ratio);
prioritization.pop (); // blockzero
EXPECT_EQ (block1 (), prioritization.top ());
prioritization.pop ();
EXPECT_EQ (block0 (), prioritization.top ());
prioritization.pop ();
EXPECT_EQ (block3 (), prioritization.top ());
prioritization.pop ();
EXPECT_TRUE (prioritization.empty ());
}
TEST (prioritization, trim_normal)
{
nano::prioritization prioritization{ 1 };
prioritization.push (1000, block0 (), nano::Gxrb_ratio);
prioritization.push (1100, block2 (), nano::Gxrb_ratio);
ASSERT_EQ (1, prioritization.size ());
ASSERT_EQ (block0 (), prioritization.top ());
}
TEST (prioritization, trim_reverse)
{
nano::prioritization prioritization{ 1 };
prioritization.push (1100, block2 (), nano::Gxrb_ratio);
prioritization.push (1000, block0 (), nano::Gxrb_ratio);
ASSERT_EQ (1, prioritization.size ());
ASSERT_EQ (block0 (), prioritization.top ());
}
TEST (prioritization, trim_even)
{
nano::prioritization prioritization{ 2 };
prioritization.push (1000, block0 (), nano::Gxrb_ratio);
prioritization.push (1100, block2 (), nano::Gxrb_ratio);
ASSERT_EQ (1, prioritization.size ());
ASSERT_EQ (block0 (), prioritization.top ());
prioritization.push (1000, block1 (), nano::Mxrb_ratio);
ASSERT_EQ (2, prioritization.size ());
ASSERT_EQ (block0 (), prioritization.top ());
prioritization.pop ();
ASSERT_EQ (block1 (), prioritization.top ());
}

View file

@ -0,0 +1,253 @@
#include <nano/node/scheduler/buckets.hpp>
#include <nano/secure/common.hpp>
#include <gtest/gtest.h>
#include <unordered_set>
nano::keypair & keyzero ()
{
static nano::keypair result;
return result;
}
nano::keypair & key0 ()
{
static nano::keypair result;
return result;
}
nano::keypair & key1 ()
{
static nano::keypair result;
return result;
}
nano::keypair & key2 ()
{
static nano::keypair result;
return result;
}
nano::keypair & key3 ()
{
static nano::keypair result;
return result;
}
std::shared_ptr<nano::state_block> & blockzero ()
{
nano::block_builder builder;
static auto result = builder
.state ()
.account (keyzero ().pub)
.previous (0)
.representative (keyzero ().pub)
.balance (0)
.link (0)
.sign (keyzero ().prv, keyzero ().pub)
.work (0)
.build_shared ();
return result;
}
std::shared_ptr<nano::state_block> & block0 ()
{
nano::block_builder builder;
static auto result = builder
.state ()
.account (key0 ().pub)
.previous (0)
.representative (key0 ().pub)
.balance (nano::Gxrb_ratio)
.link (0)
.sign (key0 ().prv, key0 ().pub)
.work (0)
.build_shared ();
return result;
}
std::shared_ptr<nano::state_block> & block1 ()
{
nano::block_builder builder;
static auto result = builder
.state ()
.account (key1 ().pub)
.previous (0)
.representative (key1 ().pub)
.balance (nano::Mxrb_ratio)
.link (0)
.sign (key1 ().prv, key1 ().pub)
.work (0)
.build_shared ();
return result;
}
std::shared_ptr<nano::state_block> & block2 ()
{
nano::block_builder builder;
static auto result = builder
.state ()
.account (key2 ().pub)
.previous (0)
.representative (key2 ().pub)
.balance (nano::Gxrb_ratio)
.link (0)
.sign (key2 ().prv, key2 ().pub)
.work (0)
.build_shared ();
return result;
}
std::shared_ptr<nano::state_block> & block3 ()
{
nano::block_builder builder;
static auto result = builder
.state ()
.account (key3 ().pub)
.previous (0)
.representative (key3 ().pub)
.balance (nano::Mxrb_ratio)
.link (0)
.sign (key3 ().prv, key3 ().pub)
.work (0)
.build_shared ();
return result;
}
TEST (buckets, construction)
{
nano::scheduler::buckets buckets;
ASSERT_EQ (0, buckets.size ());
ASSERT_TRUE (buckets.empty ());
ASSERT_EQ (62, buckets.bucket_count ());
}
TEST (buckets, index_min)
{
nano::scheduler::buckets buckets;
ASSERT_EQ (0, buckets.index (std::numeric_limits<nano::uint128_t>::min ()));
}
TEST (buckets, index_max)
{
nano::scheduler::buckets buckets;
ASSERT_EQ (buckets.bucket_count () - 1, buckets.index (std::numeric_limits<nano::uint128_t>::max ()));
}
TEST (buckets, insert_Gxrb)
{
nano::scheduler::buckets buckets;
buckets.push (1000, block0 (), nano::Gxrb_ratio);
ASSERT_EQ (1, buckets.size ());
ASSERT_EQ (1, buckets.bucket_size (48));
}
TEST (buckets, insert_Mxrb)
{
nano::scheduler::buckets buckets;
buckets.push (1000, block1 (), nano::Mxrb_ratio);
ASSERT_EQ (1, buckets.size ());
ASSERT_EQ (1, buckets.bucket_size (13));
}
// Test two blocks with the same priority
TEST (buckets, insert_same_priority)
{
nano::scheduler::buckets buckets;
buckets.push (1000, block0 (), nano::Gxrb_ratio);
buckets.push (1000, block2 (), nano::Gxrb_ratio);
ASSERT_EQ (2, buckets.size ());
ASSERT_EQ (2, buckets.bucket_size (48));
}
// Test the same block inserted multiple times
TEST (buckets, insert_duplicate)
{
nano::scheduler::buckets buckets;
buckets.push (1000, block0 (), nano::Gxrb_ratio);
buckets.push (1000, block0 (), nano::Gxrb_ratio);
ASSERT_EQ (1, buckets.size ());
ASSERT_EQ (1, buckets.bucket_size (48));
}
TEST (buckets, insert_older)
{
nano::scheduler::buckets buckets;
buckets.push (1000, block0 (), nano::Gxrb_ratio);
buckets.push (1100, block2 (), nano::Gxrb_ratio);
ASSERT_EQ (block0 (), buckets.top ());
buckets.pop ();
ASSERT_EQ (block2 (), buckets.top ());
buckets.pop ();
}
TEST (buckets, pop)
{
nano::scheduler::buckets buckets;
ASSERT_TRUE (buckets.empty ());
buckets.push (1000, block0 (), nano::Gxrb_ratio);
ASSERT_FALSE (buckets.empty ());
buckets.pop ();
ASSERT_TRUE (buckets.empty ());
}
TEST (buckets, top_one)
{
nano::scheduler::buckets buckets;
buckets.push (1000, block0 (), nano::Gxrb_ratio);
ASSERT_EQ (block0 (), buckets.top ());
}
TEST (buckets, top_two)
{
nano::scheduler::buckets buckets;
buckets.push (1000, block0 (), nano::Gxrb_ratio);
buckets.push (1, block1 (), nano::Mxrb_ratio);
ASSERT_EQ (block0 (), buckets.top ());
buckets.pop ();
ASSERT_EQ (block1 (), buckets.top ());
buckets.pop ();
ASSERT_TRUE (buckets.empty ());
}
TEST (buckets, top_round_robin)
{
nano::scheduler::buckets buckets;
buckets.push (1000, blockzero (), 0);
ASSERT_EQ (blockzero (), buckets.top ());
buckets.push (1000, block0 (), nano::Gxrb_ratio);
buckets.push (1000, block1 (), nano::Mxrb_ratio);
buckets.push (1100, block3 (), nano::Mxrb_ratio);
buckets.pop (); // blockzero
EXPECT_EQ (block1 (), buckets.top ());
buckets.pop ();
EXPECT_EQ (block0 (), buckets.top ());
buckets.pop ();
EXPECT_EQ (block3 (), buckets.top ());
buckets.pop ();
EXPECT_TRUE (buckets.empty ());
}
TEST (buckets, trim_normal)
{
nano::scheduler::buckets buckets{ 1 };
buckets.push (1000, block0 (), nano::Gxrb_ratio);
buckets.push (1100, block2 (), nano::Gxrb_ratio);
ASSERT_EQ (1, buckets.size ());
ASSERT_EQ (block0 (), buckets.top ());
}
TEST (buckets, trim_reverse)
{
nano::scheduler::buckets buckets{ 1 };
buckets.push (1100, block2 (), nano::Gxrb_ratio);
buckets.push (1000, block0 (), nano::Gxrb_ratio);
ASSERT_EQ (1, buckets.size ());
ASSERT_EQ (block0 (), buckets.top ());
}
TEST (buckets, trim_even)
{
nano::scheduler::buckets buckets{ 2 };
buckets.push (1000, block0 (), nano::Gxrb_ratio);
buckets.push (1100, block2 (), nano::Gxrb_ratio);
ASSERT_EQ (1, buckets.size ());
ASSERT_EQ (block0 (), buckets.top ());
buckets.push (1000, block1 (), nano::Mxrb_ratio);
ASSERT_EQ (2, buckets.size ());
ASSERT_EQ (block0 (), buckets.top ());
buckets.pop ();
ASSERT_EQ (block1 (), buckets.top ());
}

View file

@ -163,8 +163,6 @@ add_library(
peer_exclusion.cpp
portmapping.hpp
portmapping.cpp
prioritization.cpp
prioritization.hpp
process_live_dispatcher.cpp
process_live_dispatcher.hpp
repcrawler.hpp
@ -196,6 +194,8 @@ add_library(
rocksdb/rocksdb_iterator.hpp
rocksdb/rocksdb_txn.hpp
rocksdb/rocksdb_txn.cpp
scheduler/buckets.cpp
scheduler/buckets.hpp
scheduler/component.hpp
scheduler/component.cpp
scheduler/hinted.hpp

View file

@ -1,21 +1,21 @@
#include <nano/lib/blocks.hpp>
#include <nano/lib/utility.hpp>
#include <nano/node/prioritization.hpp>
#include <nano/node/scheduler/buckets.hpp>
#include <string>
bool nano::prioritization::value_type::operator< (value_type const & other_a) const
bool nano::scheduler::buckets::value_type::operator< (value_type const & other_a) const
{
return time < other_a.time || (time == other_a.time && block->hash () < other_a.block->hash ());
}
bool nano::prioritization::value_type::operator== (value_type const & other_a) const
bool nano::scheduler::buckets::value_type::operator== (value_type const & other_a) const
{
return time == other_a.time && block->hash () == other_a.block->hash ();
}
/** Moves the bucket pointer to the next bucket */
void nano::prioritization::next ()
void nano::scheduler::buckets::next ()
{
++current;
if (current == schedule.end ())
@ -25,19 +25,19 @@ void nano::prioritization::next ()
}
/** Seek to the next non-empty bucket, if one exists */
void nano::prioritization::seek ()
void nano::scheduler::buckets::seek ()
{
next ();
for (std::size_t i = 0, n = schedule.size (); buckets[*current].empty () && i < n; ++i)
for (std::size_t i = 0, n = schedule.size (); buckets_m[*current].empty () && i < n; ++i)
{
next ();
}
}
/** Initialise the schedule vector */
void nano::prioritization::populate_schedule ()
void nano::scheduler::buckets::populate_schedule ()
{
for (auto i = 0; i < buckets.size (); ++i)
for (auto i = 0; i < buckets_m.size (); ++i)
{
schedule.push_back (i);
}
@ -47,7 +47,7 @@ void nano::prioritization::populate_schedule ()
* Prioritization constructor, construct a container containing approximately 'maximum' number of blocks.
* @param maximum number of blocks that this container can hold, this is a soft and approximate limit.
*/
nano::prioritization::prioritization (uint64_t maximum) :
nano::scheduler::buckets::buckets (uint64_t maximum) :
maximum{ maximum }
{
auto build_region = [this] (uint128_t const & begin, uint128_t const & end, size_t count) {
@ -67,12 +67,12 @@ nano::prioritization::prioritization (uint64_t maximum) :
build_region (uint128_t{ 1 } << 112, uint128_t{ 1 } << 116, 4);
build_region (uint128_t{ 1 } << 116, uint128_t{ 1 } << 120, 2);
minimums.push_back (uint128_t{ 1 } << 120);
buckets.resize (minimums.size ());
buckets_m.resize (minimums.size ());
populate_schedule ();
current = schedule.begin ();
}
std::size_t nano::prioritization::index (nano::uint128_t const & balance) const
std::size_t nano::scheduler::buckets::index (nano::uint128_t const & balance) const
{
auto index = std::upper_bound (minimums.begin (), minimums.end (), balance) - minimums.begin () - 1;
return index;
@ -82,12 +82,12 @@ std::size_t nano::prioritization::index (nano::uint128_t const & balance) const
* Push a block and its associated time into the prioritization container.
* The time is given here because sideband might not exist in the case of state blocks.
*/
void nano::prioritization::push (uint64_t time, std::shared_ptr<nano::block> block, nano::amount const & priority)
void nano::scheduler::buckets::push (uint64_t time, std::shared_ptr<nano::block> block, nano::amount const & priority)
{
auto was_empty = empty ();
auto & bucket = buckets[index (priority.number ())];
auto & bucket = buckets_m[index (priority.number ())];
bucket.emplace (value_type{ time, block });
if (bucket.size () > std::max (decltype (maximum){ 1 }, maximum / buckets.size ()))
if (bucket.size () > std::max (decltype (maximum){ 1 }, maximum / buckets_m.size ()))
{
bucket.erase (--bucket.end ());
}
@ -98,29 +98,29 @@ void nano::prioritization::push (uint64_t time, std::shared_ptr<nano::block> blo
}
/** Return the highest priority block of the current bucket */
std::shared_ptr<nano::block> nano::prioritization::top () const
std::shared_ptr<nano::block> nano::scheduler::buckets::top () const
{
debug_assert (!empty ());
debug_assert (!buckets[*current].empty ());
auto result = buckets[*current].begin ()->block;
debug_assert (!buckets_m[*current].empty ());
auto result = buckets_m[*current].begin ()->block;
return result;
}
/** Pop the current block from the container and seek to the next block, if it exists */
void nano::prioritization::pop ()
void nano::scheduler::buckets::pop ()
{
debug_assert (!empty ());
debug_assert (!buckets[*current].empty ());
auto & bucket = buckets[*current];
debug_assert (!buckets_m[*current].empty ());
auto & bucket = buckets_m[*current];
bucket.erase (bucket.begin ());
seek ();
}
/** Returns the total number of blocks in buckets */
std::size_t nano::prioritization::size () const
std::size_t nano::scheduler::buckets::size () const
{
std::size_t result{ 0 };
for (auto const & queue : buckets)
for (auto const & queue : buckets_m)
{
result += queue.size ();
}
@ -128,27 +128,27 @@ std::size_t nano::prioritization::size () const
}
/** Returns number of buckets, 62 by default */
std::size_t nano::prioritization::bucket_count () const
std::size_t nano::scheduler::buckets::bucket_count () const
{
return buckets.size ();
return buckets_m.size ();
}
/** Returns number of items in bucket with index 'index' */
std::size_t nano::prioritization::bucket_size (std::size_t index) const
std::size_t nano::scheduler::buckets::bucket_size (std::size_t index) const
{
return buckets[index].size ();
return buckets_m[index].size ();
}
/** Returns true if all buckets are empty */
bool nano::prioritization::empty () const
bool nano::scheduler::buckets::empty () const
{
return std::all_of (buckets.begin (), buckets.end (), [] (priority const & bucket_a) { return bucket_a.empty (); });
return std::all_of (buckets_m.begin (), buckets_m.end (), [] (priority const & bucket_a) { return bucket_a.empty (); });
}
/** Print the state of the class in stderr */
void nano::prioritization::dump () const
void nano::scheduler::buckets::dump () const
{
for (auto const & i : buckets)
for (auto const & i : buckets_m)
{
for (auto const & j : i)
{
@ -158,12 +158,12 @@ void nano::prioritization::dump () const
std::cerr << "current: " << std::to_string (*current) << '\n';
}
std::unique_ptr<nano::container_info_component> nano::prioritization::collect_container_info (std::string const & name)
std::unique_ptr<nano::container_info_component> nano::scheduler::buckets::collect_container_info (std::string const & name)
{
auto composite = std::make_unique<container_info_composite> (name);
for (auto i = 0; i < buckets.size (); ++i)
for (auto i = 0; i < buckets_m.size (); ++i)
{
auto const & bucket = buckets[i];
auto const & bucket = buckets_m[i];
composite->add_component (std::make_unique<container_info_leaf> (container_info{ std::to_string (i), bucket.size (), 0 }));
}
return composite;

View file

@ -9,7 +9,9 @@
namespace nano
{
class block;
}
namespace nano::scheduler
{
/** A container for holding blocks and their arrival/creation time.
*
* The container consists of a number of buckets. Each bucket holds an ordered set of 'value_type' items.
@ -20,7 +22,7 @@ class block;
* The arrival/creation time is only an approximation and it could even be wildly wrong,
* for example, in the event of bootstrapped blocks.
*/
class prioritization final
class buckets final
{
class value_type
{
@ -34,7 +36,7 @@ class prioritization final
using priority = std::set<value_type>;
/** container for the buckets to be read in round robin fashion */
std::vector<priority> buckets;
std::vector<priority> buckets_m;
/** thresholds that define the bands for each bucket, the minimum balance an account must have to enter a bucket,
* the container writes a block to the lowest indexed bucket that has balance larger than the bucket's minimum value */
@ -54,7 +56,7 @@ class prioritization final
void populate_schedule ();
public:
prioritization (uint64_t maximum = 250000u);
buckets (uint64_t maximum = 250000u);
void push (uint64_t time, std::shared_ptr<nano::block> block, nano::amount const & priority);
std::shared_ptr<nano::block> top () const;
void pop ();
@ -67,4 +69,4 @@ public:
std::unique_ptr<nano::container_info_component> collect_container_info (std::string const &);
};
}
} // namespace nano::scheduler

View file

@ -2,7 +2,7 @@
#include <nano/lib/numbers.hpp>
#include <nano/node/active_transactions.hpp>
#include <nano/node/prioritization.hpp>
#include <nano/node/scheduler/buckets.hpp>
#include <boost/optional.hpp>
@ -54,7 +54,7 @@ private:
bool priority_queue_predicate () const;
bool manual_queue_predicate () const;
nano::prioritization buckets;
nano::scheduler::buckets buckets;
std::deque<std::tuple<std::shared_ptr<nano::block>, boost::optional<nano::uint128_t>, nano::election_behavior>> manual_queue;
bool stopped{ false };