Commit 99f8dcdd authored by Sridhar Srinivasan's avatar Sridhar Srinivasan Committed by Facebook GitHub Bot

Invoke life cycle observer callbacks during event base attach and

Summary: Inform LifecycleObservers when an EventBase is attached or detached from an AsyncSocket.

Reviewed By: bschlinker

Differential Revision: D24294292

fbshipit-source-id: 652ec438d0b6213a78742b8a8ef0d24d55ac9816
parent d5d78479
......@@ -1578,6 +1578,9 @@ void AsyncSocket::attachEventBase(EventBase* eventBase) {
if (evbChangeCb_) {
evbChangeCb_->evbAttached(this);
}
for (const auto& cb : lifecycleObservers_) {
cb->evbAttach(this, eventBase_);
}
}
void AsyncSocket::detachEventBase() {
......@@ -1587,6 +1590,10 @@ void AsyncSocket::detachEventBase() {
assert(eventBase_ != nullptr);
eventBase_->dcheckIsInEventBaseThread();
// Make a copy of the existing event base, to invoke lifecycle observer
// callbacks
EventBase* existingEvb = eventBase_;
eventBase_ = nullptr;
ioHandler_.unregisterHandler();
......@@ -1596,6 +1603,9 @@ void AsyncSocket::detachEventBase() {
if (evbChangeCb_) {
evbChangeCb_->evbDetached(this);
}
for (const auto& cb : lifecycleObservers_) {
cb->evbDetach(this, existingEvb);
}
}
bool AsyncSocket::isDetachable() const {
......
......@@ -762,6 +762,28 @@ class AsyncTransport : public DelayedDestruction,
* @param transport Transport that has connected.
*/
virtual void connect(AsyncTransport* /* transport */) noexcept = 0;
/**
* Called when the socket has been attached to a new EVB
* and is called from within the new EVB's thread
*
* @param socket The socket on which the new EVB was attached.
* @param evb The new event base that is being attached.
*/
virtual void evbAttach(AsyncTransport* /* socket */, EventBase* /* evb */) {
// do nothing
}
/**
* Called when the socket is detached from an EVB and
* is called from the existing EVB's thread.
*
* @param socket The socket from which the EVB was detached.
* @param evb The existing evb that is being detached.
*/
virtual void evbDetach(AsyncTransport* /* socket */, EventBase* /* evb */) {
// do nothing
}
};
/**
......
......@@ -3260,6 +3260,8 @@ class MockAsyncSocketLifecycleObserver : public AsyncSocket::LifecycleObserver {
GMOCK_METHOD1_(, noexcept, , connect, void(AsyncTransport*));
GMOCK_METHOD1_(, noexcept, , fdDetach, void(AsyncSocket*));
GMOCK_METHOD2_(, noexcept, , move, void(AsyncSocket*, AsyncSocket*));
GMOCK_METHOD2_(, noexcept, , evbAttach, void(AsyncTransport*, EventBase*));
GMOCK_METHOD2_(, noexcept, , evbDetach, void(AsyncTransport*, EventBase*));
};
class MockAsyncTransportLifecycleObserver
......@@ -3270,8 +3272,48 @@ class MockAsyncTransportLifecycleObserver
GMOCK_METHOD1_(, noexcept, , destroy, void(AsyncTransport*));
GMOCK_METHOD1_(, noexcept, , close, void(AsyncTransport*));
GMOCK_METHOD1_(, noexcept, , connect, void(AsyncTransport*));
GMOCK_METHOD2_(, noexcept, , evbAttach, void(AsyncTransport*, EventBase*));
GMOCK_METHOD2_(, noexcept, , evbDetach, void(AsyncTransport*, EventBase*));
};
TEST(AsyncSocket, LifecycleObserverDetachAndAttachEvb) {
auto cb = std::make_unique<StrictMock<MockAsyncSocketLifecycleObserver>>();
EventBase evb;
EventBase evb2;
auto socket = AsyncSocket::UniquePtr(new AsyncSocket(&evb));
EXPECT_CALL(*cb, observerAttach(socket.get()));
socket->addLifecycleObserver(cb.get());
EXPECT_THAT(socket->getLifecycleObservers(), UnorderedElementsAre(cb.get()));
Mock::VerifyAndClearExpectations(cb.get());
// Detach the evb and attach a new evb2
EXPECT_CALL(*cb, evbDetach(socket.get(), &evb));
socket->detachEventBase();
EXPECT_EQ(nullptr, socket->getEventBase());
Mock::VerifyAndClearExpectations(cb.get());
EXPECT_CALL(*cb, evbAttach(socket.get(), &evb2));
socket->attachEventBase(&evb2);
EXPECT_EQ(&evb2, socket->getEventBase());
Mock::VerifyAndClearExpectations(cb.get());
// detach the new evb2 and re-attach the old evb.
EXPECT_CALL(*cb, evbDetach(socket.get(), &evb2));
socket->detachEventBase();
EXPECT_EQ(nullptr, socket->getEventBase());
Mock::VerifyAndClearExpectations(cb.get());
EXPECT_CALL(*cb, evbAttach(socket.get(), &evb));
socket->attachEventBase(&evb);
EXPECT_EQ(&evb, socket->getEventBase());
Mock::VerifyAndClearExpectations(cb.get());
InSequence s;
EXPECT_CALL(*cb, destroy(socket.get()));
socket = nullptr;
Mock::VerifyAndClearExpectations(cb.get());
}
TEST(AsyncSocket, LifecycleObserverAttachThenDestroySocket) {
auto cb = std::make_unique<StrictMock<MockAsyncSocketLifecycleObserver>>();
TestServer server;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment