风险提示:理性看待区块链,提高风险意识!
比特币源码分析:任务调度器的使用
首页 > 币界资讯 > 区块链知识 2018-03-24 07:23:00

blockchain

任务调度器

Bitcoin 进程启动后,有一个专门的线程做任务调度, 这些任务根据指定的时刻,执行对应的函数:

bool AppInitMain()
 {
 .......
 // Start the lightweight task scheduler thread
 CScheduler::Function serviceLoop = boost::bind(&CScheduler::serviceQueue, &scheduler);
 threadGroup.create_thread(boost::bind(&TraceThread, "scheduler", serviceLoop));
 .......
 }

调度器类主要是实现了一个生产者消费者的任务队列,只是这个任务队列是用 std::multimap 实现的,map 的key表达某一时刻,map的值表达:那一时刻要执行的函数,内部使用条件变量和锁来保护multimap ,还有几个bool 条件:

class CScheduler
 {
 public:
 CScheduler();
 ~CScheduler();
 typedef std::function<void(void)> Function;
 void schedule(Function f, boost::chrono::system_clock::time_point t=boost::chrono::system_clock::now());
 void scheduleFromNow(Function f, int64_t deltaMilliSeconds);
 void scheduleEvery(Function f, int64_t deltaMilliSeconds);
 void serviceQueue();
 void stop(bool drain=false);
 size_t getQueueInfo(boost::chrono::system_clock::time_point &first,
 boost::chrono::system_clock::time_point &last) const;
 bool AreThreadsServicingQueue() const;
 private:
 std::multimap<boost::chrono::system_clock::time_point, Function> taskQueue;
 boost::condition_variable newTaskScheduled;
 mutable boost::mutex newTaskMutex;
 int nThreadsServicingQueue;
 bool stopRequested;
 bool stopWhenEmpty;
 bool shouldStop() const { return stopRequested || (stopWhenEmpty && taskQueue.empty()); }
 };

CScheduler的client 通过调用schedule 往内部multimap添加一个条目; scheduleFromNow 和scheduleEvery 内部都是调用schedule 方法实现; 这三个方法属于生产者要生产任务的方法, 任务的消费者调用serviceQueue等待取走任务, 然后执行。

目前整个程序有一个全局的CScheduler实例:

static CScheduler scheduler; 这个实例对应只有一个消费者线程, 即唯一的后台调度器线程。

class SingleThreadedSchedulerClient 主要用途是,借助CScheduler类型,保障被添加到内部链表的任务,被串行执行:

class SingleThreadedSchedulerClient {
 private:
 CScheduler *m_pscheduler;
 CCriticalSection m_cs_callbacks_pending;
 std::list<std::function> m_callbacks_pending;
 bool m_are_callbacks_running = false;
 void MaybeScheduleProcessQueue();
 void ProcessQueue();
 public:
 explicit SingleThreadedSchedulerClient(CScheduler *pschedulerIn) : m_pscheduler(pschedulerIn) {}
 void AddToProcessQueue(std::function func);
 void EmptyQueue();
 size_t CallbacksPending();
 };

使用例子

基本的使用例子:

#include
 #include <boost/bind.hpp>
 #include <boost/thread.hpp>
 #include <boost/test/unit_test.hpp>
 #include
 static void doN(){
 std::cout << "output now\n";
 }
 static void doE(){
 for(int i = 0; i < 10; i++){
 std::cout << "i = " << i << '\n';
 }
 std::cout << '\n';
 }
 BOOST_AUTO_TEST_SUITE(sche_tests)
 BOOST_AUTO_TEST_CASE(sche)
 {
 CScheduler s;
 s.scheduleFromNow(doN, 1000);
 s.scheduleEvery(doE, 1000);
 boost::thread t(boost::bind(&CScheduler::serviceQueue, &s));
 boost::this_thread::sleep_for(boost::chrono::seconds{5});
 t.interrupt();
 t.join();
 }
 BOOST_AUTO_TEST_CASE(singlethread)
 {
 CScheduler s;
 SingleThreadedSchedulerClient sc (&s);
 for(int i = 1; i <11; i++){
 auto f = [=]{
 std::cout << "thread " << boost::this_thread::get_id() << " print arg: " << i << '\n'; }; sc.AddToProcessQueue(f); } boost::thread t(boost::bind(&CScheduler::serviceQueue, &s)); boost::this_thread::sleep_for(boost::chrono::seconds{1}); t.interrupt(); t.join(); } BOOST_AUTO_TEST_SUITE_END()

进程启动后, 全局对象连接管理器connman初始化后, connman 的Start 方法最后,通过scheduler 线程安排了一个定时任务: 每隔15分钟, 把connman 对象内部成员,banmap_t 类型的 setBanned, CAddrMan 类型的addrman 序列化到本地文件banlist.dat 和 peers.dat。

//init.cpp if (!connman.Start(scheduler, connOptions)) { return false; } //net.cpp bool CConnman::Start(CScheduler& scheduler, const Options& connOptions) { ............... scheduler.scheduleEvery(std::bind(&CConnman::DumpData, this), DUMP_ADDRESSES_INTERVAL * 1000); }

如果钱包功能编译使能, 会让scheduler 线程安排每隔500毫秒刷新钱包状态。

//init.cpp #ifdef ENABLE_WALLET StartWallets(scheduler); #endif //wallet/init.cpp void StartWallets(CScheduler& scheduler) { for (CWalletRef pwallet : vpwallets) { pwallet->postInitProcess(scheduler);
 }
 }
 //wallet/wallet.cpp
 void CWallet::postInitProcess(CScheduler& scheduler)
 {
 ReacceptWalletTransactions();
 if (!CWallet::fFlushScheduled.exchange(true)) {
 scheduler.scheduleEvery(MaybeCompactWalletDB, 500);
 }
 }

PeerLogicValidation 对象的构造函数内部, scheduler 线程安排每45秒执行CheckForStaleTipAndEvictPeer函数主要做两件事:

  1. 关掉多余的外出tcp 连接
  2. 根据当前时间,检查当前节点的blockchain 的tip 是否有可能过时了,建立额外的连接同步跟上
PeerLogicValidation::PeerLogicValidation(CConnman* connmanIn, CScheduler &scheduler) : connman(connmanIn), m_stale_tip_check_time(0) {
 // Initialize global variables that cannot be constructed at startup.
 recentRejects.reset(new CRollingBloomFilter(120000, 0.000001));
 const Consensus::Params& consensusParams = Params().GetConsensus();
 // Stale tip checking and peer eviction are on two different timers, but we
 // don't want them to get out of sync due to drift in the scheduler, so we
 // combine them in one function and schedule at the quicker (peer-eviction)
 // timer.
 static_assert(EXTRA_PEER_CHECK_INTERVAL < STALE_CHECK_INTERVAL, "peer eviction timer should be less than stale tip check timer"); scheduler.scheduleEvery(std::bind(&PeerLogicValidation::CheckForStaleTipAndEvictPeers, this, consensusParams), EXTRA_PEER_CHECK_INTERVAL * 1000); } void PeerLogicValidation::CheckForStaleTipAndEvictPeers(const Consensus::Params &consensusParams) { if (connman == nullptr) return; int64_t time_in_seconds = GetTime(); EvictExtraOutboundPeers(time_in_seconds); if (time_in_seconds > m_stale_tip_check_time) {
 LOCK(cs_main);
 // Check whether our tip is stale, and if so, allow using an extra
 // outbound peer
 if (TipMayBeStale(consensusParams)) {
 LogPrintf("Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n", time_in_seconds - g_last_tip_update);
 connman->SetTryNewOutboundPeer(true);
 } else if (connman->GetTryNewOutboundPeer()) {
 connman->SetTryNewOutboundPeer(false);
 }
 m_stale_tip_check_time = time_in_seconds + STALE_CHECK_INTERVAL;
 }
 }

以上就是bitoin 里面CScheduler类的主要使用场景。

上一篇: Solidity概述及基本代码展示
下一篇: Bitcoin如何通过脚本进行一段时间的资金冻结
推荐专栏
web3首席知识博主
一位相信价值投资的币圈KOL。稳定盈利的缠论野生交易员 #BTC行情分析师 #价值投资 #链上数据分析
爱Web 3,爱生活,爱科技,爱炒币的老韭菜
热门币种
更多
币种
价格
24H涨跌幅
BTC比特币
¥264,358.04
37,039.98 USDT
-0.08%
ETH以太坊
¥14,381.54
2,015.04 USDT
-0.33%
USDT泰达币
¥7.20
1.01 USDT
+0.03%
BNB币安币
¥1,622.26
227.30 USDT
-0.04%
XRP瑞波币
¥4.34
0.60860 USDT
+1.11%
USDC
¥7.14
1.00 USDT
+0.04%
SOLSolana
¥397.24
55.66 USDT
+0.89%
OKBOK币
¥398.18
55.79 USDT
-1.98%
ADA艾达币
¥2.68
0.37490 USDT
-1.52%
DOGE狗狗币
¥0.55410
0.07765 USDT
-1.04%
热搜币种
更多
币种
价格
24H涨跌幅
Terra Classic
¥0.00
9.433E-5 USDT
-17.92%
Gala
¥0.18
0.025395 USDT
-4.47%
dYdX
¥22.45
3.1738 USDT
-1.74%
比特股
¥0.05
0.006817 USDT
+3.93%
PancakeSwap
¥15.45
2.1845 USDT
-3.6%
Conflux
¥1.07
0.1514 USDT
-3.57%
Filecoin
¥31.38
4.4363 USDT
-1.25%
FTX Token
¥30.21
4.2702 USDT
+16.02%
Shiba Inu
¥0.00
8.12E-6 USDT
-2.52%
Yield Guild Games
¥2.54
0.3591 USDT
-0.91%
比特币
¥262,018.97
37039.98 USDT
-0.08%
比原链
¥0.07
0.010012 USDT
-5.35%
最新快讯
更多
汇丰、恒生、渣打、富邦华一四家外资银行入围首批“数字人民币”业务试点名单
2023-11-28 19:06:57
摩根大通和Apollo计划建立代币化“企业主网”
2023-11-28 19:03:57
Nansen2公测版本上线,新增链上数据异动、智能搜索等功能
2023-11-28 18:59:52
西班牙公民需在明年3月底前申报其海外平台上加密货币持仓
2023-11-28 18:53:43
Nansen2已公开测试
2023-11-28 18:53:38
dYdX基金会:主网启动以来超过1645万DYDX被质押
2023-11-28 18:52:07
NicCarter等比特币倡导者发文:比特币挖矿是清洁能源和平衡电网的关键工具
2023-11-28 18:47:58
下载币界网APP