Signal-Slot Implementation — Part 2

C. Burak Ongay
brakulla
Published in
3 min readMay 15, 2019

In the previous post, we implemented basic signal-slot mechanism with two classes. Now we want to make them work in their own thread, but before that, I need to explain some stuff.

For inter-thread communication, or thread synchronization, there are some methodologies. I’ll focus on one of them which is one of the most efficient ones in terms of computer resources. In this approach, we use conditional variables. To understand what mutex and conditional variable are, you need to research them yourself, they are out of scope of this post.

Some concepts:

  • If you want a thread to stop while not doing anything, AFAIK, the best way to achieve that is to use conditional variables. By this way, when a thread is not working (or wating for conditional variable), it will be switched out by operating system scheduler and will not be active until conditional variable is notified. This approach prevents this thread to be switched in while not working, providing better resource management than simply polling a variable in a loop. In a polling loop the thread would run constantly. You can also put a sleep into the loop for thread to be switched out by scheduler, but that can result in delays since it has to check the variable after sleep duration.
  • Consider you have two classes, A and B, running in threads A and B, respectively. If you call a function of class A running in thread A from thread B, that function will run on thread B, in the caller thread. In order to run that function thread A, the thread of class A, you can say that it should run the function and you can say that with conditional variable.

Adding these topics up, when you want to tell another thread to do something or pass a data to be processed by another thread, you can implement a producer consumer queue, where each of them running in their own thread. This producer consumer queue will have a push function which will take an item and put it in the queue and notify the conditional wait, and another function pop that will return the first element in queue if there is an item and wait until an item is pushed if the queue is empty. By this way, if there is no item in the queue, consumer thread will block and do nothing, will be switched out. When an item is pushed to the queue, then it will wake up (waked by operating system) and start working.

This is the code for it:

This implementation is based on the idea that pop and push functions will be called from different threads. When thread A calls pop() function, it will block until an item is pushed by thread B using function push(item).

This implementation has one big problem. You have no way to stop it. For example, pop() function is called in thread A, and the executable is stopped by ctrl-c combination. Since thread A is blocked on conditional variable, it will hang waiting for conditional variable. Only way to unblock is to pop, and other threads are stopped so no way of popping.

In order to prevent this deadlock, we can introduce a boolean for its running status with a stop function. Below is the updated version:

In this version, we changed our pop function. We introduced a new function waitPop() which return a boolean and changed our pop() function to return first item in queue without waiting for conditional variable. To use this queue correctly, first you need to use waitPop() function to wait for an insertion to queue, and when it returns it tells you if you can use pop or not. If it return true, than you can use pop() function to get the first item, if false, than you should not use pop() function and do an error handling. In addition, the conditional variable is looking for both _queue.empty() condition and _stopped boolean variable. So when you call stop() function, it will notify the conditional variable and if anyone is blocked with waitPop() function, will be notified and return value will be false. So it knows that waiting is stopped not due to a ready item.

This implementation is important, since it is the base idea of achieving signal-slot mechanism with multiple threads. Which will be continued on the next post.

--

--