I l @ ve RuBoard |
MotivationNetworked applications that send and receive messages often require support for
Since it's hard to manually perform linearization, marshaling, and de-marshaling correctly and efficiently , these operations are best encapsulated in reusable classes, which is why ACE provides ACE_OutputCDR and ACE_InputCDR . Class CapabilitiesThe ACE_OutputCDR and ACE_InputCDR classes provide a highly optimized, portable, and convenient means to marshal and demarshal data using the standard CORBA Common Data Representation (CDR) format [Obj01]. ACE_ OutputCDR creates a CDR buffer from a data structure (marshaling) and ACE_InputCDR extracts data from a CDR buffer (demarshaling). The ACE_OutputCDR and ACE_InputCDR classes support the following features:
The interfaces for the ACE CDR streaming classes are shown in Figure 4.3. The key methods in ACE_OutputCDR class are shown in the following table:
Figure 4.3. The ACE_InputCDR and ACE_OutputCDR Class Diagrams
Likewise, the key methods for the ACE_InputCDR class are shown in the following table:
The ACE_InputCDR and ACE_OutputCDR classes transform typed data into untyped buffers and vice versa. As a result, programmers must be careful when using these classes to prevent type system violations. One way to avoid these problems altogether is to program using distribution middleware, such as CORBA [Obj01] and The ACE ORB (TAO) [SLM98] described in Section B.1.4 on page 264. ExampleThe ACE CDR streaming classes predefine operators << and >> for primitive types and arrays. ACE applications are responsible for defining these operators for their own data types. [1] To illustrate these operators, we show the ACE CDR insertion and extraction operators for the ACE_Log_Record class that's used by both the client application and logging server. This C++ class contains several fields and a variable- sized message buffer. Our insertion operation therefore marshals each field into an ACE_OutputCDR object, as shown below:
int operator<< (ACE_OutputCDR &cdr, const ACE Log Record &log_record) { size_t msglen = log_record.msg_data_len (); // Insert each <log_record> field into the output CDR stream. cdr << ACE_CDR::Long (log_record.type ()); cdr << ACE_CDR::Long (log_record.pid ()); cdr << ACE_CDR::Long (log_record.time_stamp ().sec ()); cdr << ACE_CDR::Long (log_record.time_stamp ().usec ()); cdr << ACE_CDR::ULong (msglen); cdr.write_char_array (log_record.msg_data (), msglen); return cdr.good bit (); } Our extraction operator demarshals each field from an ACE_InputCDR object and fills in an ACE_Log_Record object accordingly : int operator>> (ACE_InputCDR &cdr, ACE_Log_Record &log_record) { ACE_CDR::Long type; ACE_CDR::Long pid; ACE_CDR::Long sec, usec; ACE_CDR::ULong buffer_len; // Extract each field from input CDR stream into <log_record>. if ((cdr >> type) && (cdr >> pid) && (cdr >> sec) && (cdr >> usec) && (cdr >> buffer_len)) { ACE_TCHAR log_msg[ACE_Log_Record::MAXLOGMSGLEN+1]; log_record.type (type); log_record.pid (pid); log_record.time_stamp (ACE_Time_Value (sec, usec)); cdr.read_char_array (log_msg, buffer_len); log_msg [buffer_len] = 'int operator>> (ACE_InputCDR &cdr, ACE_Log_Record &log_record) { ACE_CDR::Long type; ACE_CDR::Long pid; ACE_CDR::Long sec, usec; ACE_CDR::ULong buffer_len; // Extract each field from input CDR stream into <log_record>. if ((cdr >> type) && (cdr >> pid) && (cdr >> sec) && (cdr >> usec) && (cdr >> buffer_len)) { ACE_TCHAR log_msg[ACE_Log_Record::MAXLOGMSGLEN+1]; log_record.type (type); log_record.pid (pid); log_record.time_stamp (ACE_Time_Value (sec, usec)); cdr.read_char_array (log_msg, buffer_len); log_msg [buffer_len] = '\0'; log_record.msg_data (log_msg); } return cdr.good_bit (); }'; log_record.msg_data (log_msg); } return cdr.good_bit (); } We'll use these two insertion and extraction operators to simplify our networked logging application shortly. |
I l @ ve RuBoard |