Firing COM events in C++ - Synchronous or asynchronous? - c++

I have an ActiveX control written using the MS ATL library and I am firing events via pDispatch->Invoke(..., DISPATCH_METHOD). The control will be used by a .NET client and my question is this - is the firing of the event a synchronous or asynchronous call? My concern is that, if synchronous, the application that handles the event could cause performance issues unless it returns immediately.

It is synchronous from the point of view of the component generating the event. The control's thread of execution will call out into the receivers code and things are out of its control at that point.
Clients receiving the events must make sure they return quickly. If they need to do some significant amount of work then they should schedule this asynchronously. For example by posting a windows message, or using a separate thread.

Related

Is it safe to call gst_bus_set_sync_handler on GStreamer pipeline bus?

To get all bus messages from my GStreamer pipelines, I am currently calling gst_bus_set_sync_handler (returning GST_BUS_DROP from my handler). This seems to work perfectly as far as I can tell, but the documentation states:
This function is usually only called by the creator of the bus.
Applications should handle messages asynchronously using the gst_bus
watch and poll functions.
Should I be worried? I assume that the "creator of the bus" is not the same as the creator of the pipeline (me), or is it?
There are a couple considerations I'm aware of regarding the use of gst_bus_set_sync_handler.
Firstly, since it runs your code synchronously in the same thread that posted the message, you'll be blocking that thread from doing other work for as long as your callback runs. If you do a fair bit of work when handling a message, this could cause performance issues.
Secondly, you may not reliably be able to use gst_element_set_state in a synchronous message handler, because elements are not allowed to set their own state in their streaming thread. Whether or not this is a problem will depend on which streaming thread in the pipeline sent the message, something you normally don't have to worry about in asynchronous messaging handlers.
I would recommend using asynchronous messaging whenever possible, as it has fewer caveats. On the other hand, if gst_bus_set_sync_handler works for you, using it shouldn't be a problem.

Making the application passive, which triggered by events?

I'm studying some codes about RS232 with Borland C++. The implementation of reading data from the port is polling the status of the port by timer. There are some events checking whether the status of the port changed. If the status changed, events trigger the data-reading subroutine.
However, I think that polling is so bad that much resource is spent on the action. Could the program be passive in monitoring the port without any aggressive polling or something else? In other words,
the program hibernates unless some events which triggered by incoming
data in the port activate it.
Is the idea is possible?
Thank you for reading
Best regards
I think for your requirements the design pattern named Reactor is appropriate. Reactor is based on the system call 'select' (which is available in both Unix and Windows environments). From the referenced document,
Blocks awaiting events to occur on a set of Handles. It returns when it is possible to
initiate an operation on a Handle without blocking. A common demultiplexer for I/O
events is select [1], which is an event demultiplexing system call provided by the UNIX
and Win32 OS platforms. The select call indicates which Handles can have operations
invoked on them synchronously without blocking the application process.
You can see that this pattern is encoded as a library in several frameworks such as ACE, Boost.
If you are working with the Win32 API functions for reading the serial port you can call ReadFile. It will suspend until it has the number of bytes you requested or until a timeout that you can set. If your program is a GUI then the serial read should be in a secondary thread so the GUI thread can react to any received Windows messages.

Priority between thread messages?

Though I am quoting this in context of Borland C++ application, but the question is both specific for Borland as well as generic in nature.
In a Borland C++ project, I observe that a user interaction with the GUI (say a menu item click) is taking less priority than a task delegated to the main thread using Synchronize(), even though the user interaction is happening a few milliseconds earlier. When the main thread is available, the delegated task is done first and then the action corresponding to the user interaction is performed. A worker thread delegates a task to main thread and waits for the task to complete using Synchronize(). So we can equate Synchronize() to SendMessage().
I believe that the user interaction queues up as a message in the message queue and same should be the case with the delegated task. But how does the task execute first? Is there any priority between messages?
Up to and including C++Builder 5, Synchronize() did indeed make a call to SendMessage(). But in C++Builder 6, Synchronize() was re-written to not use SendMessage() anymore (to support Linux under CLX). Requests are now placed in a FIFO queue, and the VCL periodically calls CheckSynchronize() to process the queue. Even though CLX is long dead, Synchronize() still uses the same FIFO queue (and it has been enhanced over the years).
Aside from that, in cases where SendMessage() is used, it does have higher priority. User interactions are posted messages to the main thread message queue (aka PostMessage()). Although SendMessage() goes directly to a window's wndproc, it is not called until the receiving window's owning thread performs message processing if sent by a different thread (which used to be the case with Synchronize()). Pending SendMessage() requests to the main thread message queue have higher priority than pending posted messages to the same queue, as there are other threads/processes being blocked until the pending SendMessage() requests are processed.

Asynchronous Agents and window messages

I'm currently playing with the Asynchronous Agents Library in Microsoft's Concurrency Runtime. I have not yet found an obvious way to signal that a task is finished by using window messages, or some other means of notifying the UI thread that the work is finished.
I know I can pass window handles and message values (WM_xxx) along to the tasks, and have the task use PostMessage() to signal the UI thread. This is somewhat ugly in my opinion, and a source of error. If an exception occurs, I have to have a catch handler that signals my UI thread. This is easily forgotten, and the exception condition might not be run very often, so it's hard to spot it.
The documentation talks about how to move data back to the UI thread. It does not make use of window messages, but polling techniques. I find it silly to set up timers to poll if a task has finished, when there are "interrupt" methods available!
It's kind of odd that this isn't built into the library, as it's not a cross platform library. It's designed to run on Windows, and Windows only, from what I understand.
Is the functionality available in the library, or do I have to hand roll this?
You can create one monitor thread with sole function of monitoring an unbounded_buffer for a windows message and dispatching that message appropriately. Have your agents know about this buffer.

Timer Vs Event: which one is preferable for Asynchronous processing?

Ours is a huge project. I need to call certain functions in my code asynchronously to avoid some circular function calls. Upon receiving a specific input, I can call my function asynchronously either by using Event or Timer.
Which way is preferable considering Performance ?
Sending events to Event manager and handling them with an Event handler ? Or
Starting a timer and provide timeout handler ?
For pure performance, event-driven model will be better. Use timers only if you cannot rely on one or more of your events to get set in a timely way by the worker code, and so need a backup means by which to continue processing. This may be the case if your worker code makes external calls to a database or other remote service whose reliability or performance is unproven.