Provide a value-semantic type usable as an efficient identifier.
More...
Namespaces |
namespace | bmqt |
Detailed Description
- Outline
-
-
- Purpose:
- Provide a value-semantic type usable as an efficient identifier.
-
- Classes:
-
-
- Description:
- This component implements a value-semantic class,
bmqt::CorrelationId
, which can be used to identify any async operations. The correlationId contains a value (64-bit integer, raw pointer or sharedPtr) supplied by the application or uses an auto-assigned value. The type and the value of the correlationId can be set at construction time and changed later via the setNumeric()
, setPointer()
and setSharedPointer
methods. Alternatively, a CorrelationId::AutoValue
can be used to generate a unique correlationId from within the process. The bmqt::CorrelationIdLess
comparison functor can be used for storing CorrelationId
in a map as the key element; and a hash functor specialization is provided in the bsl::hash
namespace.
-
- AutoValue:
- If the application doesn't care about the actual value of the correlation, AutoValue type can be used to create a unique correlationId. An AutoValue correlationId behaves exactly the same as any other type of correlation, with the exception that it's value can not be retrieved (but two correlationId can be still compared equal).
-
- Usage:
- This section illustrates intended use of this component.
-
- Example 1: Correlating Responses:
- Suppose that we have the following asynchronous messaging interface that we want to use to implement a basic request/response class.
class Messenger {
public:
typedef bsl::function<
void(void *buffer,
int bufferLength,
const bmqt::CorrelationId& correlationId)> MessageHandler;
void sendMessage(void *buffer,
int bufferLength,
const bmqt::CorrelationId& correlationId);
void setMessageHandler(const MessageHandler& handler);
};
First we declare a requester class. class Requester {
Messenger *d_messenger_p;
bslma::Allocator *d_allocator_p;
static void handleMessage(void *buffer,
int bufferLength,
const bmqt::CorrelationId& correlationId);
public:
typedef bsl::function<void(void *buffer, int bufferLength)>
ResponseCallback;
explicit Requester(Messenger *messenger,
bslma::Allocator *basicAllocator);
void sendRequest(void *buffer,
int bufferLength,
const ResponseCallback& callback);
};
Then, we implement the constructor, setting the message handler on the provided Messenger
to our class method. Requester::Requester(Messenger *messenger,
bslma::Allocator *basicAllocator)
: d_messenger_p(messenger)
, d_allocator_p(basicAllocator)
{
d_messenger_p->setMessageHandler(&Requester::handleMessage);
}
Now, we implement sendRequest
, copying the given callback
into a correlationId that is provided to the messenger. void Requester::sendRequest(void *buffer,
int bufferLength,
const ResponseCallback& callback)
{
bsl::shared_ptr<ResponseCallback> callbackCopy;
callbackCopy.createInplace(d_allocator_p, callback, d_allocator_p);
bmqt::CorrelationId correlationId(bsl::shared_ptr<void>(callbackCopy));
d_messenger_p->sendMessage(buffer, bufferLength, correlationId);
}
Finally, we implement our message handler, extracting the response callback from the correlationId, and invoking it with the received response message. void Requester::handleMessage(void *buffer,
int bufferLength,
const bmqt::CorrelationId& correlationId)
{
assert(correlationId.isSharedPtr());
ResponseCallback *callback = static_cast<ResponseCallback *>(
correlationId.theSharedPtr().get());
(*callback)(buffer, bufferLength);
}