Internet Protocols Module User’s Guide : PART I Overview of the Internet Protocols Module : Chapter 2 Product Overview : Multithreading and IOUs
Multithreading and IOUs
The packages are multithread-hot and multithread-safe, which means that they create threads to complete their tasks. Each protocol request and agent action runs in a separate thread. The packages handle thread creation, management, and synchronization for you using the Threads Module of SourcePro Core.
The packages use Threads Module IOUs to allow asynchronous communication. All of the agent and client methods return RWTIOUResults, which are vouchers that can be redeemed for actual results. This means that operations never block unless you make them block by redeeming the result before the protocol command has completed its action. The IOU architecture enables you to use multithreading without explicitly handling the synchronization complexities that multithreading introduces.
The following sections briefly describe how to use IOUs. For more information, see the Threads Module User’s Guide and the Threads Module Platform Guide.
RWTIOUResult
Class RWTIOUResult allows a function in one thread to return immediately, while the code that supplies the actual result continues to run in a new thread. The RWTIOUResult instance may be redeemed immediately, as shown in the following example:
 
RWFtpReply r = ftp.cd("pub");
This function actually returns an object of type RWTIOUResult<RWFtpReply>, which is immediately converted to the redeemable type RWFtpReply. If the redeemable type is available at the time when RWFtpReply is assigned, the call does not block and the redeemable is returned. If the redeemable is not available yet (that is, the thread processing the request has not finished), then the call blocks in the assignment statement until the redeemable is available.
Under some circumstances, you may want your application to do other processing instead of waiting until the result is received. In the following example, the result of the cd method is assigned to an RWTIOUResult:
 
// Get the IOU that will eventually contain the result
RWTIOUResult<RWFtpReply> iou = ftp.cd("pub");
...
// Perform other processing
...
// Redeem the IOU and get the result
RWFtpReply r = iou; // or RWFtpReply r = iou.redeem();
The IOU can be redeemed when you are ready to use the result.
RWTIOUResult Callbacks
You can define a callback that is invoked when an RWTIOUResult becomes redeemable. The callback enables your application to perform other work instead of waiting for the result and without polling the RWTIOUResult for its completion status. The following example extends the previous example:
 
// Get the IOU that will eventually contain the result
RWTIOUResult<RWFtpReply> iou = ftp.cd("pub");
 
// Add a callback to the IOUResult that will call our member
// function when the redeemable is ready.
 
iou.addCallback(rwIOUMakeCallbackM(myClass, *this,
&myClass::getResult,
RWFtpReply));
 
void
myClass::getResult(RWTIOUResult<RWFtpReply> iou)
{
// Redeem the IOU and get the result
RWFtpReply r = iou;
}
RWTIOUResult Polling
RWTIOUResult enables your application to poll the IOU to determine if the result is available. You can then call the redeem() method without blocking, as shown in the following example.
 
// Get the IOU that will eventually contain the result
RWTIOUResult<RWFtpReply> iou = ftp.cd("pub");
 
while (!iou.redeemable()) {
// Go to sleep for a while, or do other things
}
 
// Redeem the available IOU result
RWFtpReply r = iou.redeem();
A Common Multithreading Mistake
When a new thread is created to handle the dataClose() method, the main thread may exit earlier than the new thread, which results in undesirable behavior when the new thread exits.
NOTE >> Although this software attempts to hide multithreading programming issues, your application must handle this situation.
The solution is shown in the example below. Line //1 ensures that the new thread exits before the main thread goes out of scope, by forcing the IOU to be redeemed. This blocks the main thread until the dataClose() operation has completed.
 
void main()
{
RWFtpClient client;
...
// do file transfer processing
...
// incorrect !!!
client.dataClose();
// instead, use RWFtpReply reply = client.dataClose(); //1
// or assign to IOU and use the callback mechanism
// or assign to IOU and use the polling mechanism
}