CORBA programming with Tao-4. Basic functions (common basic method analysis)
Abstract:This section briefly introduces the functions of several common basic methods defined by the CORBA specification and issues that need attention in applications.
Body:The IDL compiler generates a corresponding Proxy Base Class: Class interfacename for each interface declared in IDL; and two object reference types: interfacename_ptr and interfacename_var. The former is a pointer type, its definition is often: typedef interfacename * interfacename; therefore, we will not discuss it too much. Interfacename_var is a smart pointer class. By using the smart pointer class, we do not need to manually maintain the pointer reference count, which greatly simplifies the compilation of applications. The following describes several basic methods in the proxy base class and the _ var smart pointer class.
I. Several Basic methods defined in the Proxy Base ClassEach proxy base class (as well as CORBA: Object) provides the following static methods:
· _ DuplicateReturns a copy of a parameter pointer. (to avoid the consumption caused by object deep copy, the reference count is adjusted)
· _ NilReturns an empty reference of the corresponding interface type.
· _ NarrowTry to convert the parameter pointer to the target pointer. If the conversion fails, a null reference of the target type is returned. In addition to the above static methods, each proxy class also includes two methods:
· _ Is_aThis method receives a type ID information const char * type_id and returns a CORBA: Boolean to determine whether a reference is of the type indicated by type_id.
· _ ThisThis method returns the reference of the current object copy.
· _ Add_ref/_ remove_refThis method is used to increase the reference count and reduce the reference count, which may be used when we compile the interface implementation (these two methods cannot be used in the client program, because only the skeleton code generates these two methods, the customer program code does not need to use these two methods to maintain the reference count ). In addition, the following definitions are also defined in the CORBA namespace:
· CORBA: is_nilDetermines whether a PTR is null.
· CORBA: ReleaseRelease the parameter object. To compare whether the two references are the same, the following methods are defined in "CORBA: object:
· Is_equivalentAccording to the CORBA specification, the Behavior Produced by comparing, converting, and testing non-empty objects or object pointers using the above basic methods is not defined. These methods are relatively simple and will be used in subsequent articles.
Ii. Basic Methods in the _ var smart pointer classAccording to the CORBA specification, every _ var smart pointer class includes the following methods: · In · out · inout · _ retn · PTR the easiest way to master these methods is to learn about CORBA:: Implementation of the string_var class. CORBA: string_var is a smart pointer class of the CORBA: string class, which encapsulates a char * pointer. Let's take a look at how Tao implements these methods (see % tao_root %/TAO/corba_string.inl): ace_inline const char * CORBA: string_var: In (void) const {return this-> PTR _;} ace_inline char * & CORBA: string_var: inout (void) {return this-> PTR _;} ace_inline char * & CORBA :: string_var: Out (void) {CORBA: string_free (this-> PTR _); this-> PTR _ = 0; return this-> PTR _;} ace_inline char * CORBA: string_var: _ retn (void) {char * temp = This-> PTR _; thi S-> PTR _ = 0; return temp;} // Tao extension. ace_inline char * CORBA: string_var: PTR (void) {return this-> PTR _;} does not seem to be worth noting on the surface, but returns several different types of pointers: the in method returns a pointer (because it is only used as an input parameter). The inout method returns a reference to a pointer (because it must be used not only as an input parameter, but also as a function call to modify its content ), the out method also returns a pointer reference (because the content needs to be modified through a function call), The inout method returns a pointer (because it is only used as a return parameter and cannot be modified ), PTR also returns a normal pointer and cannot be modified. But take a closer look at the implementation of _ retn, you will find that this method first saves the pointer content, then clear the pointer to 0 (so that the original address space will not be free when string_var is released), and return the pointer. That is to say, through this method call, the control of the address space pointed to by the string_var object is handed over to the party that calls this method. Similarly, to release an address space, you must call this method. For the out method, in order to ensure the safe release of the original pointer, this method first releases the address space to which the original pointer is directed, clears the pointer 0, and returns the reference of the pointer. Therefore, the called method is responsible for allocating space for the object internally, and the release of the space is done by the caller. The implementation of the above methods of other objects is basically consistent with that of string_var in principle, only when the IDL compiler tao_idl generates the stub and skeleton code, it will apply different class templates for the fixed length struct and the variable length struct respectively to generate different types of _ var classes. For a fixed-length struct, the class template of the application is tao_fixed_var_t, and for a variable-length struct, the class template of the application is tao_var_var_t. The difference between the two is that for a fixed-length struct, The _ retn and out methods are the same as the inout method, and there is no clear process. The following is the relevant code in the tao_fixed_var_t template class: // mapping for fixed size. template <typename T> ace_inline T & tao_fixed_var_t <t >:: out (void) {return * This-> PTR _;} template <typename T> ace_inline ttao_fixed_var_t <t> :: _ retn (void) {return * This-> PTR _;} For more information about the _ var class, refer to % tao_root %/TAO/varout_t.inl, or: http://www.dre.vanderbilt.edu/Doxygen/Current/html/tao/classTAO__Var__Var__T.htmlhttp://www.dre.vanderbilt.edu/Doxygen/Current/html/tao/classTAO__Fixed__Var__T.html
Iii. Typical Problem AnalysisThe above section briefly introduces several basic methods commonly used in CORBA programming. The following briefly analyzes several problems related to memory management.
· Memory release of struct containing variable length membersThe following IDL is used as an example: struct demostruct {string name _;}; for the following code: int main (){//... demostruct_var demo = new demostruct; demo. name _ = CORBA: string_dup ("hello ");//...} because we use the _ var smart pointer class, the space dynamically allocated through new will be released when the demo object is destroyed, but the following code is used :: is the space allocated by string_dup as the member variable name _ leaked? The answer is: no. This is because the string member variable of the struct in the idl file is mapped to tao_string_manager after being compiled by tao_idl. This type is basically the same as that of string_var, only the string_var constructor without any parameters will initialize the pointer PTR _ to 0, while the tao_string_manager constructor without any parameters will initialize PTR _ into an empty string, for details, see % tao_root %/TAO/managed_types. I and % tao_root %/TAO/corba_string.inl. Therefore, when the struct is released, we do not need to worry about the release of the string. The same is true for other struct with variable length.
· _ Mistakes in using VAR classesNote that string_var provides three Constructors (see % tao_root %/TAO/corba_string.h): CORBA: string_var (char * P ): PTR _ (p) {} ace_inlinecorba: string_var (const char * P): PTR _ (CORBA: string_dup (p) {} CORBA: string_var :: string_var (const CORBA: string_var & R) {This-> PTR _ = CORBA: string_dup (R. PTR _);} The first constructor only copies the pointer P and saves it to the internal PTR _. The next two constructors construct the string_var object through deep copy. Although the differences between the two constructor methods are relatively small, they may cause some very hidden problems. The following code has a problem: string_var STR ("hello"); because the above Code uses the first instead of the second constructor to construct STR, in this way, STR obtains control of the static address space "hello" and tries to release the space when the STR is parsed. This is obviously incorrect. To avoid this error, we should always force the second constructor, or actively copy the string content before constructing the stirng_var object, such as string_var str1 (const char *) "Hello"); string_var str2 (CORBA: string_dup ("hello"); unless you know clearly that the first constructor is what you need. For other _ var types, there is no constructor equivalent to the second constructor. We always use the first constructor, that is, the newly constructed _ var object obtains control of the pointer. Similar to the third constructor, If you input a _ var reference, the following constructor is used: Template <typename T> tao_var_base_t <t> :: tao_var_base_t (const tao_var_base_t <t> & P): PTR _ (p. PTR _? New T (* P. PTR _): 0) {} This constructor performs a deep copy of the passed _ var reference.
· Explanation of memory management issues for remote method callsThe principle of allocating/releasing the CORBA memory is simple: Each is responsible for releasing the space allocated by itself. The allocation and release (and update) of the memory at both ends of C/S will not automatically notify the other party. For client code, the space released by the client code also includes the server pointer image created by ORB during unmarshalling, that is, local copy of the server pointer, these spaces may be obtained by calling out/inout parameters or the return values of the interface methods. There should be no problems in understanding this. However, we have not considered the server-side memory management. Take the following code as an example: demostruct * demointf: Foo () {demostruct_var Var = new demostruct ;//... return var. _ retn ();} when the function returns, the client orb creates an image of the memory area indicated by the pointer through unmarshalling, and then accesses the pointer, finally, the client is responsible for the release of the region. However, we have said that the C/s side will not automatically notify the other party to allocate and release the memory. For the server side, because the _ retn method releases the control of the original _ var object on the address space indicated by its PTR _ pointer, the space originally managed by the _ var object seems to be out of control, will this part of memory leak? Similarly, the answer is no. This is because orb is responsible for releasing the space indicated by the pointer after the pointer is passed to the client, the management of In, out, And inout parameters is similar. Let's take a look at the following example based on the discussion of the server memory management method. For the following IDL files: struct demostruct {string name _ ;}; interface demointf {demostruct get () ;}; there are similar implementations: Class demointf :... {PRIVATE: demostruct_var demo _; public: demostruct * Get () {return demo _ ;}}; The above implementation seems to work normally at the beginning, but according to the above discussion, orb releases the address space of the returned value pointer, which causes the demo _ to be unexpectedly released and eventually leads to an error. Therefore, we should change the implementation code to: demostruct * Get () {: Device: deviceid_var dev_id = new: Device: DeviceID; dev_id-> device_name = CORBA :: string_dup (ID _-> device_name); Return dev_id. _ retn ();} the client code is as follows: Device: deviceid_var device_id = This-> device_id ();
Refer:1. Michi Henning, Steve vinoski. Advanced CORBA programming with C ++. Addison-Wesley, 1999.2. Douglas C. Schmidt & Bala natarajan. CORBA tutorial. http://www.cs.wustl.edu /~ Schmidt/pdf/corba4.pdf