one task previleged in asio io_service - boost-asio

I have io_service with one task (deadline_timer) that is fired every 1 sec.
Next, I want to create new thread by thread t1(bind(&io_service::run, &ios)); for some other tasks.
How to be sure (if possible) that deadline_timer will not be interrupted? Or better, be sure that it has own thread.

To guarantee that an I/O object, such as a deadline_timer, has its own dedicated thread, one could use multiple io_service objects:
an io_service for the timer processed by a single thread or group of threads
an io_service for all other tasks and I/O objects processed by a different thread or different group of threads
Using multiple io_service objects can help prevent contention between event handling and dispatching. For example, an io_service will not be impacted by a completion handler that is taking a long time to complete within a different io_service. However, all threads are still subject to the OS scheduler, where interruptions may occur.
Below is an example demonstrating using multiple io_service objects, where a deadline_timer is being processed by a dedicated thread:
#include <iostream>
#include <thread>
#include <boost/asio.hpp>
void arm_timer(boost::asio::deadline_timer& timer)
{
timer.expires_from_now(boost::posix_time::milliseconds(500));
timer.async_wait([&timer]
(const boost::system::error_code& error)
{
std::cout << "timer: " << error.message() << std::endl;
arm_timer(timer);
});
}
int main()
{
// Dedicate an io_service and thread to a single timer.
boost::asio::io_service timer_io_service;
boost::asio::deadline_timer timer(timer_io_service);
arm_timer(timer);
std::thread timer_thread([&timer_io_service]() {
timer_io_service.run();
});
// Use a different io_service for other tasks.
boost::asio::io_service io_service;
// Post a tasks to stop the timer io_service.
io_service.post([&timer_io_service]{
timer_io_service.stop();
});
// Let timer run.
std::this_thread::sleep_for(std::chrono::seconds(2));
io_service.run();
timer_thread.join();
}

Related

QThread always stuck in wait

I am trying to use QThread to call a function in another thread without having the UI to freeze. I am using QT5.11.2 on both windows and linux.
Everything works fine on windows but the wait() function for QThread never returns no matter what.
I use RHEL7 on linux
Here is what I am doing:
void MainWidget::configure_click(double value)
{
QThread *myThread = QThread::create([this, value]{ Configure(value); });
dsoThread->setObjectName("My Configure Thread");
QObject::connect(myThread, &QThread::finished, [](){ qDebug()<< "Configure Thread has finished";}); // This is never printed
myThread->start();
myThread->wait(); // Never returns from this
myThread->quit();
myThread->deleteLater();
}
My Configure function prints its start and finish and both lines are being printed on run time
void MainWidget::Configure(double value)
{
qDebug() << QThread::currentThread() << " started";
// Code to execute
qDebug() << QThread::currentThread() << " finished";
}
I even read that quit() forces the thread to stop, so just for testing I tried switching quit() and wait() like so
myThread->quit();
myThread->wait(); // Never returns from this either
myThread->deleteLater();
I even tried looping the isRunning() function instead of wait() but I got the same results
while(myThread->isRunning()) // Same goes for !isFinished()
{
// Do nothing
}
It seems like no matter what the thread never knows that it was finished.
What can I do to either solve this problem or to check why this is happening?
You haven't start()ed the thread.
myThread->wait(); in gui thread waits for thread to terminate so it blocks gui thread event loop, so you lose all benifints of threading this way and might as well just do Configure(value); without threading.
Documentation says:
wait() and the sleep() functions should be unnecessary in
general, since Qt is an event-driven framework. Instead of
wait(), consider listening for the finished() signal. Instead of
the sleep() functions, consider using QTimer.

How to force a libusb event so that libusb_handle_events() returns

Suppose I have a libusb program that just uses the hotplug API. You register a callback and then apparently have to call libusb_handle_events() in a loop which then calls your hotplug callback.
int LIBUSB_CALL hotplugCallback(libusb_context* ctx,
libusb_device* device,
libusb_hotplug_event event,
void* user_data)
{
cout << "Device plugged in or unplugged";
}
void main()
{
libusb_init(nullptr);
libusb_hotplug_register_callback(nullptr,
static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
LIBUSB_HOTPLUG_NO_FLAGS,
LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY,
&hotplugCallback,
this,
&hotplugCallbackHandle);
for (;;)
{
if (libusb_handle_events_completed(nullptr, nullptr) != LIBUSB_SUCCESS)
return 1;
}
return 0;
}
The question is, without timeout hacks how can I exit this event loop cleanly? I can't find any functions that force libusb_handle_events() (or libusb_handle_events_completed()) to return. In theory they could just never return.
Sorry if this is late.
The question could have been phrased better but I'm assuming (from your comment updates) that your actual program resembles something a little closer to this:
int LIBUSB_CALL hotplugCallback(libusb_context *ctx,
libusb_device *device,
libusb_hotplug_event event,
void *user_data) {
cout << "Device plugged in or unplugged";
}
void SomeClass::someFunction() {
libusb_init(nullptr);
libusb_hotplug_register_callback(nullptr,
static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
LIBUSB_HOTPLUG_NO_FLAGS,
LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY,
&hotplugCallback,
this,
&hotplugCallbackHandle);
this->thread = std::thread([this]() {
while (this->handlingEvents) {
int error = libusb_handle_events_completed(context, nullptr);
}
});
}
Let's say your object is being deallocated and, no matter what is happening on the USB bus, you don't care and you want to clean up your thread.
You negate this->handlingEvents and you call thread.join() and the thread hangs for 60 seconds and then execution resumes.
This is done because the default behavior of libusb_handle_events_completed calls libusb_handle_events_timeout_completed and passes in a 60 second timeout interval with plans to make it infinite.
The way you force libusb_handle_events_completed to return is you call libusb_hotplug_deregister_callback which wakes up libusb_handle_events(), causing the function to return.
There is more info about this behavior in the docs.
So your destructor (or wherever you want to stop listening immediately) for the class could look something like this:
SomeClass::~SomeClass() {
this->handlingEvents = false;
libusb_hotplug_deregister_callback(context, hotplugCallbackHandle);
if (this->thread.joinable()) this->thread.join();
libusb_exit(this->context);
}
In the function:
int libusb_handle_events_completed(libusb_context* ctx, int* completed)
You can change the value of the completed to "1" so the function will return without blocking
According to their docs:
If the parameter completed is not NULL then after obtaining the event
handling lock this function will return immediately if the integer
pointed to is not 0. This allows for race free waiting for the
completion of a specific transfer.
There is no functions in libusb that force libusb_handle_events() to return.
It's recommended to use libusb_handle_events() in a dedicated thread so your main thread will not be blocked by this call. Even though, if you need to manipulate the call of the event handler you can put the call in a while(condition) and change the condition state in your main thread.
Libusb documentation details this here.

STM32F412 using FreeRTOS and USB to do audio processing

I am using stm32f4 nucleuo board. I can transmit the audio data through usb to PC without FreeRTOS. Now I want to learn how to integrate the FreeRTOS and usb together. But I have some questions about how fundamentally threads and ISR interact with each other.
Below I have two files.
In main.c, there are two threads created.In usb_thread, I initialize usb dirver and do nothing else.
In vr_thread, it waits state == 1 and process PCM_Buffer.
/* main.c */
extern uint16_t PCM_Buffer[16];
int state = 0;
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
osThreadDef(usb_t, usb_thread, osPriorityNormal, 0, configMINIMAL_STACK_SIZE);
osThreadDef(vr_t, vr_thread, osPriorityNormal, 0, configMINIMAL_STACK_SIZE);
usb_thread_handle = osThreadCreate (osThread(usb_t), NULL);
usb_thread_handle = osThreadCreate (osThread(vr_t), NULL);
osKernelStart();
for (;;) {}
}
static void usb_thread(void const *argument)
{
/*Do some initialization here.*/
for (;;) {}
}
static void vr_thread(void const *argument)
{
/*Do some initialization here.*/
for (;;) {
if (state == 1) {
state = 0;
process_buffer(PCM_Buffer);
}
}
}
In app.c, USB_AUDIO_CallBack will be called by usb ISR every 1 millisecond. It transmit PCM_Buffer to PC first because it is really important, then it changes state to 1.
/* app.c */
uint16_t PCM_Buffer[16];
extern int state;
void USB_AUDIO_CallBack(void) //It will be called by usb ISR every 10^-3 second.
{
Send_Audio_to_USB((int16_t *)(PCM_Buffer), NUM_AUDIO_BUF);
state = 1;
}
Here are my questions.
1. How to find out the unit counting tick of FreeRTOS? USB_AUDIO_CallBack will be
called every 1 millisecond, how to know FreeRTOS basic tick is faster or slower
than 1 millisecond. Is FreeRTOS tick equal to systick?
2. Let's assume the process time of process_buffer is less than 1 millisecond. What I want to accomplish here is described below
hardware trigger
|
usb ISR
|
USB_AUDIO_CallBack
|
state=1
|
vr_thread process_buffer
|
state=0, then wait for hardware trigger again.
I really doubt it is the correct way to do it. Or should I use suspend() and resume()?
3. Is using extern to declare global PCM_Buffer the correct way to pass variable between threads or should I use queue in FreeRTOS?
I know these questions are trivial but I really want to understand them. Any helpful document or website is welcome. Thanks.
To convert real time to systick you can use macro pdMS_TO_TICKS(xTimeInMS).
You can define your USB_AUDIO_CallBack also as a thread (or task) or paste the code from the callback to vr_thread (as your application works on only one processor). Then inside the USB ISR you can send a notification using function vTaskNotifyGiveFromISR and receive it inside vr_thread by calling ulTaskNotifyTake. After receiving the notification you can call Send_Audio_to_USB((int16_t *)(PCM_Buffer), NUM_AUDIO_BUF);
and then process_buffer(PCM_Buffer);. It is better to bring out the code from callback to task, because the ISR handler will finish it's job faster as Send_Audio_to_USB function could run long time. You also keep things to be executed in the same order as you needed.
I think that you mean volatile instead of extern. If you want to use this buffer along different threads and ISRs you should define it as volatile, but if you will use the approach with only one task you can declare this buffer as local buffer.

How to wake up a process blocked by pause()?

I need to block and wake a process using SIGUSR2 and SIGUSR1 respectively. Below here's my signal handler sub routine. How do I wake a process blocked by pause?
void sig_handler(int sig) {
static int i = 1;
if(sig == SIGUSR2) {
pause();
}
else if(sig == SIGUSR1) {
/* I don't what to write here */
}
}
Also, I read somewhere pause() is not a good programming practice, is there any other means to suspend a process for some time?
See this page
In general, doing a lot of works in signals is ... tricky. Some things are not async-signal-safe, and therefore it makes robust programming there a bit difficult. In your case, pause() waits for a signal to arrive, but since you are calling it from the signal handler, it is not going to work there (I think).
As to making the process sleep and resume on signals. Look at the page I linked above. The best way is to have the signal handlers simply set flags and have the main thread (i.e. in main() or in an event loop) react to these flags. As recommended by the page, use sigsuspend when SIGUSR2 is received to pause the process until SIGURS1 is received.
It's simple. Use the 'kill' system call-
void sig_handler(int sig) {
static int i = 1;
if(sig == SIGUSR2) {
pause();
}
else if(sig == SIGUSR1) {
kill(<pid of process to wake up>, sig);
// make sure that process with pid has registered for sig
}
}

Using Dispatch Semaphores with delegate methods

So I have a wrapper class that when I send it a message, it returns YES/NO based on whether the internal object RECEIVED the message. Meaning, when I send this, it doesn't actually return when the task is done. I also want to make sure that only one task is executed at a time, so I use dispatch semaphores. My wrapper class calls a delegate method to notify me that it finished processing the internal task.
dispatch_queue_t queue = dispatch_queue_create("com.test.all", 0); // private queue
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1); // one at a time
...
- (void)doStuff:(NSString *)stuff {
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_sync(queue, ^(void) {
[myWrapperObject sendRequestToInternalStuff:stuff];
}
}
...
- (void)myWrapperClassProcessingIsDone {
dispatch_semaphore_signal(semaphore);
}
This doesn't work, and it hangs. How can I implement something like this without hanging?
If you want to ensure that only one task is executed at a time, the correct approach is to execute each task on the same serial GCD queue. A serial queue always executes just one task at a time. The dispatch_queue_create function creates a serial queue when you pass 0 (or DISPATCH_QUEUE_SERIAL or NULL) as the second argument..
If anyone needs to know, there is no way to do this. The semaphore locks the thread, so you would have to have a separate spawned thread with a run-loop waiting for a variable change. I just re-worked my code to avoid semaphores.