I'm working on a design that uses a gatekeeper task to access a shared resource. The basic design I have right now is a single queue that the gatekeeper task is receiving from and multiple tasks putting requests into it.
This is a memory limited system, and I'm using FreeRTOS (Cortex M3 port).
The problem is as follows: To handle these requests asynchronously is fairly simple. The requesting task queues its request and goes about its business, polling, processing, or waiting for other events. To handle these requests synchronously, I need a mechanism for the requesting task to block on such that once the request has been handled, the gatekeeper can wake up the task that called that request.
The easiest design I can think of would be to include a semaphore in each request, but given the memory limitations and the rather large size of a semaphore in FreeRTOS, this isn't practical.
What I've come up with is using the task suspend and task resume feature to manually block the task, passing a handle to the gatekeeper with which it can resume the task when the request is completed. There are some issues with suspend/resume, though, and I'd really like to avoid them. A single resume call will wake up a task no matter how many times it has been suspended by other calls and this can create an undesired behavior.
Some simple pseudo-C to demonstrate the suspend/resume method.
void gatekeeper_blocking_request(void)
{
put_request_in_queue(request);
task_suspend(this_task);
}
void gatekeeper_request_complete_callback(request)
{
task_resume(request->task);
}
A workaround that I plan to use in the meantime is to use the asynchronous calls and implement the blocking entirely in each requesting task. The gatekeeper will execute a supplied callback when the operation completes, and that can then post to the task's main queue or a specific semaphore, or whatever is needed. Having the blocking calls for requests is essentially a convenience feature so each requesting task doesn't need to implement this.
Pseudo-C to demonstrate the task-specific blocking, but this needs to be implemented in each task.
void requesting_task(void)
{
while(1)
{
gatekeeper_async_request(callback);
pend_on_sempahore(sem);
}
}
void callback(request)
{
post_to_semaphore(sem);
}
Maybe the best solution is just to not implement blocking in the gatekeeper and API, and force each task to handle it. That will increase the complexity of each task's flow, though, and I was hoping I could avoid it. For the most part, all calls will want to block until the operation is finished.
Is there some construct that I'm missing, or even just a better term for this type of problem that I can google? I haven't come across anything like this in my searches.
Additional remarks - Two reasons for the gatekeeper task:
Large stack space required. Rather than adding this requirement to each task, the gatekeeper can have a single stack with all the memory required.
The resource is not always accessible in the CPU. It is synchronizing not only tasks in the CPU, but tasks outside the CPU as well.
Use a mutex and make the gatekeeper a subroutine instead of a task.
It's been six years since I posted this question, and I struggled with getting the synchronization working how I needed it to. There were some terrible abuses of OS constructs used. I've considered updating this code, even though it works, to be less abusive, and so I've looked at more elegant ways to handle this. FreeRTOS has also added a number of features in the last six years, one of which I believe provides a lightweight method to accomplish the same thing.
Direct-to-Task Notifications
Revisiting my original proposed method:
void gatekeeper_blocking_request(void)
{
put_request_in_queue(request);
task_suspend(this_task);
}
void gatekeeper_request_complete_callback(request)
{
task_resume(request->task);
}
The reason this method was avoided was because the FreeRTOS task suspend/resume calls do not keep count, so several suspend calls will be negated by a single resume call. At the time, the suspend/resume feature was being used by the application, and so this was a real possibility.
Beginning with FreeRTOS 8.2.0, Direct-to-task notifications essentially provide a lightweight built-into-the-task binary semaphore. When a notification is sent to a task, the notification value may be set. This notification will lie dormant until the notified task calls some variant of xTaskNotifyWait() or it will be woken if it had already made such a call.
The above code, can be slightly reworked to be the following:
void gatekeeper_blocking_request(void)
{
put_request_in_queue(request);
xTaskNotifyWait( ... );
}
void gatekeeper_request_complete_callback(request)
{
xTaskNotify( ... );
}
This is still not an ideal method, as if the task notifications are used elsewhere, you may run into the same problem with suspend/resume, where the task is woken by a different source than the one it is expecting. Given that, for me, it was a new feature, it may work out in the revised code.
Related
I have an use case where I need to apply multiple functions to every incoming message, each producing 0 or more results.
Having a loop won't scale for me, and ideally I would like to be able to emit results as soon as they are ready instead of waiting for the all the functions to be applied.
I thought about using AsyncIO for this, maintaining a ThreadPool but if I am not mistaken I can only emit one record using this API, which is not a deal-breaker but I'd like to know if there are other options, like using a ThreadPool but in a Map/Process function so then I can send the results as they are ready.
Would this be an anti-pattern, or cause any problems in regards to checkpointing, at-least-once guarantees?
Depending on the number of different functions involved, one solution would be to fan each incoming message out to n operators, each applying one of the functions.
I fear you'll get into trouble if you try this with a multi-threaded map/process function.
How about this instead:
You could have something like a RichCoFlatMap (or KeyedCoProcessFunction, or BroadcastProcessFunction) that is aware of all of the currently active functions, and for each incoming event, emits n copies of it, each being enriched with info about a specific function to be performed. Following that can be an async i/o operator that has a ThreadPool, and it takes care of executing the functions and emitting results if and when they become available.
In my Tcl extension, a secondary thread is filling the Tcl event queue with events; the events contain pointers to structures with a dynamic life time.
What is the right strategy for ensuring that no events with dangling pointers to de-allocated structures remain in the event queue? I can prevent the secondary thread from creating new events; currently I call Tcl_DoOneEvent(TCL_DONTWAIT) in a loop till it returns 0 (i.e., event queue is empty) after ensuring no new events can be created and before de-allocating the structure.
Is that the right way to do it?
On a related note, I am unsure of the purpose of Tcl_ThreadAlert(): if this is needed after every call to Tcl_ThreadQueueEvent(), why isn't the alert included in Tcl_ThreadQueueEvent()?
Finally, my code does not call Tcl_CreateEventSource(), since it doesn't seem to be needing a setup nor a check procedure as a second thread is involved. Is that cause for concern?
On the first point, that seems OK to me. It is very much like running update at the TCL level.
I'm not sure about the second point, as it isn't part of the API that I have explored a lot. It might be that way to allow multiple events to be scheduled per notification, or because there are other uses for the call, but I really don't know.
On the third point, it sounds fine. I think you never need special event sources just to do inter-thread messaging.
I have implemented a Source by extending RichSourceFunction for our Message Queue that Flink doesn't support.
When I implements the run method whose signature is:
override def run(sc: SourceFunction.SourceContext[String]): Unit = {
val msg = read_from_mq
sc.collect(msg)
}
When the run method is called, if there is no newer message in message queue,
Should I run without calling sc.collect or
I can wait until newer data comes(in this case, run method will be blocked).
I would prefer the 2nd one,not sure if this is the correct usage.
The run method of a Flink source should loop, endlessly producing output until its cancel method is called. When there's nothing to produce, then it's best if you can find a way to do a blocking wait.
The apache nifi source connector is another reasonable example to use as a model. You will note that it sleeps for a configurable interval when there's nothing for it to do.
As you probably know both options are functionally correct and will yield correct results.
This being said the second one is preferred because you're not holding the thread. In fact, if you take a look at the RabbitMQ connector implementation you'll notice that this exactly how it is implemented: inside its run it indirectly waits for messages to be placed on a BlockingQueue.
I am writing an application in WPF using .NET 4.5. The application allows the user to select multiple files and import them. When this happens the application will parse text files and store the data into a database. The files can be very large so I want the UI to remain responsive and allow the user to do other things while this is happening.
I'm new to asynchronous programming and would to know what the best approach would be? According to a Microsoft article...
"The async and await keywords don't cause additional threads to be created. Async methods don't require multithreading because an async method doesn't run on its own thread. The method runs on the current synchronization context and uses time on the thread only when the method is active. You can use Task.Run to move CPU-bound work to a background thread, but a background thread doesn't help with a process that's just waiting for results to become available."
Since I am processing multiple files would I be better of using "Task.Run" for each file since they will run on separate threads? If not, what is the advantage of running everything on the same thread using async/await?
Note that no other UI operation (except progress bars - progress reporting) really cares about when these files are done processing so according to this article it seems like using Task.Run would benefit me. What are your thoughts?
What are you doing with the files? If you're doing anything CPU intensive, it would be better to move that processing off the UI thread. If it's really just going to be the IO, then you can do it all in the UI thread - and still make it parallel.
For example:
private async Task ProcessAllFiles(IEnumerable<string> files)
{
List<Task> tasks = files.Select(x => ProcessFile(x))
.ToList();
await Task.WhenAll(tasks);
textBox.Text = "Finished!";
}
private async Task ProcessFile(string file)
{
// Do stuff here with async IO, and update the UI if you want to...
}
Here you're still doing all the actual processing on the UI thread - no separate threads are running, beyond potentially IO completion ports - but you're still starting multiple asynchronous IO operations at the same time.
Now one other thing to consider is that this might actually slow everything down anyway. If you're processing multiple files on the same physical disk, you might find that accessing them sequentially would be faster just due to the nature of disk IO. It will depend on the disk type though (SSDs would act differently to "regular" disks, for example).
Is there a (or, do you have your own) preferred way to do background processing in slices on the UI thread in Windows Forms? Like OnIdle() in MFC?
In native Windows programming you could roll your own message loop to do this, but Application.Run() doesn't give us access to the message loop.
The Application.Idle event gives us no way to trigger it repeatedly.
I guess you could call native PostMessage() with P/Invoke (since there's no managed version) to post yourself a private "WM_IDLE" message, and override WndProc() to catch it. I don't know how this would get along with Application.Run().
So far I've used a short Timer for this, but I'm afraid I may be losing cycles sleeping, especially since the actual Timer resolution is coarser than the nominal 1 ms minimum.
The best option I've seen is to use a modified version of the Managed DirectX Render Loop designed by Tom Miller. By adding a call to Thread.Sleep() inside the render loop, you can pull your CPU usage down dramatically.
This does require a P/Invoke call to track that the application is still idle, but as long as it's idle, you can make a "timer" that fires continuously during the idle phases, and use that to do your processing.
That being said, on modern systems, you almost always have extra cores. I would suggest just doing the processing on a true background thread.
I thought of my own possible answer, inspired by Reed's talk of multithreading. I may have a way to retrigger Application.Idle:
Create a hidden form, let's call it formRetrigger.
In Application.Idle, launch my Retrigger() method on a thread pool thread.
Retrigger() calls formRetrigger.InvokeOnClick() (or any of the other "Control.Invoke" methods). I expect this to launch another message through Application's queue, causing Idle to get triggered again.