New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature Request] Interruptible Blocking Statements #1113
Comments
Ignoring the complexity of unblocking all tasks waiting on a Queue, There is a problem with atomicity of this operation. What post-conditions are expected when xQueueUnblock returns a success code to the calling task? If the expectation is that no task indefinitely blocks on the queue, then there is a race condition:
The listed alternative describes a FreeRTOS binary semaphore, a wrapper around a size 1 Queue. If signals are not preferred, then the timing requirements of the system can be defined. For example, if a reader must take at most 1ms to receive from the queue and process the item, and there are 3 writers, then any write to the queue must not block more than 3ms to send onto a If the send times out, then the resource must be unavailable. A writer must have some non-volatile storage so that the message can be enqueued at a later time. I would recommend opening a thread on the FreeRTOS Forum asking why such a function function is not provided. |
I understand the difficulties some non-professionals experience trying to grapple with concurrent execution. But AFAIK, only one thread at a time can be waiting on a queue anyways. I've already provided an example on how to implement it, and have already created my own nice wrapper to abstract away the details, and called it interruptQueue(...). But the codebase is not mine, so I don't own the copyrights. If someone is working on a toy project and prefers to shift the complexity off to the user, that's just constantly reinventing the wheel. I advise you to study the the C++ standard library. Any serious project would attempt to stick to that interface for maximum portability and extend that to new platforms, not reinvent the wheel with a different api, and without the tire profiles (due to its complexity, which is more a matter of skill rather than complexity. Going about it the primitive way of carving the profile out by hand, would of course be very complex, but that's not how modern tyres are fabricated. Don't get stuck on it though, it's just an analogy). |
FreeRTOS queues can have multiple readers or multiple writers waiting on them. List_t xTasksWaitingToSend; /**< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */
List_t xTasksWaitingToReceive; /**< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */ The C++ concurrency support library provides no faculties for canceling another thread from waiting on a synchronization primitive. The only thing a thread can do to prevent itself from being blocked forever on waiting is to use timeouts ( The concurrency support library includes std::atomic<bool> stop{false};
std::mutex mutex;
std::condition_variable signal;
// consumer thread(s)
while( true )
{
std::unique_lock lock{ mutex };
signal.wait( lock );
if( stop.load() ) {
break;
}
std::cout << "Signaled\n";
}
// producer thread(s)
using namespace std::chrono_literals;
while( !stop.load() )
{
signal.notify_one();
std::this_thread::wait_for( 100ms );
}
// main thread
using namespace std::chrono_literals;
std::this_thread::wait_for( 5s );
stop.store( true );
signal.notify_all(); |
Just wondering, as already stated queues can have multiple readers or writers, but stream/messagebuffers cannot. I believe what the OP is requesting could be achieved with a streambuffer by just notifying the waiting thread, this would wake it up as if the timeout triggered in the |
Is your feature request related to a problem? Please describe.
Often I need a thread to block indefinitely on some operation, such as reading from a Queue, but still need to interrupt it when some specific event/scenario occurs, such as closing of resources. Currently such operations can only be unblocked by the queue itself or by a timeout, but not by other tasks bzw external events. This means one is forced to choose an arbitrary timeout period and check for a flag, and such a period is often either too small or too big or together and inefficient.
Describe the solution you'd like
An extra function such as xQueueUnblock(QueueHandle_t) that unblocks any thread waiting to recieve or send from/to the queue, but with a failure return value (or convert the return type into an enum on which the user can place a switch statement to determine which case, whether success, failure, interrupted, etc). It can be extended to all timeout based blocking operations in FreeRTOS.
Describe alternatives you've considered
The only way to effectively achieve the same, would be to add a dummy Queue (of size 1) used solely for the sake of interrupting, and then having the thread that wants to send/receive, to block on the set of Queues, one being the dummy, the other being the real Queue, such that an interrupting thread would place a dummy value (or read a dummy value) to unblock the target thread and use a separate flag variable to signal what happened. This is unnecessarily complicated and clutters up the code.
How many devices will this feature impact?
For me it affects only a few personal projects, but I'm sure it would benefit alot of other people, hobbyists and professionals alike, low and high volume productions.
What are your project timelines?
No timeline.
Additional context
None available
If you have the same (or similar) feature request, please upvote this issue with thumbs up 👍
and use the comments section to provide answers to the questions above.
The text was updated successfully, but these errors were encountered: