*/
void workSocket();
- /// Close this connection and free or reset its resources.
- void close();
-
public:
class Task;
std::free(readBuffer_);
}
+ /// Close this connection and free or reset its resources.
+ void close();
+
/**
* Check buffers against any size limits and shrink it if exceeded.
*
}
TNonblockingServer::~TNonblockingServer() {
- // TODO: We currently leak any active TConnection objects.
- // Since we're shutting down and destroying the event_base, the TConnection
- // objects will never receive any additional callbacks. (And even if they
- // did, it would be bad, since they keep a pointer around to the server,
- // which is being destroyed.)
-
+ // Close any active connections (moves them to the idle connection stack)
+ while (activeConnections_.size()) {
+ activeConnections_.front()->close();
+ }
// Clean up unused TConnection objects in connectionStack_
while (!connectionStack_.empty()) {
TConnection* connection = connectionStack_.top();
connectionStack_.pop();
delete connection;
}
+ // The TNonblockingIOThread objects have shared_ptrs to the Thread
+ // objects and the Thread objects have shared_ptrs to the TNonblockingIOThread
+ // objects (as runnable) so these objects will never deallocate without help.
+ while (!ioThreads_.empty()) {
+ boost::shared_ptr<TNonblockingIOThread> iot = ioThreads_.back();
+ ioThreads_.pop_back();
+ iot->setThread(boost::shared_ptr<Thread>());
+ }
}
/**
connectionStack_.pop();
result->init(socket, ioThread, addr, addrLen);
}
+ activeConnections_.push_back(result);
return result;
}
void TNonblockingServer::returnConnection(TConnection* connection) {
Guard g(connMutex_);
+ activeConnections_.erase(std::remove(activeConnections_.begin(), activeConnections_.end(), connection), activeConnections_.end());
+
if (connectionStackLimit_ &&
(connectionStack_.size() >= connectionStackLimit_)) {
delete connection;
*/
std::stack<TConnection*> connectionStack_;
+ /**
+ * This container holds pointers to all active connections. This container
+ * allows the server to clean up unlcosed connection objects at destruction,
+ * which in turn allows their transports, protocols, processors and handlers
+ * to deallocate and clean up correctly.
+ */
+ std::vector<TConnection*> activeConnections_;
+
/**
* Called when server socket had something happen. We accept all waiting
* client connections on listen socket fd and assign TConnection objects