I have simple Application which receives messages through TCP Socket and process the same messages and Perform Some Actions.
I have used std::queue's to store the messages and process them on a thread.
Application is working fine with no crash. But, after few minutes the application consumes heavy cpu.
Here is my insert message and process message ( thread) code
My Simple Queue and thread veriables
std::queue<std::string> in_data_queue;
pthread_mutex_t in_data_queue_lock=PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t in_data_queue_condition=PTHREAD_COND_INITIALIZER;
Code For Processing Queue
void *processMessage(void *attr) {
while (true) {
try {
if (pthread_mutex_trylock(&in_data_queue_lock) == 0) {
if (!in_data_queue.empty()) {
std::string data = in_data_queue.front();
in_data_queue.pop();
pthread_cond_signal(&in_data_queue_condition);
pthread_mutex_unlock(&in_data_queue_lock);
// do some action ;
} else {
pthread_cond_wait(&in_data_queue_condition,
&in_data_queue_lock);
pthread_mutex_unlock(&in_data_queue_lock);
}
}
} catch (std::exception &e) {
cout << e.what() << endl;
}
cout << "processMessage" << endl;
}
pthread_exit(NULL);
}
Code For Insert the Message in Queue
void pushMessage(std::string rData) {
pthread_mutex_lock(&in_data_queue_lock);
in_data_queue.push(rData);
pthread_cond_signal(&in_data_queue_condition);
pthread_mutex_unlock(&in_data_queue_lock);
}
Any body help me what's the wrong with thread. Is that fine implementation or any issue on this thread. Please help me..
Related
I have tried to create a server with asio, when i try to integrate a timer behind the event handler from client.
asio::io_context m_asioContext;
std::thread m_threadContext;
void print()
{
std::cout << "Hello, world!" << std::endl;
SendTimer();
}
void SendTimer()
{
asio::steady_timer timer(m_asioContext, asio::chrono::seconds(2));
timer.async_wait(boost::bind(&server_interface::print, this));
}
bool Start()
{
try
{
// Issue a task to the asio context - This is important
// as it will prime the context with "work", and stop it
// from exiting immediately. Since this is a server, we
// want it primed ready to handle clients trying to
// connect.
WaitForClientConnection();
std::cout << "[SERVER] Started!azazaz\n";
// Launch the asio context in its own thread
m_threadContext = std::thread([this]() { m_asioContext.run(); });
}
catch (std::exception& e)
{
// Something prohibited the server from listening
std::cerr << "[SERVER] Exception: " << e.what() << "\n";
return false;
}
std::cout << "[SERVER] Started!\n";
return true;
}
void Update(size_t nMaxMessages = -1, bool bWait = false)
{
if (bWait) m_qMessagesIn.wait();
// Process as many messages as you can up to the value
// specified
size_t nMessageCount = 0;
while (nMessageCount < nMaxMessages && !m_qMessagesIn.empty())
{
// Grab the front message
auto msg = m_qMessagesIn.pop_front();
// Pass to message handler
OnMessage(msg.remote, msg.msg);
nMessageCount++;
}
Update(nMaxMessages, bWait);
}
Server call
CustomServer server(60000);
server.Start();
asio::io_context io;
server.Update(-1, true);
It'seem that the timer could not run correctly. Just like the infinitive loop. I really newbie with asio. So I wonder how we could keep multi event with only a thread.
Thanks for your answer.
I've been trying to write both periodic and non-periodic messages on a serial port using Windows API. The architecture of my code is the following:
The main thread starts the following :
A "message sending thread" that will be responsible for writing data over the serial port. It will wait on a condition variable to be waken up by other threads, then will send data contained in a buffer over the serial port. I'm protected from Spurious wake-ups by a flag.
A thread that builds a message, fill the data buffer and notifies the "message sending thread" with the notify_one() function every 100ms.
For debug purpose, the main thread also loops a few times on another function that builds a message and notifies the "message sending thread" the same way as the timer do every 500 ms. Here's the code
#include <iostream>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <Windows.h>
std::condition_variable m_cvSend;
std::mutex m_mtxSend;
std::thread m_threadSendMessage;
std::thread m_threadPeriodicMessage;
char messageToSend[512] = { 0 };
bool newMessage = false;
bool threadRunning = false;
int count = 0;
void SendPeriodicMessage();
void SendFoo();
void sendMessageRun(void);
int main()
{
threadRunning = true;
//Start message sending thread
m_threadSendMessage = std::thread(&sendMessageRun);
m_threadPeriodicMessage = std::thread(&SendPeriodicMessage);
Sleep(1000);
while (count < 20) {
SendFoo();
Sleep(500);
count++;
}
m_threadSendMessage.join();
}
void sendMessageRun(void) {
std::unique_lock<std::mutex> lck(m_mtxSend);
DWORD bytesEcrits = 0;
while (threadRunning == true) {
m_cvSend.wait(lck, [&] {return newMessage; });
std::cout << "I'm HERE" << std::endl;
std::cout << messageToSend << std::endl;
//Send message over Serial port
//NOT RELEVANT FOR THE ISSUE
//Clean buffer
Sleep(20);
memset(messageToSend, 0, sizeof(messageToSend));
bytesEcrits = 0;
newMessage = 0;
}
}
//Envoi d'une consigne de pointage
void SendPeriodicMessage() {
while (true) {
//Send every 100 ms
Sleep(100);
std::lock_guard<std::mutex> lkEnvoi(m_mtxSend);
strcpy_s(messageToSend, "Thread 1");
//Flag for spurious wake ups
newMessage = true;
//// Debug
//std::cout << "Message to be sent periodically" << std::endl;
//std::cout << messageToSend << std::endl;
//End of critical section
//Notify sending thread
m_cvSend.notify_one();
}
}
void SendFoo() {
std::lock_guard<std::mutex> lkEnvoi(m_mtxSend);
char countChar[3] = { 0 };
_itoa_s(count, countChar, 10);
strcpy_s(messageToSend, "foo");
strcat_s(messageToSend, countChar);
//Flag for spurious wake ups
newMessage = true;
//End of critical section
//Notify sending thread
m_cvSend.notify_one();
}
While running this, I see that the foo function sometimes doesn't wake up the thread. In fact, the function should notify the thread to wake up through the notify_one() function. However, I suppose the wait() function doesn't unlock as I don't observe another "I'M HERE" on the console.
I've seen that waking up a thread with a notify_one() is done atomically so I don't understand why it wouldn't be done with something in between interfering.
I've tried changing the thread priorities using Windows API but it doesn't work.
Some help would be highly appreciated for this first post!
Thank you!
You have two different threads which can "send" a message. Neither of those threads whether theres already a pending message (e.g. newMessage==true;).
notify_one will eventually notify the receiving thread, but there's nothing that guarantees it does so immediately.
Add an assert(! newMessage); in both of your send functions, and you'll presumably see one being hit.
I have my application main loop control where I do start a thread to handle asio work as follows:
void AsioThread::Run()
{
try
{
/*
* Start the working thread to io_service.run()
*/
boost::asio::io_service::work work(ioService);
boost::thread t(boost::bind(&boost::asio::io_service::run, &ioService));
t.detach();
while (true)
{
// Process stuff related to protocol, calling
// connect_async, send_async and receive_async
}
}
catch (std::runtime_error &ex)
{
std::cout << "ERROR IN FTP PROTOCOL: " << ex.what() << std::endl;
}
catch (...)
{
std::cout << "UNKNOWN EXCEPTION." << std::endl;
}
During the async operation, the handlers are called and sometimes I do throw exception on those handlers, like:
void AsioThread::ReceiveDataHandler(const boost::system::error_code& errorCode, std::size_t bytesTransferred)
{
std::cout << "Receive data handler called. " << bytesTransferred << " bytes received." << std::endl;
if (errorCode)
{
std::cout << "Error receiving data from server." << std::endl;
}
rxBufferSize = bytesTransferred;
/*
* Check for response
*/
std::string msg(rxBuffer);
if (msg.substr(0, 3) != "220")
throw std::runtime_error("Error connecting to FTP Server");
}
My problem is that the exception thrown inside the async handler (AsioThread::ReceiveDataHandler) is not catched by the main processing loop try...catch block in AsioThread::Run. Naturally this happens because the working thread t is on another thread, detached, and at runtime that leads to an execution error.
How can I receive exceptions from the detached boost::asio::io_service::work thread ? How can I structure my code to make this logic work ?
Thanks for helping.
You can catch exceptions in the worker thread, save them into a queue variable that is shared by the two threads, and check that queue periodically in the main thread.
To use a queue, you need to first convert your exceptions to a common type. You can use std::exception or string or whatever is the best for your situation. If you absolutely need to keep information of the original exception class, you can use boost::exception_ptr.
Variables you need (these could be members of AsioThread):
boost::mutex queueMutex;
std::queue<exceptionType> exceptionQueue;
Run this function in the worker thread:
void AsioThread::RunIoService(){
try{
ioService.run();
}
catch(const exceptionType& e){
boost::lock_guard<boost::mutex> queueMutex;
exceptionQueue.push(e);
}
catch(...){
boost::lock_guard<boost::mutex> queueMutex;
exceptionQueue.push(exceptionType("unknown exception"));
}
}
Launch the worker thread like this:
boost::thread t(boost::bind(&AsioThread::RunIoService, this));
t.detach();
In the main thread:
while(true){
// Do something
// Handle exceptions from the worker thread
bool hasException = false;
exceptionType newestException;
{
boost::lock_guard<boost::mutex> queueMutex;
if(!exceptionQueue.empty()){
hasException = true;
newestException = exceptionQueue.front();
exceptionQueue.pop();
}
}
if(hasException){
// Do something with the exception
}
}
This blog post implements a thread-safe queue, which you can use to simplify saving exceptions; in that case you would not need a separate mutex because that would be inside the queue class.
Building a SignalR C++ client using Visual Studio 2013, I am starting with the working sample code from NuGet Package Microsoft.AspNet.SignalR.Client.Cpp.v120.WinDesktop, source here
Reviewing the library source it seems to me the event handling processes are based on the Concurrency Runtime (pplx::task) which relies on C++11 features
void chat(const utility::string_t& name)
{
signalr::hub_connection connection{ U("https://testsite") };
auto proxy = connection.create_hub_proxy(U("ChatHub"));
proxy.on(U("broadcastMessage"), [](const web::json::value& m)
{
ucout << std::endl << m.at(0).as_string() << U(" wrote:") << m.at(1).as_string() << std::endl << U("Enter your message: ");
});
connection.start()
.then([proxy, name]()
{
for (;;)
{
utility::string_t message;
std::getline(ucin, message);
if (message == U(":q"))
{
break;
}
send_message(proxy, name, message);
}
})
.then([&connection]() // fine to capture by reference - we are blocking so it is guaranteed to be valid
{
return connection.stop();
})
.then([](pplx::task<void> stop_task)
{
try
{
stop_task.get();
ucout << U("connection stopped successfully") << std::endl;
}
catch (const std::exception &e)
{
ucout << U("exception when starting or stopping connection: ") << e.what() << std::endl;
}
}).get();
}
I want to eliminate the "user input" component; and instead quit loop when a particular "broadcastMessage" has been received.
If I replace the for loop with a sleep statement, the broadcastMessage event stops firing.
If I use the for loop without the getline, set bComplete to true when done, it works the way I want but causes high CPU usage (obviously)
for (;;)
{
if (bComplete) break;
}
Ideally I want connection to start, and then just wait until the broadcastMessage events signals to close the connection.
In addition the "chat" function shouldn't return until connection has closed.
I can see in your answer that you've already discovered Windows event objects; however, if you were looking for a C++11 platform-independent solution, consider std::condition_variable!
unsigned int accountAmount;
std::mutex mx;
std::condition_variable cv;
void depositMoney()
{
// go to the bank etc...
// wait in line...
{
std::unique_lock<std::mutex> lock(mx);
std::cout << "Depositing money" << std::endl;
accountAmount += 5000;
}
// Notify others we're finished
cv.notify_all();
}
void withdrawMoney()
{
std::unique_lock<std::mutex> lock(mx);
// Wait until we know the money is there
cv.wait(lock);
std::cout << "Withdrawing money" << std::endl;
accountAmount -= 2000;
}
int main()
{
accountAmount = 0;
std::thread deposit(&depositMoney);
std::thread withdraw(&withdrawMoney);
deposit.join();
withdraw.join();
std::cout << "All transactions processed. Final amount: " << accountAmount << std::endl;
return 0;
}
In this example we make two threads: one to deposit money into the account and one to withdraw money. Because it's possible for the thread to withdraw the money to run first, especially because there's more processing involved with depositMoney(), we need to wait until we know the money is there. We lock our thread before accessing the money, and then tell the condition_variable what we are waiting for. The condition_variable will unlock the thread, and once the money has been deposited and notify_all() is called we'll be re-awoken to finish processing our logic.
Note that it's possible to do the exact same using the Windows event objects. Instead of std::condition_variable::wait() and std::condition_variable::notify_all() you'd use SetEvent() and WaitForSingleObject(). This is platform-independent though.
I got this working using WinAPI WaitForSingleObject:
HANDLE hEvent;
void chat(const utility::string_t& name)
{
signalr::hub_connection connection{ U("https://testsite") };
auto proxy = connection.create_hub_proxy(U("ChatHub"));
proxy.on(U("broadcastMessage"), [](const web::json::value& m)
{
ucout << std::endl << m.at(0).as_string() << U(" wrote:") << m.at(1).as_string() << std::endl;
if (m.at(1).as_string() == L"quit")
{
SetEvent(hEvent);
}
});
hEvent = CreateEvent(0, TRUE, FALSE, 0);
connection.start()
.then([proxy, name]()
{
WaitForSingleObject(hEvent, INFINITE);
})
.then([&connection]() // fine to capture by reference - we are blocking so it is guaranteed to be valid
{
return connection.stop();
})
.then([](pplx::task<void> stop_task)
{
try
{
stop_task.get();
ucout << U("connection stopped successfully") << std::endl;
}
catch (const std::exception &e)
{
ucout << U("exception when starting or stopping connection: ") << e.what() << std::endl;
}`enter code here`
}).get();
}
When having multiple threads using shared data, how does one correctly handle the destruction of that data when exceptions are thrown?
I'm working on an application where I want one process to be doing work while waiting for a result sent from another process over a network. I implemented a class that creates a thread to wait for the result, something like the following (actual code is too large to post here, so this is a small example):
class Notifier {
public:
Notifier(Client* _client) : value(-1), client(_client) {
listener = boost::thread(&Notifer::Listen, this);
}
void Listen() {
try {
int rec = client->Receive(); //blocking call to receive data over a socket
boost::scoped_lock sl(mutex);
value = rec;
} catch (...) {
cout << "Exception thrown in listener" << endl;
}
}
int Get() {
boost::mutex::scoped_lock sl(mutex);
return value;
}
private:
int value;
boost::mutex;
boost::thread listener;
Client* client;
}
int main() {
Client client; //initialize client, connect, etc.
Notifier n(client);
while(n.Get() < 0) {
// do work
cout << "Waiting for data" << endl;
sleep(1);
}
}
This works fine for me until I add exception handling:
int main() {
try {
Client client; //initialize client, connect, etc.
Notifier n(client);
while(n.Get() < 0) {
// do work
cout << "Waiting for data" << endl;
sleep(1);
throw exception();
}
} catch(...) {
cout << "Exception thrown in main" << endl;
}
return 0;
}
I get the error
"boost: mutex lock failed in pthread_mutex_lock: Invalid argument".
My guess is that, when the exception gets thrown, the stack for the main function gets unwound, destroying the mutex. Then the Receive() call in the Listen function returns and the scoped_lock constructor tries to lock the mutex, which doesn't exist, resulting in the error.
Can someone confirm that this is indeed what is happening? If so, is there a way to communicate to the thread that that the mutex no longer exists or that the thread should terminate? Or is there a more exception-safe way of doing what I'm trying to do?
You have to write a correct destructor for Notifier class, which would cancel all blocked calls (i.e. unblock client->Receive()) and then terminate listener thread. Also you need to modify Notifier::Listen() to periodically check for thread termination request... then everything will be Ok.