Saturday, 4 November 2017

Bitcoin core tutorial & code walk through (Part 6) - signal

In part 6 of the tutorial, the signals used in bitcoin core will be discussed.

Looking at init.cpp, it defines registerSignalHandler() function. It registers signal handler to a signal in linux style. The "struct sigaction" is same as what is available in linux. In AppInitBasicSetup(), three signal handlers are registered respectively for SIGTERM, SIGINT, SIGHUP.

In net.h, "struct CNodeSignals" is declared. It defines boost C++ library style signal. This line
boost::signals2::signal<bool (CNode*, CConnman&, std::atomic<bool>&), CombinerAll> ProcessMessages
means a ProcessMessages signal is defined. The return type of the connector is bool, the connector takes in 3 parameters. The "CombinerAll" is a combiner. 

In net_processing.cpp, compare the function declaration bool ProcessMessages(CNode*, CConnman&, const std::atomic<bool>&)
with the signal connector signature. The signature exactly matches.

In net_processing.cpp, the slot is connected to the signal in RegisterNodeSignals(CNodeSignals& nodeSignals).
Both the slot and signal are called ProcessMessages, as seen in the line below !! nodeSignals.ProcessMessages.connect(&ProcessMessages);

In net.h, it defines the combiner. The result_type is the return value of the combiner.
struct CombinerAll {
    typedef bool result_type;


    template<typename I>

    bool operator()(I first, I last) const

    {

        while (first != last) {

            if (!(*first)) return false;
            ++first;
        }
        return true;
    }
};

The combiner takes in two input iterator, "first" and "last". It compares all connector return values, and returns true if all values are equal.

In validationinterface.h, "struct CMainSignals" is declared. It also defines boost C++ library style signal. This line

boost::signals2::signal<void (const CBlockIndex *, const CBlockIndex *, bool fInitialDownload)> UpdatedBlockTip;

means for the UpdatedBlockTip signal, the connector returns void, and takes in 3 parameters.

In validationinterface.cpp, the connector is

g_signals.UpdatedBlockTip.connect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3));

The boost:bind() is used. It means it stores a copy of pwalletIn->UpdateBlockTip(_1, _2, _3). That is the three paramters as in the connector.

In validation.cpp, the UpdatedBlockTip signal is called with three parameters.

GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, fInitialDownload);

So, for headless bitcoin core source code, linux and boost style signal are used.

No comments:

Post a Comment