Design question: asynchronous API in C++

M

Marcel Müller

I want to provide an asynchronous C++ API. I.e. placing a request will
not immediately provide a reply. Instead a callback signals the
availability of the result.

The classic solution is to provide an interface that must be implemented
by a class of the caller. This interface contains a method for the
asynchronous callback.

Advantage: the implementing classes could also be used to track the
state of the request. (In this case it is an abstract base class rather
than an interface.)

class AsyncBase
{
// Notify availability of result.
virtual void OnCompleteion() = 0;

// Cancel an outstanding request.
// Do not call OnCompletion once it returns.
void Cancel();

// Fetch the result data (and wait if necessary).
// If called from OnCompletion() the returned data must not be used
// after OnCompletion returned.
// If /not/ called from OnCompletion the lifetime of Result is
// extended until this class instance dies.
const Result& ReceiveResult();
};

Unfortunately this is very bulky, because the caller has to implement
one class for each different call. So I would like to have a more
convenient API.

The requirements are:
- 1. The caller places a request, does some other processing and then
waits for the reply.
- 2. The caller places a request and gets notified as soon as the reply
is available.
- 3. The caller places a request with fire and forget.

Case 2 is the most important one. Whether the notification function
already receives the reply as parameters is optional. An additional call
to a method of the tracking object that is returned when placing the
request is also fine.

In fact the returned data could be rather large and a value copy should
be avoided.


Has anyone an idea that comes with less effort for the caller? I would
prefer something with template meta programming and preferably no more
than two code lines for each call.

I think that Lambda expressions would help. However, my compiler does
not support them.


Marcel
 
K

Kevin P. Fleming

I want to provide an asynchronous C++ API. I.e. placing a request will
not immediately provide a reply. Instead a callback signals the
availability of the result.

The classic solution is to provide an interface that must be implemented
by a class of the caller. This interface contains a method for the
asynchronous callback.

Advantage: the implementing classes could also be used to track the
state of the request. (In this case it is an abstract base class rather
than an interface.)

class AsyncBase
{
// Notify availability of result.
virtual void OnCompleteion() = 0;

// Cancel an outstanding request.
// Do not call OnCompletion once it returns.
void Cancel();

// Fetch the result data (and wait if necessary).
// If called from OnCompletion() the returned data must not be used
// after OnCompletion returned.
// If /not/ called from OnCompletion the lifetime of Result is
// extended until this class instance dies.
const Result& ReceiveResult();
};

Unfortunately this is very bulky, because the caller has to implement
one class for each different call. So I would like to have a more
convenient API.

The requirements are:
- 1. The caller places a request, does some other processing and then
waits for the reply.
- 2. The caller places a request and gets notified as soon as the reply
is available.
- 3. The caller places a request with fire and forget.

Case 2 is the most important one. Whether the notification function
already receives the reply as parameters is optional. An additional call
to a method of the tracking object that is returned when placing the
request is also fine.

In fact the returned data could be rather large and a value copy should
be avoided.


Has anyone an idea that comes with less effort for the caller? I would
prefer something with template meta programming and preferably no more
than two code lines for each call.

I think that Lambda expressions would help. However, my compiler does
not support them.

C++0x support async operations and futures, which is what you are trying
to create.
 
M

Marcel Müller

Kevin said:
C++0x support async operations and futures, which is what you are trying
to create.

Fine. But I do not need the implementation of the asynchronous
processing. In fact that does already exist. I need a language interface
to the library user. And I need it /without/ C++0x support. So
std::async and anything related is not an option.


Marcel
 
K

Kevin P. Fleming

Fine. But I do not need the implementation of the asynchronous
processing. In fact that does already exist. I need a language interface
to the library user. And I need it /without/ C++0x support. So
std::async and anything related is not an option.

Well, you mentioned lambdas as a way to simplify this mechanism (which
is certainly likely to be true), but you'll need C++0x for that and
"your compiler doesn't support them". That seemed to imply that C++0x
was a possible way to address your goal :)

If not, using Boost.Lambda and Boost.Thread would probably be a
reasonable way to get started.
 
Ö

Öö Tiib

I want to provide an asynchronous C++ API. I.e. placing a request will
not immediately provide a reply. Instead a callback signals the
availability of the result.

The classic solution is to provide an interface that must be implemented
by a class of the caller. This interface contains a method for the
asynchronous callback.

The abstract interfaces are simply a way to loosely couple whatever
that attaches to interface with whatever that provides the interface.
Specifying such is likely of secondary importance. First design two
concrete classes that can communicate asynchronously.
Advantage: the implementing classes could also be used to track the
state of the request. (In this case it is an abstract base class rather
than an interface.)

class AsyncBase
{
   // Notify availability of result.
   virtual void OnCompleteion() = 0;

   // Cancel an outstanding request.
   // Do not call OnCompletion once it returns.
   void Cancel();

   // Fetch the result data (and wait if necessary).
   // If called from OnCompletion() the returned data must not be used
   // after OnCompletion returned.
   // If /not/ called from OnCompletion the lifetime of Result is
   // extended until this class instance dies.
   const Result& ReceiveResult();

};

Unfortunately this is very bulky, because the caller has to implement
one class for each different call. So I would like to have a more
convenient API.

Usually modern asynchronous requests API consists of up to 6 different
elements, so it feels that you are oversimplifying the issue.
The requirements are:
- 1. The caller places a request, does some other processing and then
waits for the reply.
- 2. The caller places a request and gets notified as soon as the reply
is available.
- 3. The caller places a request with fire and forget.

On case of long asynchronous operations there are usually some more
requirements. One is that lets the client to query about progress with
that pending request or put up interface where to report progress (mid-
way completed) notifications. Other is that lets the client to cancel
(and if needed roll back) pending requests.
Case 2 is the most important one. Whether the notification function
already receives the reply as parameters is optional. An additional call
to a method of the tracking object that is returned when placing the
request is also fine.

In fact the returned data could be rather large and a value copy should
be avoided.

Has anyone an idea that comes with less effort for the caller? I would
prefer something with template meta programming and preferably no more
than two code lines for each call.

Client of asynchronous API has to provide some interface how to notify
it and variable or function where to put the results. It can of course
do it all with making the request.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,049
Latest member
Allen00Reed

Latest Threads

Top