Overview
INCO API functions are generally threadsafe in the sense that they can be called from arbitrary application threads. For every thread, libinco_32 will setup an individual communication channel to the target via INCOServer. These resources are managed by libinco_32 and automatically released when an application thread exists. However, there a few points to consider:
CallProcedureEx
By default, tickets cannot be passed between threads, meaning that only the thread that received a ticket using CallProcedureEx() can wait for asynchronous results using CallProcedureExWait() or CallProcedureExResult(). However, if an application requires such handling, it can allow "Ticket Delegation" by calling IncoControl() with IncoCtlAllowTicketDelegation during initialization:
uint32 uAllow = 1;
if (uError) {
printf("failed to enable ticket delegation. inco_32 DLL too old?\n");
return 1;
}
This is useful in situations where a background thread is used to poll or wait for asynchronous calls to complete. There are still some limitations left:
- Only one thread is allowed to wait on a ticket at the same time, otherwise the call will fail with error ER_INCO_RPC_WAIT_EXCLUSIVE.
- The thread that created a ticket must still exist when another thread attempts to wait for a ticket, otherwise the call will fail with ER_INCO_RPC_CREATOR_THREAD_GONE.
- This mode is intended for applications that want to apply separation of concerns, e.g. by using the producer-consumer pattern to start asynchronous procedures by one thread and gather all the results by a different thread. However, it is not optimized for performance in the sense that CallProcedureExWait() may not return instantaneously when the async result is available, but with some latency in the order of milliseconds. Therefore, if your main goal is to minimize the round trip time of callprocedures, this mode may is probably not suited for you.