Skip to content

Commit

Permalink
Refactor API weak reference fix to reduce boilerplate, extend fix to …
Browse files Browse the repository at this point in the history
…database_api
  • Loading branch information
theoreticalbts committed Apr 28, 2016
1 parent d16e671 commit 9936892
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 22 deletions.
9 changes: 9 additions & 0 deletions example_plugins/hello_api/hello_api_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ class hello_api_api
{
public:
hello_api_api( steemit::app::application& app );

/**
* Called immediately after the constructor. If the API class uses enable_shared_from_this,
* shared_from_this() is available in this method, which allows signal handlers to be registered
* with app::connect_signal()
*/
void on_api_startup();
std::string get_message();

private:
Expand Down Expand Up @@ -91,6 +98,8 @@ std::string hello_api_plugin::get_message()

hello_api_api::hello_api_api( steemit::app::application& app ) : _app(app) {}

void hello_api_api::on_api_startup() {}

std::string hello_api_api::get_message()
{
std::stringstream result;
Expand Down
14 changes: 7 additions & 7 deletions libraries/app/api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ namespace steemit { namespace app {
{
}

void login_api::on_api_startup() {}

bool login_api::login(const string& user, const string& password)
{
optional< api_access_info > acc = _app.get_api_access_info( user );
Expand Down Expand Up @@ -80,15 +82,11 @@ namespace steemit { namespace app {
/// NOTE: cannot register callbacks in constructor because shared_from_this() is not valid.
}

void network_broadcast_api::register_callbacks() {
void network_broadcast_api::on_api_startup()
{
/// note cannot capture shared pointer here, because _applied_block_connection will never
/// be freed if the lambda holds a reference to it.
std::weak_ptr<network_broadcast_api> weak_this = shared_from_this();
_applied_block_connection = _app.chain_database()->applied_block.connect(
[weak_this](const signed_block& b){
auto shared_this = weak_this.lock();
if( shared_this ) shared_this->on_applied_block(b);
});
_applied_block_connection = connect_signal( _app.chain_database()->applied_block, *this, &network_broadcast_api::on_applied_block );
}

void network_broadcast_api::on_applied_block( const signed_block& b )
Expand Down Expand Up @@ -167,6 +165,8 @@ namespace steemit { namespace app {
{
}

void network_node_api::on_api_startup() {}

fc::variant_object network_node_api::get_info() const
{
fc::mutable_variant_object result = _app.p2p_node()->network_get_info();
Expand Down
10 changes: 1 addition & 9 deletions libraries/app/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,15 +228,7 @@ namespace detail {
_self->register_api_factory< login_api >( "login_api" );
_self->register_api_factory< database_api >( "database_api" );
_self->register_api_factory< network_node_api >( "network_node_api" );
_self->register_api_factory( "network_broadcast_api", [this]() -> fc::api_ptr {

auto shared_api_ptr = std::make_shared< network_broadcast_api >( *_self );
shared_api_ptr->register_callbacks();

// apparently the compiler is smart enough to downcast shared_ptr< api<Api> > to shared_ptr< api_base > automatically
// see http://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast for example
return std::make_shared< fc::api< network_broadcast_api > >( shared_api_ptr );
});
_self->register_api_factory< network_broadcast_api >( "network_broadcast_api" );
}

void startup()
Expand Down
14 changes: 11 additions & 3 deletions libraries/app/database_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
bool verify_authority( const signed_transaction& trx )const;
bool verify_account_authority( const string& name_or_id, const flat_set<public_key_type>& signers )const;

// signal handlers
void on_applied_block( const chain::signed_block& b );

mutable fc::bloom_filter _subscribe_filter;
std::function<void(const fc::variant&)> _subscribe_callback;
std::function<void(const fc::variant&)> _pending_trx_callback;
Expand Down Expand Up @@ -150,14 +153,17 @@ void database_api_impl::set_pending_transaction_callback( std::function<void(con
void database_api::set_block_applied_callback( std::function<void(const variant& block_id)> cb )
{
my->set_block_applied_callback( cb );
my->_block_applied_connection = my->_db.applied_block.connect( [&]( const chain::signed_block& b ) {
my->_block_applied_callback( fc::variant(signed_block_header(b) ) );
});
}

void database_api_impl::on_applied_block( const chain::signed_block& b )
{
_block_applied_callback( fc::variant(signed_block_header(b) ) );
}

void database_api_impl::set_block_applied_callback( std::function<void(const variant& block_header)> cb )
{
_block_applied_callback = cb;
_block_applied_connection = connect_signal( _db.applied_block, *this, &database_api_impl::on_applied_block );
}

void database_api::cancel_all_subscriptions()
Expand Down Expand Up @@ -194,6 +200,8 @@ database_api_impl::~database_api_impl()
elog("freeing database api ${x}", ("x",int64_t(this)) );
}

void database_api::on_api_startup() {}

//////////////////////////////////////////////////////////////////////
// //
// Blocks and transactions //
Expand Down
8 changes: 6 additions & 2 deletions libraries/app/include/steemit/app/api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,8 @@ namespace steemit { namespace app {
*/
void on_applied_block( const signed_block& b );


/// internal method, not exposed via JSON RPC
void register_callbacks();
void on_api_startup();
private:
boost::signals2::scoped_connection _applied_block_connection;

Expand Down Expand Up @@ -151,6 +150,8 @@ namespace steemit { namespace app {
*/
std::vector<graphene::net::potential_peer_record> get_potential_peers() const;

/// internal method, not exposed via JSON RPC
void on_api_startup();
private:
application& _app;
};
Expand Down Expand Up @@ -186,6 +187,9 @@ namespace steemit { namespace app {
return it->second;
}

/// internal method, not exposed via JSON RPC
void on_api_startup();

private:
application& _app;
flat_map< std::string, fc::api_ptr > _api_map;
Expand Down
18 changes: 17 additions & 1 deletion libraries/app/include/steemit/app/application.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ namespace steemit { namespace app {
{
// apparently the compiler is smart enough to downcast shared_ptr< api<Api> > to shared_ptr< api_base > automatically
// see http://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast for example
return std::make_shared< fc::api< Api > >( std::make_shared< Api >( *this ) );
std::shared_ptr< Api > api = std::make_shared< Api >( *this );
api->on_api_startup();
return std::make_shared< fc::api< Api > >( api );
} );
}

Expand All @@ -119,4 +121,18 @@ namespace steemit { namespace app {
boost::program_options::options_description _cfg_options;
};

template< class C, typename... Args >
boost::signals2::scoped_connection connect_signal( boost::signals2::signal< void(Args...) >& sig, C& c, void(C::* f)(Args...) )
{
std::weak_ptr<C> weak_c = c.shared_from_this();
return sig.connect(
[weak_c,f](Args... args)
{
std::shared_ptr<C> shared_c = weak_c.lock();
if( !shared_c )
return;
((*shared_c).*f)(args...);
} );
}

} } // steemit::app
5 changes: 5 additions & 0 deletions libraries/app/include/steemit/app/database_api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,11 @@ class database_api
*/
map<uint32_t,operation_object> get_account_history( string account, uint64_t from, uint32_t limit )const;

////////////////////////////
// Handlers - not exposed //
////////////////////////////
void on_api_startup();

private:
void set_pending_payout( discussion& d )const;
void set_url( discussion& d )const;
Expand Down
2 changes: 2 additions & 0 deletions libraries/plugins/debug_node/debug_node_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ debug_node_api::debug_node_api( steemit::app::application& app )
my = std::make_shared< detail::debug_node_api_impl >(app);
}

void debug_node_api::on_api_startup() {}

void debug_node_api::debug_push_blocks( std::string source_filename, uint32_t count )
{
my->debug_push_blocks( source_filename, count );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class debug_node_api
public:
debug_node_api( steemit::app::application& app );

void on_api_startup();

/**
* Push blocks from existing database.
*/
Expand Down

0 comments on commit 9936892

Please sign in to comment.