From d23e818f64ba83d58a29fb386137dd42777c8f21 Mon Sep 17 00:00:00 2001 From: Emiel Bruijntjes Date: Wed, 20 Aug 2014 12:44:52 +0200 Subject: [PATCH] turns out that shared_from_this() can not be called from the constructor, so we made a special attach() function to postpone object initialization --- include/channel.h | 6 ++- include/channelimpl.h | 26 ++++--------- src/channelimpl.cpp | 88 ++++++++++++++---------------------------- src/connectionimpl.cpp | 2 +- 4 files changed, 42 insertions(+), 80 deletions(-) diff --git a/include/channel.h b/include/channel.h index 83ecfcf..94a7b99 100644 --- a/include/channel.h +++ b/include/channel.h @@ -27,7 +27,11 @@ public: * Construct a channel object * @param connection */ - Channel(Connection *connection) : _implementation(ChannelImpl::instantiate(this, connection)) {} + Channel(Connection *connection) : _implementation(new ChannelImpl()) + { + // attach the connection to the channel + _implementation->attach(connection); + } /** * Destructor diff --git a/include/channelimpl.h b/include/channelimpl.h index 3153478..f03930d 100644 --- a/include/channelimpl.h +++ b/include/channelimpl.h @@ -25,17 +25,11 @@ class ConsumedMessage; class ChannelImpl : public Watchable, public std::enable_shared_from_this { private: - /** - * The actual channel object - * @var Channel - */ - Channel *_parent; - /** * Pointer to the connection * @var ConnectionImpl */ - ConnectionImpl *_connection; + ConnectionImpl *_connection = nullptr; /** * Callback when the channel is ready @@ -74,7 +68,7 @@ private: * The channel number * @var uint16_t */ - uint16_t _id; + uint16_t _id = 0; /** * State of the channel object @@ -84,7 +78,7 @@ private: state_connected, state_closing, state_closed - } _state = state_connected; + } _state = state_closed; /** * The frames that still need to be send out @@ -109,11 +103,10 @@ private: ConsumedMessage *_message = nullptr; /** - * Constructor to make a shared pointer - * @param parent the publis channel object - * @param connection pointer to the connection + * Attach the connection + * @param connection */ - static std::shared_ptr instantiate(Channel *parent, Connection *connection); + void attach(Connection *connection); /** * Push a deferred result @@ -136,11 +129,8 @@ protected: * Note that the constructor is private, and that the Channel class is * a friend. By doing this we ensure that nobody can instantiate this * object, and that it can thus only be used inside the library. - * - * @param parent the public channel object - * @param connection pointer to the connection */ - ChannelImpl(Channel *parent, Connection *connection); + ChannelImpl() {} public: /** @@ -152,7 +142,7 @@ public: * Invalidate the channel * This method is called when the connection is destructed */ - void invalidate() + void detach() { _connection = nullptr; } diff --git a/src/channelimpl.cpp b/src/channelimpl.cpp index 1d74ff5..5fa756f 100644 --- a/src/channelimpl.cpp +++ b/src/channelimpl.cpp @@ -46,66 +46,6 @@ */ namespace AMQP { -/** - * Derived class with public constructor - * - * We need this because std::make_shared is not possible - */ -struct PublicChannelImpl : public ChannelImpl -{ - /** - * Constructor - * @param parent - * @param connection - */ - PublicChannelImpl(Channel *parent, Connection *connection) : ChannelImpl(parent, connection) {} - - /** - * Destructor - */ - virtual ~PublicChannelImpl() {} -}; - -/** - * Constructor to make a shared pointer - * @param parent the publis channel object - * @param connection pointer to the connection - */ -std::shared_ptr ChannelImpl::instantiate(Channel *parent, Connection *connection) -{ - // we can only use std::make_shared with a PublicChannelImpl - return std::make_shared(parent, connection); -} - -/** - * Construct a channel object - * @param parent - * @param connection - * @param handler - */ -ChannelImpl::ChannelImpl(Channel *parent, Connection *connection) : - _parent(parent), - _connection(&connection->_implementation) -{ - // add the channel to the connection - _id = _connection->add(shared_from_this()); - - // check if the id is valid - if (_id == 0) - { - // this is invalid - _state = state_closed; - } - else - { - // busy connecting - _state = state_connected; - - // valid id, send a channel open frame - send(ChannelOpenFrame(_id)); - } -} - /** * Destructor */ @@ -122,6 +62,34 @@ ChannelImpl::~ChannelImpl() while (_oldestCallback) _oldestCallback.reset(_oldestCallback->next()); } +/** + * Initialize the object with an connection + * @param connection + */ +void ChannelImpl::attach(Connection *connection) +{ + // get connection impl + _connection = &connection->_implementation; + + // retrieve an ID + _id = _connection->add(shared_from_this()); + + // check if the id is valid + if (_id == 0) + { + // this is invalid + _state = state_closed; + } + else + { + // busy connecting + _state = state_connected; + + // valid id, send a channel open frame + send(ChannelOpenFrame(_id)); + } +} + /** * Push a deferred result * @param result The deferred object to push diff --git a/src/connectionimpl.cpp b/src/connectionimpl.cpp index 2971e63..b41c07c 100644 --- a/src/connectionimpl.cpp +++ b/src/connectionimpl.cpp @@ -45,7 +45,7 @@ ConnectionImpl::~ConnectionImpl() close(); // invalidate all channels, so they will no longer call methods on this channel object - for (auto iter = _channels.begin(); iter != _channels.end(); iter++) iter->second->invalidate(); + for (auto iter = _channels.begin(); iter != _channels.end(); iter++) iter->second->detach(); } /**