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
|
* Construct a channel object
|
||||||
* @param connection
|
* @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
|
* Destructor
|
||||||
|
|
|
||||||
|
|
@ -25,17 +25,11 @@ class ConsumedMessage;
|
||||||
class ChannelImpl : public Watchable, public std::enable_shared_from_this<ChannelImpl>
|
class ChannelImpl : public Watchable, public std::enable_shared_from_this<ChannelImpl>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
/**
|
|
||||||
* The actual channel object
|
|
||||||
* @var Channel
|
|
||||||
*/
|
|
||||||
Channel *_parent;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pointer to the connection
|
* Pointer to the connection
|
||||||
* @var ConnectionImpl
|
* @var ConnectionImpl
|
||||||
*/
|
*/
|
||||||
ConnectionImpl *_connection;
|
ConnectionImpl *_connection = nullptr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback when the channel is ready
|
* Callback when the channel is ready
|
||||||
|
|
@ -74,7 +68,7 @@ private:
|
||||||
* The channel number
|
* The channel number
|
||||||
* @var uint16_t
|
* @var uint16_t
|
||||||
*/
|
*/
|
||||||
uint16_t _id;
|
uint16_t _id = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* State of the channel object
|
* State of the channel object
|
||||||
|
|
@ -84,7 +78,7 @@ private:
|
||||||
state_connected,
|
state_connected,
|
||||||
state_closing,
|
state_closing,
|
||||||
state_closed
|
state_closed
|
||||||
} _state = state_connected;
|
} _state = state_closed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The frames that still need to be send out
|
* The frames that still need to be send out
|
||||||
|
|
@ -109,11 +103,10 @@ private:
|
||||||
ConsumedMessage *_message = nullptr;
|
ConsumedMessage *_message = nullptr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor to make a shared pointer
|
* Attach the connection
|
||||||
* @param parent the publis channel object
|
* @param connection
|
||||||
* @param connection pointer to the connection
|
|
||||||
*/
|
*/
|
||||||
static std::shared_ptr<ChannelImpl> instantiate(Channel *parent, Connection *connection);
|
void attach(Connection *connection);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Push a deferred result
|
* Push a deferred result
|
||||||
|
|
@ -136,11 +129,8 @@ protected:
|
||||||
* Note that the constructor is private, and that the Channel class is
|
* Note that the constructor is private, and that the Channel class is
|
||||||
* a friend. By doing this we ensure that nobody can instantiate this
|
* a friend. By doing this we ensure that nobody can instantiate this
|
||||||
* object, and that it can thus only be used inside the library.
|
* 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:
|
public:
|
||||||
/**
|
/**
|
||||||
|
|
@ -152,7 +142,7 @@ public:
|
||||||
* Invalidate the channel
|
* Invalidate the channel
|
||||||
* This method is called when the connection is destructed
|
* This method is called when the connection is destructed
|
||||||
*/
|
*/
|
||||||
void invalidate()
|
void detach()
|
||||||
{
|
{
|
||||||
_connection = nullptr;
|
_connection = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,66 +46,6 @@
|
||||||
*/
|
*/
|
||||||
namespace AMQP {
|
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
|
* Destructor
|
||||||
*/
|
*/
|
||||||
|
|
@ -122,6 +62,34 @@ ChannelImpl::~ChannelImpl()
|
||||||
while (_oldestCallback) _oldestCallback.reset(_oldestCallback->next());
|
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
|
* Push a deferred result
|
||||||
* @param result The deferred object to push
|
* @param result The deferred object to push
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ ConnectionImpl::~ConnectionImpl()
|
||||||
close();
|
close();
|
||||||
|
|
||||||
// invalidate all channels, so they will no longer call methods on this channel object
|
// 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