I wrote a small tcp client using boost::asio, providing the following function:
typedef boost::function<void(const bs::error_code& errCode, size_t bytesTransferred)> ReadHandler;
void CTcpClient::AsyncRead2(std::vector<char>& data, size_t length, ReadHandler readCompletedCallback)
{
async_read(m_tcpData->socket, ba::buffer(data, length), readCompletedCallback);
}
My idea is to offer the user of my TcpClient class asynchronous operations, without to worry about thread handling, io_services and so on.
Now the code calling the above function from my unittest class looks like this:
CTestTcpClient header
class CTestTcpClient : public ::testing::Test
{
public:
CTestTcpClient(void);
virtual ~CTestTcpClient(void);
struct ReadCompletedHandler
{
ReadCompletedHandler() : m_isCompleted(false){};
void operator()(const boost::system::error_code& errCode, size_t bytesTransferred)
{
m_isCompleted = true; // my breakpoint here, checking this pointer
};
bool isCompleted(void)
{
return m_isCompleted;
}
private:
bool m_isCompleted;
};
ReadCompletedHandler m_readHandler;
};
CTestTcpClient source
TEST_F(CTestTcpClient, testAsynchronousRead_Success)
{
CTcpClient client(testService);
// Skipped code to setup echo server, connecting and sending of data
// Receive echo
vector<char> receiveBuffer(TESTDATA_SIZE);
client.AsyncRead2(receiveBuffer, TESTDATA_SIZE, m_readHandler);
while (!m_readHandler.isCompleted())
{
client.Wait(200);
}
}
Now here is the problem: the while loop will never exit, because the is_completed flag is set in a copy of the m_readHandler. If I set a breakpoint in operator() of my handler, I can check and compare the this pointer. It seems boost::asio is copying my handler, call the operator() there, and return. My original handler is never touched at all.
The boost documentation says that copies will be made of the handler as required. So that seems to be ok, but what can I do to achieve the desired behaviour?
Thanks for any help