I am using async_read_some to read data from a port that is saved in a char[] called _data. Its buffer size is big enough for every request:
void start() {
socket_.async_read_some(boost::asio::buffer(data_,BUFFERSIZE),make_custom_alloc_handler(allocator_,boost::bind(&attentionSession::handle_read, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)));
}
void handle_read(const boost::system::error_code& error, size_t bytes_transferred) {
string ip = socket_.remote_endpoint().address().to_string();
log->processData(data_,ip,"memory");
strcpy(data_,"");
}
processData adds some additional information (like timestamp etc.) to the request by copying it to another newly alloced char*. Then this char[] is sent to writeToMemory(char*) to append that char* to the std::string memoryBuffer:
void writeCacheToFile() {
// This function writes buffer data to the log file
char* temp = new char[memoryBuffer.length() + 1];
strcpy(temp, memoryBuffer.c_str());
writeToFile(temp);
delete[] temp;
memoryBuffer.clear();
}
void writeToMemory(char* data) {
int maxSize = 1024;
// Checks if char* data would 'fit' into the pre-defined maxSize
if ((strlen((const char*)data) + memoryBuffer.length()) >= maxSize) {
writeCacheToFile(); // If not the cache memoryBuffer is saved first
}
memoryBuffer.append((const char*) data);
cout << memoryBuffer.length() << endl;
}
It works but if there are constantly requests (bombarding it with requests) things get messed up. As you can see above in the writeToMemory() function I'll added a line to print out the current length of memoryBuffer and this is where I think it has somethings to do with thread safety of std::strings:
96
188
284
3639
94
190
286
2591
102
198
294
388
484
2591
96
2591
96
190
286
2591
The length of each (processed by processData()) request is 96 characters. But here the length of memoryBuffer just rises and falls down - some lengths are even bigger than maxSize (1024 chars).
EDIT: Sam pointed out I should add some more code. This is how I start the io_service:
boost::asio::io_service ioService;
boost::scoped_ptr<boost::thread> ioServiceThread;
server_class server (ioService,PORT); // Create server instance
ioServiceThread.reset (new boost::thread ( boost::bind ( &boost::asio::io_service::run, &ioService ) ) );
// Only one threaded io_service (to receive user inputs in main() function)
And this is the async_acceptor's function after completing a request:
typedef boost::shared_ptr<session_class> session_ptr;
void handleAccept(session_ptr thisSession, const boost::system::error_code& error) {
if (!error) {
thisSession->start(); // Calls the start() function above
thisSession.reset(new session(ioService,LOGGING_CLASS));
acceptor.async_accept(thisSession->socket(),boost::bind(&server_class::handleAccept, this, thisSession, PLACEHOLDER_ERROR));
}
}
The session_class holds the functions start() and handle_read(x,y) mentioned above. LOGGING_CLASS provides the class to write log files (holds the functions writeCacheToFile() and writeToMemory(char*)). log (mentioned above) is a kind of this class.
EOE: END OF EDIT
If I try to fix outsource the caching part (appending received char* to std::string) with boost::threads it ends up with a totally mixed up memoryBuffer
Is it really the thread safety of std::strings or something else I missed?
Thanks for your help in advance! :)
Paul