turns out that shared_from_this() can not be called from the constructor, so we made a special attach() function to postpone object initialization

This commit is contained in:
Emiel Bruijntjes 2014-08-20 12:44:52 +02:00
parent 53b2bd9f0d
commit d23e818f64
4 changed files with 42 additions and 80 deletions

View File

@ -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

View File

@ -25,17 +25,11 @@ class ConsumedMessage;
class ChannelImpl : public Watchable, public std::enable_shared_from_this<ChannelImpl>
{
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<ChannelImpl> 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;
}

View File

@ -46,66 +46,6 @@
*/
namespace AMQP {
/**
* Derived class with public constructor
*
* We need this because std::make_shared<ChannelImpl> 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> ChannelImpl::instantiate(Channel *parent, Connection *connection)
{
// we can only use std::make_shared with a PublicChannelImpl
return std::make_shared<PublicChannelImpl>(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

View File

@ -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();
}
/**