Page #118 (Asynchronous Method Calls)


COM+ Pipes

The standard marshaling technique under COM was originally designed to hide the details of the RPC mechanism as much as possible. When the client calls a method, the [in] parameters are transferred to the server, and the [out] parameters are returned at the end of the call. In general, the amount of data that is passed over the network via method parameters is not much; the performance of data transfer is not that big an issue. However, if a large amount of data needs to be transferred, the standard transferring mechanism is not adequate. Pipes were introduced in COM+ to facilitate bulk data transfer within a method call.

A COM+ pipe is an ordered sequence of elements of the same type. It supports two methods, Push and Pull. As should be obvious, Push is used to send data to the server and Pull is used to fetch data from the server. The SDK defines a template-like interface definition for the pipe, shown as follows:

 interface IPipe##name : IUnknown  {   HRESULT Pull(     [out, size_is(cRequest), length_is(*pcReturned)]type *buf,      [in] ULONG cRequest,      [out] ULONG *pcReturned );    HRESULT Push(     [in, size_is(cSent)] type *buf,      [in] ULONG cSent );  } 

Based on this template, COM+ defines three pipe interfaces: IPipeByte (to transfer BYTE data type), IPipeLong (to transfer LONG data type), and IPipeDouble (to transfer DOUBLE data type).

An IPipeXXX interface can be used as any regular interface the server can implement the interface and the client can query for the interface.

The following code snippet shows an implementation of the IPipeLong::Push method:

 STDMETHODIMP CMyPipeSvr::Push(LONG *buf, ULONG cSent)  {   ::MessageBox(NULL, _T("Received data"), _T("Server"), MB_OK);    for (ULONG i=0; i<cSent; i++) {     // do something with buf[i]    }    return S_OK;;  } 

The corresponding client-side implementation that calls the IPipeLong::Push method is shown below. It generates sequential numbers and passes it to the server.

 void sub()  {   // Instantiate the object    IUnknownPtr spUnk(__uuidof(MyPipeSvr));    // Obtain the IPipeLong interface    IPipeLongPtr spPipe = spUnk;    // Push data to the pipe    const int BUFSIZE = 100000;    LONG buf[BUFSIZE];    for (long i=0; i<BUFSIZE; i++) {     buf[i] = i;    }    HRESULT hr = spPipe->Push(buf, BUFSIZE);    if (FAILED(hr)) {     _com_issue_error(hr);    }    ::MessageBox(NULL, _T("Sent data"), _T("Client"), MB_OK);  } 

Looking at the server and the client code, IPipeXXX doesn t look any different from other interfaces. So what s so special about these interfaces? The answer lies in the COM+ implementation of the proxy stub for IPipeXXX interfaces. For each pipe interface, COM+ provides a corresponding asynchronous version. The proxy/stub code for the pipe interfaces performs read-ahead and write-behind buffer management using asynchronous versions of the pipe interfaces. When Push is called from the client, the proxy pushes the data into the ORPC channel and returns immediately. This transparently improves the performance of large data transfer within the application.


COM+ Programming. A Practical Guide Using Visual C++ and ATL
COM+ Programming. A Practical Guide Using Visual C++ and ATL
ISBN: 130886742
Year: 2000
Pages: 129 © 2008-2017.
If you may any questions please contact us: