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:
parent
53b2bd9f0d
commit
d23e818f64
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue