Using Runnable Servers
The RWTThreadIOUFunction used in the example is generally not suitable for an active object implementation that must accept any number of asynchronous requests from a client interface.
It is better to use one of the runnable server classes, RWRunnableServer or RWServerPool, to provide the internal thread or threads required by the active object. These classes are suitable because they are designed to continuously accept and execute other runnable objects. This allows you to package individual operations as synchronous runnables that can be passed to the internal server for execution. Runnable servers are covered in detail in The Server Classes.
In Example 23, individual operations are executed asynchronously relative to the thread that requests them, but simultaneous requests cannot be processed concurrently. This limitation is a consequence of choosing the single-threaded RWRunnableServer class for the internal server thread.
If an active object design can benefit from increased concurrency, then the multithreaded RWServerPool class should be used instead.
Example 23 – Using a single-threaded runnable server class
#include <rw/thread/RWRunnableServer.h>
#include <rw/thread/RWTRunnableIOUFunction.h>
#include <rw/itc/RWTIOUResult.h>
#include <rw/functor/rwBind.h>
#include <iostream>
 
using namespace std;
 
class ServiceProvider; // Forward reference for inlines!
 
class ServiceProvider {
private:
RWRunnableServer server_;
protected:
int syncService() // 1
{
int status = 0;
// Do something useful that produces a status
// value indicating success or failure
rwSleep(1000); // Waste some time...
return status;
}
public:
ServiceProvider() { // 2
server_ = RWRunnableServer::make();
server_.start();
}
~ServiceProvider() { // 3
server_.stop();
server_.join();
}
RWTIOUResult<int> asyncService() { // 4
RWTRunnableIOUFunction<int> runnable;
runnable = RWTRunnableIOUFunction<int>::make(rwBind(
&ServiceProvider::syncService,
this));
server_.enqueue(runnable);
return runnable.result();
}
};
 
void
main()
{
ServiceProvider provider; // 5
cout << "Calling asynchronous service..." << endl;
RWTIOUResult<int> iou = provider.asyncService(); // 6
cout << "Redeemed value of IOU: " << iou << endl; // 7
} // 8
//1 Defines the actual service to be performed.
//2 Defines a constructor that creates and starts the internal server.
//3 Defines a destructor that stops the internal server and waits for it to exit.
//4 Defines a member function to initiate an asynchronous operation by constructing a synchronous runnable and passing it to the internal server. The IOU representing the result of the operation is returned to the caller.
//5 Constructs an instance of the service provider.
//6 Calls the asynchronous service and save the IOU result.
//7 Redeems the IOU result, blocking if necessary, until the result is made available.
//8 The service provider object is destroyed at block scope, but the destructor does not return until its internal server thread has shutdown and exited.