Go to the previous, next section.

Using ILU with CORBA 2.0 C++

We do understand the pressing desire for C++ support, and the work going on here, getting the actual CORBA mind-warped mapping implemented, is truly impressive. Imagine a darkened roomful of programmers, twenty or perhaps thirty. Each sits before a trio of screens. On the left screen is a Visual C++ environment; in the middle, Emacs with g++; on the right, the SunPro tools with C++ mode enabled. A communal coffee urn by the door feeds individual IV drips in each programmer's left arm; precious aged Jolt cola trickles into the right arm. At the front of the room, a huge projected screen flashes an endless slide show emphasizing the differences between the underscore, nested-class, and namespace versions of the CORBA mapping (all mutually non-inter-portable); a garish neon sign on the left wall points up the non-inter-portable differences between compilers with exception support and those without; nasty muttered whispers from the programmers convey rumors about the differences between environments without RTTI and those having it. On the right side of the room are two small shrines, with votive candles burning to light the images of Bjarne Stroustrup and Steve Vinoski. Next to the projector screen in front, a pair of Makefile experts sit on stools, valiantly struggling to devise tests and configuration switches for the individual compiler defects detected and announced in a continuous stream by the mapping implementors. Squeezed into the corner are another pair, visiting philosophers from a German university, attempting to devise a coherent metaphysical framework for the seemingly impossible memory management dicta in the mapping spec. Smoke from their pipes mingles with that coming from the candles, drifting up to the low ceiling and almost obscuring the giant mechanized whip at the back of the room, connected directly to an SMTP server. Each incoming query about the expected release date of free ILU C++ support causes the lashes to crack down again, with horrible results...

Did I mention we're looking for more volunteers to help with the work?

[mail sent to the ILU mailing list, 14 February 1997]

Introduction

This chapter describes the use of ILU with C++ in a manner compliant with the CORBA 2.0 C++ language mapping specification. (see http://www.omg.org/corba/corbiiop.htm) The use of ILU's original C++ support is deprecated.

Any function or type which is not part of the CORBA 2.0 specification has the prefix 'ilu'. It should be understood that use of 'ilu' prefixed functionality is not portable to other (non-ILU) CORBA implementations.

Some arguments or return values of functions (e.g. char*) have storage management requirements. Basically this revolves around whether the caller retains or gets ownership of the parameter and is therefore responsible for eventually releasing it, or if ILU takes or retains ownership, where it will be released at ILU's discretion. Any function parameter that becomes owned by ILU is marked with the comment /* ILUowned */ Any return value (or 'out' parameter) that remains under the ownership of ILU is similarly marked. Anything not so marked is not ILU's responsibility.

Note that ILU support for C++ does rely on having argument prototypes, all C++ library functions, and the capabilities of the C++ pre-processor.

Mapping ILU ISL to C++

The CORBA 2.0 C++ chapters 15 though 18 describes the mapping of OMG IDL to C++. For those elements of ISL for which there is a direct counterpart in IDL, the ISL component is mapped just as the IDL component is. Those ISL concepts with no IDL counterpart (marked with a '-' in the table below) have a mapping separately described in a following section.

ISL to IDL Correspondences


     ISL                    IDL
     -------------------------------------
     INTEGER                long
     SHORT INTEGER          short
     LONG INTEGER           -
     CARDINAL               unsigned long
     SHORT CARDINAL         unsigned short
     LONG CARDINAL          -
     BYTE                   octet
     BOOLEAN                boolean
     REAL                   double
     SHORT REAL             float
     LONG REAL              -
     CHARACTER              -
     SHORT CHARACTER        char
     PICKLE                 Any
     ARRAY                  array
     SEQUENCE               sequence
     RECORD                 struct
     UNION                  union
     OPTIONAL               -
     ENUMERATION            enum
     OBJECT                 object
     CString                string
     SEQUENCE OF CHARACTER  -
     EXCEPTION              -, exception
     INTERFACE              module

ISL Specific Mappings

The following table describes the mappings for ISL types that have no IDL counterparts. The C++ column gives the mapping modulo indirection and/or 'const' qualification dictated by parameter directionality (i.e., IN vs OUT vs INOUT vs return values).


     ISL                    C++
     --------------------------------------------------------------
     LONG INTEGER           iluLongInteger
     LONG CARDINAL          iluLongCardinal
     LONG REAL              iluLongReal
     CHARACTER              iluCharacter
     OPTIONAL X             X* for operation parameters;
                            'managed X*' for embedded types.
     SEQUENCE OF CHARACTER  iluCharacter*
     EXCEPTION              ISL exceptions map to a subclass of
                            CORBA::UserException with a _value() 
                            member function which returns a value of 
                            the type associated with the exception.
                            Exceptions defined in IDL and
                            processed by the ILU idl translator 
                            have the standard CORBA mapping.

Correspondence between C++ Types and Kernel Types

To provide a consistent naming scheme, in many cases, a type defined in the ILU kernel has been typedeffed to appear in C++ as the corresponding type name without the intervening underscore, and with the following letter capitalized, e.g. typedef ilu_cardinal iluCardinal;

C++ Classes Produced for an Object

The mapping for an ISL Object 'A' produces 3 C++ classes:

  1. The A C++ class, which has pure virtual member function declarations for each of A's methods. For each ISL Object supertype Si of ISL Object A, the C++ class A 'public virtual' inherits from the Si C++ class. If the ISL Object A has no supertypes, the A class 'public virtual' inherits from the iluObject class. [NOTE that an object described in IDL will implicity inherit from CORBA::Object (which in turn inherits from iluObject). The ILU idl translator automatically adds ilu.CORBA-Object as a SUPERTYPE.] This basically creates a C++ class hierarchy that is isomorphic to the ISL object type hierarchy, with each method being declared pure virtual. We refer to this hierarchy as the 'abstract object hierarchy'.

  2. The A_surrogate C++ class, which has virtual member function declarations for each of ISL Object A's non inherited methods. These member functions transfer requests to the true object. For each ISL Object supertype Si of ISL Object A, the C++ class A_surrogate 'public virtual' inherits from the Si_surrogate C++ class, and then 'public virtual' inherits from the C++ class A. (If the ISL Object A has no supertypes, the A_surrogate class 'public virtual' inherits only from the C++ class A.) This basically creates a C++ 'surrogate object hierarchy' that is isomorphic to the abstract object type hierarchy, with the addition that each X_surrogate class also inherits from its counterpart in the 'abstract object hierarchy'.

  3. An A_var C++ class as prescribed by the CORBA C++ mapping.

This mapping allows servers to be developed that do not contain surrogate stub code (if they don't need it), and also prevents the situation where a server method override is forgotten, resulting in surrogate stub code being called as it it were 'true' code.

For each ISL Object 'A' for which a true side implementation is to be developed, the true side implementer should define a class A_impl that inherits virtually from the C++ class A, and implements the actual true methods as member functions (in whatever manner is appropriate). The implementer is free to use delegation, implementation inheritance, whatever - the only restriction is that if a class B_impl inherits implementation from a class X, and class X inherits from a class in the abstract object hierarchy, (e.g. when X is A_impl), then X's inheritance from the abstract object hierarchy must be 'public virtual'.

Each produced C++ class e.g. A, will have a constructor C++: constructor A ( char* pc_instance_handle, ilu_Server& r_an_ilu_server = iluServer::GetDefaultServer(), ILUCPP_BOOL b_within_object_table = ILUCPP_FALSE ) : iluObject ( A::m_ILUClassRecord, pc_instance_handle, r_an_ilu_server, b_within_object_table).

Misc. Mapping Details

Unions

In IDL, Union arms all have names, in ISL, the names may not be specified. If a name isn't specified for an arm, the name the stubber produces is the arm's typename, prefixed with '_', and suffixed with '_arm'.

For example,

TYPE someuniontype = short cardinal UNION	
        bar = 0, 1 END,   
        integer = DEFAULT	
END;

would produce the C++ names _bar_arm, and _integer_arm to reference the bar and integer arms.

Optionals

For procedure parameters, an ISL OPTIONAL type maps either to the same C++ type as its base type, if that base type is represented with an C++ pointer type, or to a pointer to that base type, if it is not represented with a C++ pointer type.

Additionally, all OPTIONAL types T have an associated C++ T_var.

For non-parameters (i.e., RECORD members, ARRAY and SEQUENCE elements) an ISL OPTIONAL type maps to a 'managed pointer', analagous to the mapping for non-parameter ISL OBJECT (CORBA interface) and ISL SEQUENCE OF SHORT CHARACTER (CORBA string). (This 'managed pointer' behaves similarly to T_var; however, CORBA does not allow compliant applications to use 'managed pointer' types directly, as the actual type is implementation-specific)

The following ISL and C++ code fragments illustrate:


     ISL

	TYPE SomeType   = ...
	TYPE MyOptional = OPTIONAL SomeType;

	TYPE MyRec = RECORD
	     member: MyOptional
	END;

	TYPE MyArray = ARRAY OF 10 MyOptional;


     C++

	 ...

     MyRec          myRec;
	 MyArray        myArray;
	 SomeType       st;
	 SomeType*      stPtr;
	 MyOptional     myOptional;  // MyOptional is equivalent to SomeType*
	 MyOptional_var stVar;

	 ...

	 myRec.member = myArray[0];        // free old myRec.member, deep copy
	 myArray[1]   = stVar;             // free old myArray[1], deep copy
	 myRec.member = stPtr;             // free old myRec.member, assume ownership
	 myRec.member = myOptional;        // free old myRec.member, assume ownership

	 myRec.member = &st;               // ILLEGAL - can't free &st
	 myRec.member = new SomeType(st);  // OK; free old myRec.member, assume ownership

	 stPtr = myArray[2];               // Simple pointer assignment, no copy
	 stVar = myRec.member;             // free old stVar, deep copy

The lifetime of recA.member and each myArray[n] are tied to recA and myArray, respectively; when an optional-containing variable goes out of scope or is destroyed, its optional members/elements are freed. Thus, the assignment myRec.member = &st in the example above is illegal and can lead to calamitous results when an attempt is made to free &st.

Overloading problems for T_vars.

Some compilers diagnose overloading errors for client and server code using T_vars as method arguments, even if no such errors are present. The ILU C++ mappings for structured types (unions, records, and sequences) provide a means of bypassing this problem if it occurs, using the form T_var->self(). This usage should be avoided unless absolutely necessary, as continued support is not guaranteed.

Similar problems for T_vars representing arrays can usually be avoided by references to the address of the first member of the array. For example, if A is an array, and references to A_var give overloading problems, replacing those references with ones to &A_var[0] usually solves the problems. If it does not, the methods A_var.in() and A_var.out(), returning, respectively, const A_var_slice* and A_var_slice* can also be used.

Exceptions

An exception defined directly in ISL maps to a subclass of CORBA::UserException, that has a _value() member function which returns a value of the type associated with the exception.

ISL Asynchronous Methods

In IDL, methods may be ASYCHRONOUS. Asynchronous methods cannot have return values or raise exceptions. Hence, they result in a C++ member function declared to return void.

ISL Functional Methods

In IDL, methods may be FUNCTIONAL. In the C++ mapping, FUNCTIONAL is ignored. The ability to create custom C++ surrogates allows the implementation to decide what and how caching may be implemented on any method, as well as perform any other sorts of message 'filtering'.

ISL Collectible Objects

An ISL object being declared COLLECTIBLE has no effect on the mapping per-se. It will however cause ILU to adjust an object's reference count based on interest or dis-interest from clients.

Inheritance from CORBA::Object

If an ISL Object A has no supertypes, the A class 'public virtual' inherits from the iluObject class. An object described in IDL will implicity inherit from CORBA::Object (which in turn inherits from iluObject). (The ILU idl translator automatically adds ilu.CORBA-Object as a SUPERTYPE.) So, if you define an object in ISL, and do not explicitly declare ilu.CORBA-Object as a SUPERTYPE, you will not have the member functions of CORBA::Object available since you do not inherit from it.

Portability and Mapping Variations

The CORBA 2.0 C++ mapping allows for variations in the mapping depending on the C++ compilers support for Name Spaces, Exception Handling, and Run-Time Type information.

The ILU CORBA 2.0 C++ mapping implementation assumes that the C++ compiler supports exceptions. We also assume that the compiler supports RTTI should someone want to do narrowing within the exception hierarchy. [Given that ILU does not provide a Dynamic Invocation Interface, there's no real need to narrow exceptions anyway.]

During the configuration phase of ILU installation (or for Windows, per the definitions in `ILUSRC/runtime/kernel/iluwin.h') a determination is made as to whether or not to use namespaces, nested classes or underscores for IDL modules, based on the C++ compiler in use. This can also be explicitly set using the configuration option --with-cplusplus-mapping= switch to config, or on Windows, by manually editing `ILUSRC/runtime/kernel/iluwin.h' before building ILU.] This results in a C++ runtime and C++ stubber that is constructed with one the selected approaches in mind.

Based on our knowledge (as of the date of this writing), of the degree of support/bugs for namespaces and nested classes, the following describes the IDL module mapping based on compiler:

C++ Compiler Module Mapping


     Compiler                 Mapping
     ---------------------------------------
     Microsoft Visual C++     underscores
     SunPro                   nested classes
     Gnu                      nested classes

Because of possible variations in compiler support for Booleans, CORBA(Boolean) is defined as ILUCPP_BOOL, where ILUCPP_BOOL is defined as either an int (with ILUCPP_TRUE and ILUCPP_FALSE #defined as 1 and 0), or as a bool (with ILUCPP_TRUE and ILUCPP_FALSE #defined as true and false).

Concepts

Servers and Ports

In ILU there is a concept of an 'server object'. In the kernel this is the ilu_Server, which in the C++ runtime is encapsulated asn an iluServer object. This 'server' effectively forms a 'scope' in which true objects reside. This is why for example, and object lookup requires both the 'server' ID, and the object's instance handle - both are needed to uniquely denote an object.

Now a server has some number of 'ports'. A port is basically a means of communicating with the objects inside a server, using a particular combination of protocol and transport. For example, when create an iluServer, the constructor for iluServer automatically adds a port for the communication protocol and transport specified as constructor arguments. We can call iluServer::iluAddPort to have additional ports added. For example we may want to be able to communicate with the objects using sunrpc over tcp/ip, as well as http over tcp/ip. The iluServer has a notion of a default port. This is initially one as specified during construction, but this can be changed if when calling iluServer::iluAddPort we specify that this should become the default port. The default port is the one used when we ask for contact information for an object - that is, if we get the string binding handle for an object, the contact information in that string will reflect the default server port.

Object Tables

True objects may either be created ahead of time, or on an 'as needed' basis, i.e. when a call comes in involving them. The 'as needed' situation is made possible by 'object tables'. An iluServer may have associated with it (at construction time) an iluObjectTable object. When a call comes involving an object in that iluServer that the ILU doesn't already know about, the iluObjectTable object's iluObjectOfInstanceHandle gets called. It is the job of this function to create and return a new object with that instance handle. How it does this is specific to your application - it may read object state off a disk for example. In any event, one thing this function must do is ensure that when it calls the true objects constructor, that it sets the constructor's b_within_object_table argument to true. (Otherwise, internal locking constraints will be violated). While in the iluObjectOfInstanceHandle function, the associated iluServer's lock is held, and if the resulting object is expected to be of a COLLECTIBLE type, the global kernel mutex "gcmu" is also held. The fact that these locks are held somewhat restricts what an application can do inside this mapping procedure.

Threading

The ILU C++ support may be initialized to run in either threaded or non-threaded mode. In non threaded mode, a call to iluServer::iluRun member function results in a call to ILU's 'mainloop'. The mainloop basically sits waiting for an incoming request. When one comes in, the request is invoked. If the implementation of the invoked method makes a call to some other remote object, the mainloop is recursively entered while awaiting a reply. This allows additional requeste to come in and get serviced, preventing deadlock.

When intialized to run in threaded mode, ILU will run one thread for each incoming connection. Note that there may be multiple connections for a particular port (either from different clients, or from the same client who needed another connection because all the ones it had so far were busy at the time). In the case of a non-concurrent protocol (sunrpc, http, courier), the connection thread receives an incoming request, processes it itself, and then waits for the next request. In the case of a concurrent protocol (csunrpc, iiop), the connnection thread receives an incoming request, spawns a worker thread to carry out the request, and immediately goes back to waiting for more incoming requests.

The ILU C++ provides no special concurrency control for methods in your objects (to do so would be presumptive on our part). The method implementor must put appropriate locking in place if it is possible that multiple threads (or recursive mainloop invocations) might be running 'in' an object simultaneously.

Custom Surrogates

A surrogate is an object that is used to represent a remote object. When a method is invoked on a surrogate, the methods implementation in the surrogate transfers the call to the true object, and returns the result of this call, thus providing location transparency. There are times however when it is useful to have the surrogate's method implementation do more than just forward the call to the true object. An application may want a surrogate method implementation that caches the results of calls (potentially reducing network overhead), perform transformations on arguments, output diagnostic information, or whatever.

To facilitate this, the ILU C++ support allows an implementation to supply a function that is called when a surrogate for a particular object type is needed. The function iluCppRuntime::iluSetSurrogateCreator tells the C++ runtime what function to call when a surrogate for an object of the specified class is needed. This allows an implementation to subclass off a surrogate class, and write a new surrogate creation function that creates an instance of this new subclass. Call iluCppRuntime::iluSetSurrogateCreator after you've performed initialization, but before you do any operations which might create a surrogate of the specified class. It basically overwrites the default surrogate creation function set up by the surrogate stubs. It returns the old surrogate creator function, or NULL if was previously no surrogate creator for that class.

A surrogate creator function should at the minimum create an instance of a surrogate, call the instances member function iluAssociateKernelObject passing the iluKernelObject, and then return a pointer to the new instance.

String Binding Handle Manipulation

A String Binding Handle is a textual representation of an object reference. It contains the object's server id, instance id, information about how to contact the object, as well as other information. ILU C++ provides the functions iluCppRuntime::iluFormSBH, iluCppRuntime::iluFormSBHUsingContactInfo, and iluCppRuntime::iluParseSBH for constructing and parsing string binding handles. An object may be obtained from a string binding handle using iluObject::iluStringToObject and the string bindign handle of an object may be obtained by calling the iluObjectToString member function.

Simple Binding

When creating a service, there needs to be some way for clients to find out about the service. ILU C++ provides a simple mechanism to achieve this. Objects may be published, looked up, and their publications withdrawn using the appropriate member functions (iluPublish, iluLookup, iluWithdraw).

Object Activation

An true object is initially 'Active', which means that its ISL (or IDL as the case may be) defined methods may be invoked on it from outside its process (or from another language within that same process). An object may be made unavailable to outside calls, i.e. marked 'inactive' by calling its iluDeactivate member function. It may may be reactivated by calling its iluActivate member function.

An object is initially available from the outside until it is deactivated Objects that are involved in a call (i.e. sent or received as arguments, or the object the method is being invoked on) need to be protected from deletion for the duration of that involvement (for example, you don't want some thread deleting a true object when it's currently the target of a method call). The C++ runtime keeps track of what objects are involved in a call, and will attempt to prevent them from being deleted until the call is completed.

The application programmer needs to assist in this by calling, in the most specific destructor, iluDeactivate (inherited virtually from iluObject). iluDeactivate blocks any further incoming calls involving the object, and wait for any ongoing calls using the object to complete. Next the destructor should perform any object specific cleanup. Finally, the destructor in iluObject will break the association between the kernel object and this object, allowing the kernel object to be potentially freed.

Security

A client may set the Passport to be used on outgoing calls by creating and setting up an iluPassport, and then passing the passport in a call to iluPassport::iluSetPassport. This sets the passport to be used in the thread that made the call - i.e. iluPassport are on a per thread basis. Note that before your thread exits, you should either call iluSetPassport(NULL), or delete the iluPassport in use (assuming it's only in use for a single thread). The iluPassport (if any) currently setup for a thread can be retrieved by calling iluPassport::iluGetPassport.

A Server may obtain the iluPassport of the caller (if any) of a method by using the iluPassport::iluGetCallerPassport() function.

A iluServer may be constructed to use a particular identity by specifying a iluPassport as a constructor argument. This identity is used to identify the principal offering the service.

Static Initialization

The C++ Runtime normally relies on the static initializers in the files that the stubber generates to place initialization functions onto internal lists so that they will be invoked when the application calls iluCppRuntime::Initialize. However, it is not guaranteed by the ANSI C++ that static initializers are called upon the loading of a compilation unit. We have only had a report of one compiler that did not run the static initializers at load time (in fact, it was reported that it did not run them ever! - bug!?). We have observed static initialization at load time in Visual C++, SunPro and GNU compilers. In the event that you end up using a compiler that does not call the static initializers at load time, you can use the stubber defined initialization macros that are generated in the common header file for each interface.

(It should be pointed out that the CORBA 2.0 C++ Runtime does not suffer from the static initializer issues that plagued ILU's original C++ support. No ILU calls are actually made until iluCppRuntime::iluInitialize is called, allowing one to set up different mainloops, etc.)

Building an Application

Running the Stubber

To generate CORBA 2.0 C++ stubs from an ISL file, use the program cpp2-stubber. The stubber has the following usage:


     Usage: cpp2-stubber Islfile [ISLFILE ...]

The stubber produces code using whatever the mapping (underscores, nexted classes, or namespaces) that was found appropriate during the configuration phase of ILU installation (see "Portability and Mapping Variations").

Stubber Generated Files

For an interface Foo the stubber generates:

`Foo-cpp.hpp' which contains the classes for the abstract object hierarchy, as well as any other declarations needed by both client and server.

`Foo-cpp.cpp', which contains any definitions needed by both client and server

`Foo-cppsurrogate.hpp' which contains the classes for the surrogate object hierarchy, as well as any other declarations needed just by a client. This file #includes Foo-cpp.hpp

`Foo-cppsurrogate.cpp', which contains any definitions needed just by a client. This file #includes Foo-cppsurrogate.hpp

`Foo-cpptrue.hpp' which contains any declarations needed just by a server. This file #includes Foo-cpp.hpp

`Foo-cpptrue.cpp', which contains any definitions needed just by a server. This file #includes Foo-cpptrue.hpp. All header files use the usual #ifdef method to prevent multiple inclusions.

A client only will #include Foo-cppsurrogate.hpp, and link with `Foo-cpp.o' and `Foo-cppsurrogate.o'

A server only will #include Foo-cpptrue.hpp, and link with `Foo-cpp.o' and `Foo-cpptrue.o'

A client and server will #include Foo-cpptrue.hpp, #include Foo-cppsurrogate.hpp, and and link with `Foo.o', `Foo-cpptrue.o', and `Foo-cppsurrogate.o'

Server Basics

The basic steps in creating a simple server application are as follows (assuming we have a ISL file called `foo.isl', describing an interface 'foo' with an object type 'bar'):

  1. Run the C++ stubber on `foo.isl', e.g. cpp2-stubber foo.isl

  2. In your implementation file, e.g. `servermain.cpp', include the true side header file, e.g. #include "foo-cpptrue.hpp".

  3. Define an implementation class that inherits public virtual from foo::bar. e.g.
    	class foo_bar_impl : public virtual foo(bar) { ... };
    

  4. In the implementation class, provide a constructor that receives an instance handle and an iluServer as arguments, and calls the iluObject constructor appropriately, e.g.

    	foo_bar_impl::foo_bar_impl(char* pc_instance_handle, iluServer& r_an_ilu_server) : 
    		iluObject(iluGetILUClassRecord(), pc_instance_handle, r_an_ilu_server) {}
    

  5. In the implementation class declaration, declare a virtual destructor. e.g. virtual foo_bar_impl::~foo_bar_impl();

  6. Define the virtual destructor of the implementation class that (at the minimum) makes a call to iluDeactivate as the first thing it does, e.g.

    	  foo_bar_impl::~foo_bar_impl() {
    		  iluDeactivate();
    		  // other app specific things that may need to be done
    	  }
    

  7. In the implementation class declaration, declare the virtual member functions that will implement the method(s), e.g.

    	virtual CORBA(Boolean) zap( CORBA(Long)  inarg, CORBA(Octet)&  inoutarg, CORBA(Double)& outarg ) 
    		throw (CORBA(SystemException), foo(zapexception));
    
  8. Define the virtual member functions that implement the method(s), e.g.

    	CORBA(Boolean) foo_bar_impl::zap( CORBA(Long)  inarg,
    		  CORBA(Octet)&  inoutarg,
    		  CORBA(Double)& outarg ) 
    		  throw (CORBA(SystemException), foo(zapexception)) {
    		  // do whatever must be done
    		  }
    

  9. In for example 'main()', Call the runtime initialization function, passing an argument specifying whether or not to set up for threaded operation, e.g.

    		// Set up the runtime for threaded operation
    		iluCppRuntime::iluInitialize(ILUCPP_TRUE);
    

  10. Create an iluServer. e.g.

    	iluServer server ("MyFooBarServerOnMyHost");
    

  11. Create a true object in that server, e.g.

    	p_true_foo_bar = new foo_bar_impl("foo_bar_instance_0", server);		
    

  12. Publish the true foo::bar object, e.g.

    	p_true_foo_bar->iluPublish() 
    

  13. Run the server, e.g.

     	server.iluRun();
    

  14. Compile your server application code, `foo-cpp.cpp' and `foo-cpptrue.cpp', and link the resulting object files with the C++ runtime library (`libilu-cpp2.a' on UNIX, and `ilucpp2.lib' on Win32) and the ILU kernel library (`lib.a' on UNIX, and `ilu32.lib' on Win32).

Client Basics

The basic steps in creating a simple client application are as follows (assuming we have a ISL file called `foo.isl', describing an interface 'foo' with an object type 'bar'):

  1. Run the C++ stubber on foo.isl, e.g. cpp2-stubber foo.isl

  2. In your implementation file, e.g. `clientmain.cpp', include the surrogate side header file, e.g. #include "foo-cppsurrogate.hpp".

  3. In for example 'main()', call the runtime initialization function, passing an argument specifying whether or not to set up for threaded operation, e.g.

    	// Set up the runtime for threaded operation
    	iluCppRuntime::iluInitialize(ILUCPP_TRUE);
    

  4. Lookup an object, e.g.

    
    	foo(bar_var) mybar_var = foo(bar)::iluLookup ("foo_bar_instance_0", "MyFooBarServerOnMyHost");
    
    

  5. Invoke a method, e.g.

    	try { 
    		bool_return_value = mybar_var->zap(inarg, inoutarg, outarg);
    	}
    	catch (const foo(zapexception)& the_exception) { 
    		/* do whatever */ 
    	}
    	catch (const CORBA(SystemException)& the_exception) { 
    		/* do whatever */ 
    	}
    	catch (...) { 
    		/* do whatever */ 
    	}
    	
    

  6. Compile your client application code, `foo-cpp.cpp' and `foo-cppsurrogate.cpp', and link the resulting object files with the C++ runtime library (`libilu-cpp2.a' on UNIX, and `ilucpp2.lib' on Win32) and the ILU kernel library (`lib.a' on UNIX, and `ilu32.lib' on Win32).

Relevant examples

The ILU examples directory contains two examples that use the CORBA 2.0 C++ mapping. See cpp2foo, and test1. The cpp2foo example illustrates a lot: object tables; collectible; custom surrogates; lookups; anys; return, in, inout, and out of most types; use of _vars; and more;

Runtime Classes

Overview

The classes of interest to the application programmer are listed below. Nearly all non-static member functions are virtual to allow creative overrides (at your own risk of course).

iluCppRuntime - Abstract class that provides various static member functions that the application can use to control the runtime's behavior.

iluServer - Provides the C++ view of a kernel server object.

iluObject - The most base class for all ILU C++ objects. All objects inherit either directly or indirectly from this class.

iluObjectTable - An abstract C++ class for developers to derive from to provide Object Tables.

iluPassport - encapsulates ilu_Passport functionality

iluGSS - encapsulates GSS functionality

iluMainLoop - An abstract base class for developers to derive from to create their own main loop.

iluWString_var Class - analog to CORBA(String_var) only for ILU Characters

(See `ILUSRC/runtime/cpp2/ilu.hpp' and `ILUSRC/runtime/cpp2/corba.hpp' for more complete descriptions.)

iluCppRuntime

An Abstract class that provides various static member functions that the application can use to control the runtime's behavior. iluCppRuntime is not meant to ever be subclassed.

iluCppRuntime - Initialization Related

C++: static void iluCppRuntime::iluInitialize ( ILUCPP_BOOL b_use_native_threads = ILUCPP_FALSE )

Initializes the C++ runtime for use. Also calls all the functions (typically interface initialization functions in generated stubs) that are on the C++ Runtime's initialization function list (see iluCppRuntime::iluAddInitializationFunction).

iluCppRuntime::iluInitialize's use depends on your use of threading:

  1. No threading at all - just call iluCppRuntime::iluInitialize().

  2. Using ILU's native operating system (OS) thread support - call iluCppRuntime::iluInitialize(ILUCPP_TRUE).

  3. Your own thread package - call iluCppRuntime::iluSetForkProcedure, iluCppRuntime::iluSetNonNativeThreadIDFunction then call the ILU kernel functions ilu_SetWaitTech, and ilu_SetLockTech appropriately, call iluMainLoop::iluSetMainLoop, then call iluCppRuntime::iluInitialize().

C++: static void iluCppRuntime::iluAddInitializationFunction ( iluPFunctionInitializer pf_initialize )

Adds an initialization function onto the runtime's list of (typically interface initialization) functions to call when iluCppRuntime::iluInitialize is called. iluPFunctionInitializer is typedeffed as

C++: void (* iluPFunctionInitializer ) ( )

C++: static void iluCppRuntime::iluSetNonNativeThreadIDFunction ( iluNonNativeThreadIDFunction p_thread_id_function )

When running non-native threaded, this should be called (before initialization) set to the function that will return a thread unique iluCardinal id of the current thread. iluNonNativeThreadIDFunction is typedeffed as

C++: iluCardinal (* iluNonNativeThreadIDFunction )( )

C++: static iluPFunctionSurrogateCreator iluCppRuntime::iluSetSurrogateCreator ( iluClass surrogate_class, iluPFunctionSurrogateCreator pfunction_surrogate_creator )

Tells the C++ runtime what function to call when a surrogate for an object of the specified class is needed. This allows an implementation to subclass off a surrogate class, and write a new surrogate creation function that creates an instance of this new subclass. This more specialized surrogate might do message filtering, caching, monitoring, etc. Call this function after you've performed initialization, but before you do any operations which might create a surrogate of the specified class. It basically overwrites the default surrogate creation function set up by the surrogate stubs. It returns the old surrogate creator function, or NULL if was previously no surrogate creator for that class (note: NULL return should not really happen unless a mistake or something clever is being done - this means you've added a new node to the surrogate creator function list). iluPFunctionSurrogateCreator is typedeffed as

C++: iluObject* (* iluPFunctionSurrogateCreator ) ( iluKernelObject).

A surrogate creator function should at the minimum create an instance of a surrogate, call the instances member function iluAssociateKernelObject passing the iluKernelObject, and then return a pointer to the new instance.

C++: static void iluCppRuntime::iluSetForkProcedure ( iluForkProc pfunction_fork_procedure )

If your using your own threads package call this before calling the ILU kernel functions ilu_SetWaitTech, etc. and pass a pointer to your function that forks a thread. iluForkProc is typedeffed as

C++: iluBoolean (* iluForkProc ) ( void (*pfunction_procedure) (void* pv_argument), void* pv_argument, ILU_ERRS((no_memory, no_resources, internal)) * p_error )

iluCppRuntime - Character Utilities

C++: static iluCardinal iluCppRuntime::iluCharacterStringLength ( const iluCharacter* p_chars )

Returns the length of the iluCharacter string

C++: static iluCharacter* iluCppRuntime::iluCharacterStringCopy ( iluCharacter* p_chars_destination, const iluCharacter* p_chars_source )

Copies the source iluCharacter string to the destination, returns the destination.

C++: static iluCharacter* iluCppRuntime::iluCharacterStringDuplicate ( const iluCharacter* p_chars_source )

Returns a duplicate of the source iluCharacter string

C++: static ILUCPP_BOOL iluCppRuntime::iluCharacterStringEqual ( const iluCharacter* p_chars_one, const iluCharacter* p_chars_two )

Returns true if strings are the same, else false.

C++: static iluCharacter* iluCppRuntime::iluCharStringFromShortCharString ( const iluShortCharacter* pc_shortchars )

Returns a new iluCharacter string filled in from the iluShortCharacter string.

C++: static ILUCPP_BOOL iluCppRuntime::iluCharStringShortCharStringEqual ( const iluCharacter* pc_chars, const iluShortCharacter* pc_shortchars )

Returns true if the iluCharacter string matches the iluShortCharacter string.

iluCppRuntime - String Binding Handle Utilities

C++: static char* iluCppRuntime::iluFormSBH ( const char* pc_serverid, const char* pc_instance_handle, iluClass the_ilu_class, iluProtocolInfo pc_protocol_type = ((iluProtocolInfo) NULL), iluTransportInfo transport_info = ((iluTransportInfo) NULL) )

C++: static char* iluCppRuntime::iluFormSBHUsingContactInfo ( const char* pc_serverid, const char* pc_instance_handle, iluClass the_ilu_class, const char* p_str_encodedContactInfo = NULL )

Use these to form a string binding handle from relevant parts, if protocol and/or transport info are NULL, current defaults are used. For iluFormSBHUsingContactInfo, p_str_encodedContactInfo is as would be obtained from iluParseSBH.

C++: static ILUCPP_BOOL iluCppRuntime::iluParseSBH ( iluCString str_encodedSBH, iluCString* p_str_plainInstanceHandle = NULL, iluCString* p_str_plainServerID = NULL, iluCString* p_str_plainMstid = NULL, iluCString* p_str_encodedContactInfo = NULL, iluCardinal* p_card_encodedContactInfoLen = NULL, ILUCPP_BOOL* p_b_malloced_contact_info = NULL) )

Parse a string binding handle, returning whichever elements are specified by passing in non-NIL pointers. Caller retains ownership of URL argument. If p_str_plainInstanceHandle != NIL, ownership of *p_str_plainInstanceHandle is passed to caller iff successful. Similarly for p_str_plainServerID and p_str_plainMstid. *p_str_encodedContactInfo is set to point into the given URL (The whole sequence of contact info is returned in *p_str_encodedContactInfo) , and *p_card_encodedContactInfoLen is set to the length of the contact info substring; the next character is left unmolested. If the p_b_malloced_contact_info out parameter is true, then caller must arrange to free it.

iluCppRuntime - File Descriptor Budget

C++: static iluCardinal iluCppRuntime::iluGetFDBudget ( )

C++: static iluCardinal iluCppRuntime::iluSetFDBudget ( iluCardinal card_size )

Get and set ILU file descriptor budget. iluSetFDBudget returns the new budget. Because ILU may open multiple connections to a server, we need some policy for when to close them. That policy is this: the application gives the ILU kernel a "File Descriptor Budget" (initally 16). The ILU kernel promises to use no more than this many File Descriptors at once.Off the top of this budget we take FDs needed for serving (one per listening socket and one per accept). The remainder is allocated to outgoing connections (over transports that use FDs -- ie, not inmemory). When we want to consume a new FD, and there's no room left in the budget, we go looking for an idle outgoing connection (one with no outstanding calls) to close. All idle outgoing connections are kept in a doubly-linked list, ordered by when the connection went idle (most recently at the front).

iluCppRuntime - Memory Management

C++: static void iluCppRuntime::iluFree ( void* pv /* ILUowned */ )

Use this to free things returned by ILU

C++: static void* iluCppRuntime::iluMalloc ( iluCardinal card_size )

You can use this to malloc things from ILU.

iluServer

iluServer provides a the C++ view of a kernel server object. iluServers cannot be copied or assigned.

iluServer - Setup and Destruction

C++: constructor iluServer::iluServer ( char* pc_server_id = NULL, iluObjectTable* p_object_table = NULL /* ILUowned */ , char * pc_protocol_type = NULL, iluTransportInfo transport_info = NULL, iluPassport* p_passport = NULL, ILUCPP_BOOL b_addport = ILUCPP_TRUE)

Constructor - If no pc_server_id is specified, one is automatically created based on based on time, hostname, and process id. If p_object_table is NULL, a default object table implementation is used. If b_addport is ILUCPP_TRUE, a port is created and added to the server using the specified protocol and transport, and becomes the default port of the server. pc_protocol_type and transport_info default to whatever the default protocol and transport are currently set to. Caller owns pc_server_id p_object_table, pc_protocol_type, transport_info, and p_passport. p_passport points to an iluPassport, defaulted to NULL - this passport containing an ILU GSS identity, which is used as the identity of the principal offering the service, and put into the connection information in the string binding handle of objects on that server.

C++: virtual iluServer::~iluServer ( )

Destructor - basically destroys the kernel server and breaks all associations between kernel objects in this server and their language specific objects. Indirectly also deletes any iluObjectTable used with this iluServer.

C++: virtual void iluServer::iluAddPort (char* pc_protocol_type, iluTransportInfo transport_info, ILUCPP_BOOL b_become_default_port = ILUCPP_FALSE, iluPassport* p_passport = NULL, ILUCPP_BOOL b_public = ILUCPP_TRUE )

Adds another port to an existing server If b_become_default_port is ILUCPP_TRUE the new port will become the default port for this server. p_passport points to an iluPassport, defaulted to NULL. this passport containing an ILU GSS identity, which is used as the identity of the principal offering the service, and put into the connection information in the string binding handle of objects on that server. If b_public is ILUCPP_TRUE, the cinfo of the port will be included in string binding handles for objects of this server; if ILUCPP_FALSE, the cinfo will not be included. Caller owns the arguments.

C++: virtual void iluServer::iluRun ( int* p_i_stop_on_non_zero = NULL )

This runs the main, outer loop of an iluServer. It never returns if p_i_stop_on_non_zero isn't supplied, else it returns when *p_i_stop_on_non_zero is non zero. If you're running threaded this routine simply goes into a sleep loop,

iluServer - Controlling Cinfo

The Cinfo of a server is the information about protocols and transports that are added to the string binding handle of an object. This can be controlled with the b_public parameter to iluAddPort, and also with the two methods iluGetCInfo and iluAddCInfo. This can be used to implement a scheme in which a dummy server process exports a server, but relocates connection requests to that server to another server process. The first server (call it the manager) creates a server with a relocate procedure (this server must be written in C or Python; the CORBA C++ runtime does not yet support relocate procedures). When it receives a connection request, it starts the real server (call it the worker), or finds an already started one. The worker creates a server with the same server id as that started by the manager, but with no ports. It calls iluAddCInfo using the manager's cinfo, so that objects exported by the worker will have the same cinfo as the manager. The worker then adds a private port, and calls iluGetCInfo to find the cinfo of this port. It sends the cinfo back to the manager, which in turn sends it back to the client, which re-connects to the worker. Any objects the worker creates and sends back to the client will have the manager's cinfo, so any re-connects later will go through the same dance.

C++: virtual ILUCPP_BOOL iluServer::iluGetCInfo ( {iluProtocolInfo *} pp_pinfo, {iluTransportInfo *} pp_tinfo, ILUCPP_BOOL b_public = ILUCPP_FALSE)

iluGetCInfo returns the native cinfo of one of the server's ports. If b_public is ILUCPP_TRUE, it will return the cinfo of the first public port; otherwise it will return the cinfo of the first private port. It returns ILUCPP_TRUE if a port of the specified type was found, ILUCPP_FALSE if not. The caller owns the returned pinfo and tinfo, and is responsible for freeing them.

C++: virtual void iluServer::iluAddCInfo ( {const iluProtocolInfo} p_pinfo, {const iluTransportInfo} p_tinfo )

iluAddCInfo adds the specified pinfo and tinfo to the cinfo which will be used for any string binding handles of objects exported through this server. The caller retains ownership of the arguments.

iluServer - Default Accessors

C++: static char* iluServer::iluGetDefaultProtocol ( )

C++: static void iluServer::iluSetDefaultProtocol ( char* pc_new_default_protocol )

Get and set the default protocol used when adding a port on a iluServer - initialized to whatever is set to be the default in the kernel (found in `ILUSRC/runtime/kernel/iluconf.h' or `ILUSRC/runtime/kernel/iluwin.h') C++: static const iluTransportInfo iluServer::iluGetDefaultTransport ( )

C++: static void iluServer::iluSetDefaultTransport ( iluTransportInfo ppc_new_default_transport_info )

Get and set the default transports used when adding a port on a iluServer - initialized to whatever is set to be the default in the kernel (found in `ILUSRC/runtime/kernel/iluconf.h' or `ILUSRC/runtime/kernel/iluwin.h') Callee owns pc_new_default_transport_info.

C++: {static iluServer@ampnr{}} iluServer::iluGetDefaultServer ( )

Returns the default iluServer, creating one if need be.

C++: static iluServer* iluServer::iluSetDefaultServer ( iluServer& new_default_server )

Sets the default iluServer, returns old default, which is NULL if no default currently is set.

iluObject

The most base class for all ILU C++ objects. All objects inherit either directly or indirectly from iluObject. All non-static member functions are virtual to allow creative overrides (at your own risk of course). iluObjects cannot be copied or assigned.

iluObject - Creation and Destruction

C++: constructor iluObject::iluObject ( iluClass the_Class, char* pc_instance_handle = NULL, iluServer& the_server = iluServer::iluGetDefaultServer(), ILUCPP_BOOL b_within_object_table = ILUCPP_FALSE )

Constructor - This constructor must be called (only) from the constructors for true objects. For example, in an implementation of a foo::bar :

 foo_bar_impl(char* pc_instance_handle, iluServer& r_an_ilu_server, CORBA(Boolean) b_within_object_table = ILUCPP_FALSE :
          iluObject(iluGetILUClassRecord(), pc_instance_handle, r_an_ilu_server, b_within_object_table) {}	

If no instance handle is specified, then the value of a monotonicaly increasing, iluServer specific counter will be used to generate one. If no server is specified, then the default server will be used. (The default server is generated automatically if needed, and has the an id based on time, hostname, and process id.) Caller owns pc_instance_handle. The new object has a reference count of 1. If b_within_object_table is true, then it is assumed the object is being created inside an iluObjectTable's iluObjectOfInstanceHandle function, meaning that the locks on the server should not be modified.

C++: static iluObject* iluObject::iluStringToObject ( char* pc_string_binding_handle )

Given a string binding handle (e.g. as obtained from iluObjectToString) returns an iluObject* for that object, with the reference count incremented.

C++: virtual iluObject::~iluObject ( )

Destructor ensures that this object is completely disassociated from the ILU kernel The most specific destructor of an object should call iluDeactivate on the object to block any further incoming calls, and wait for any ongoing calls to complete. Next it should perform any object specific cleanup. Finally, the destructor in iluObject will break the association between the kernel object and this object, allowing the kernel object to be potentially freed.

C++: virtual void iluObject::iluDeactivate ( )

Ensures this object is not available from the outside. This must be the first thing called by the most specific destructor of an object. If if isn't, then the potential exists (in multithread case) for a call to come in for an object that's in the middle of destruction - a bad thing! This function blocks until there are zero ongoing calls.

C++: virtual void iluObject::iluKernelObjectUnlinked ( )

Called by iluUnlinkKernelObject - you can override this virtual function in your objects to do whatever you like when the association between your object and the kernel object is broken - e.g. delete yourself The implementation in iluObject deletes this.

iluObject - Object Publication

C++: virtual ILUCPP_BOOL iluObject::iluPublish ( )

Publishes binding information for this object in the binding service Has no effect on object reference count.

C++: virtual ILUCPP_BOOL iluObject::iluWithdraw ( )

Removes binding information for this object from the binding service Has no effect on object reference count.

C++: static void* iluObject::iluLookup (char* pc_instance_handle, char* pc_server_id, iluClass the_class )

Used by stubber generated iluLookup functions in derived classes to lookup an object in the binding service based on its instance and server id and class. Increments reference count of object. To Lookup objects of type T, use the T::iluLookup(char* pc_instance_handle, char* pc_server_id; function produced by the stubber. For example:

mybar_var =  foo(bar)::iluLookup("foo_instance_0", pc_serverid )

iluObject - Accessors

C++: virtual iluServer* iluObject::iluGetServer ( )

Returns pointer to the iluServer that this object resides in.

C++: virtual const char* /* ILUowned */ iluObject::iluId ( )

Returns the objects instance id.

C++: virtual const char* /* ILUowned */ iluObject::iluServerId ( )

Returns the id of the objects ILU Server.

iluObject - Informational

C++: virtual iluCString iluObject::iluObjectToString ( )

Returns the ILU string binding handle for the object. Caller get ownership of the string

C++: ILUCPP_BOOL iluObject::iluIsCollectibleObject ( )

Returns true if the object is of a collectible class.

C++: virtual iluCString iluObject::iluObjectToIORString ( )

Returns a string which is the object's name and contact information as specified by the CORBA IIOP spec - caller gets ownership of the string. May return NULL if the object is not exported through an IIOP ilu_Port. (Available only when IIOP support is configured into ILU.)

C++: virtual iluCString iluObject::iluObjectToURLString ( )

Returns a string which is the object's name and contact information as specified by an HTTP URL - caller gets ownership of the string. May return NULL if the object is not exported through an HTTP ilu_Port (Available only when HTTP support is configured into ILU.)

C++: ILUCPP_BOOL iluObject::iluPing ()

Returns ILUCPP_TRUE if the true object exists, and the process serving it can be contacted, otherwise ILUCPP_FALSE.

C++: ILUCPP_BOOL iluObject::_is_equivalent (iluObject* p_obj)

Returns ILUCPP_TRUE if the two objects denote the same thing.

C++: ILUCPP_BOOL iluObject::iluInSameServer (iluObject* p_obj)

Returns ILUCPP_TRUE if the two objects are in the same ILU server. Used, for example, to determine if objects are SIBLINGS.

C++: virtual const char* /* ILUowned */ iluObject::iluClassName ( )

C++: virtual const char* /* ILUowned */ iluObject::iluClassId ( )

Return the ILU class name and type id - primarily informational use.

iluObject - Reference Counting

C++: virtual void iluObject::iluIncrementReferenceCount ( )

C++: virtual void iluObject::iluDecrementReferenceCount ( )

Reference count operations - when an object is first created, it has a reference count of one. If the reference count ever goes to zero, delete is called on this. CORBA compliant apps (where objects derive from CORBA::Object) should use the duplicate and release functionality defined in the CORBA specification.

C++: virtual iluCardinal iluObject::iluGetReferenceCount ( )

Returns what the current reference count is.

C++: static iluObject* iluObject::_duplicate (iluObject* p_obj)

Increments the reference count on the object and returns it. Returns NULL if passed NULL.

C++: static iluObject* iluObject::_narrow (iluObject* p_obj)

Effectively casts the object pointer to an iluObject*.

iluObjectTable

An abstract C++ class for developers to derive from to provide Object Tables. Object tables cannot be copied or assigned. Besides doing whatever application specific things might need to be done in the constructor and destructor, a class derived from iluObjectTable must provide the iluObjectOfInstanceHandle virtual member function.

C++: virtual iluObject* iluObjectTable::iluObjectOfInstanceHandle (iluCString pc_instance_handle /* ILUowned */) = 0;

Called by ILU to create and return a new iluObject* with the specified instance handle. ILU retains ownership of pc_instance_handle - i.e. copy it if you need want to hang on to it. Note that when in this function, you are 'inside' the object's server - i.e. you hold the locks on the server - this means that when you create the object, you must specify the 3rd argument to the object's constructor (b_within_object_table) as true.

C++: virtual iluServer* iluObjectTable::iluGetServer ();

Returns the pointer to the iluServer this object table is associated with.

C++: virtual iluObjectTable::~iluObjectTable ( )

Do whatever destroying the Object Table needs to do to free up resources, etc. It gets called when the iluServer it's associated with it is shut down.

iluPassport

Encapsulates ilu_Passport functionality

C++: constructor iluPassport::iluPassport ( iluIdentityInfo p_identity_info = NULL )

Constructor - creates and returns a passport, optionally containing the specified identity.

C++: virtual iluPassport::~iluPassport ( )

Destructor - frees any associated identities in addition to freeing the passport

C++: static iluPassport* iluPassport::iluGetPassport ( )

C++: static iluPassport* iluPassport::iluSetPassport (iluPassport* p_passport )

Get and set the passport being used for outgoing calls - in the multi-threaded case, this is per-thread Set returns the old iluPassport. Note that before your thread exits, you should either call iluSetPassport(NULL), or delete the iluPassport in use (assuming it's only in use for a single thread).

C++: static iluPassport* /* ILUowned */ iluPassport::iluGetCallerPassport ( )

Get the passport of the caller.

C++: virtual void iluPassport::iluAddIdentity ( iluIdentityInfo p_identity_info /* ILUowned */ )

Adds identity to Passport. Only one identity of each type is allowed.

C++: virtual iluIdentityInfo /* ILUowned */ iluPassport::iluFindIdentity ( iluIdentityType p_identity_type )

Returns identity of specified type, if present else NULL

C++: static iluIdentityInfo iluPassport::iluCopyIdentity ( iluIdentityInfo p_identity_info )

Returns a copy of the passed identity

C++: ilu_Passport /* ILUowned */ iluPassport::iluGetIluPassport ()

Returns the (kernel) ilu_Passport

iluGSS

Encapsulates GSS functionality - only defined when ILU is configured with secure transport.

C++: static iluIdentityInfo iluGSS::iluAcquireGSSIdentity ( gss_cred_id_t gss_credential )

C++: static ILUCPP_BOOL iluGSS::iluDecodeGSSIdentity ( iluIdentityInfo p_identity_info, gss_name_t* p_name, iluFineTime* p_good_till_time,gss_OID mechanism, ILUCPP_BOOL* p_b_local, iluCardinal* p_card_flags )

p_identity_info - input; retain; info to decode p_name - output; name in identity p_good_till_time - output; good-till mechanism - input; actual mechanism desired; optional p_b_local - if TRUE, local; otherwise remote p_card_flags - connection flags, as in gss_inquire_context

C++: static gss_cred_id_t iluGSS::iluAcquireGSSCredForName ( char* pc_name, iluCardinal card_lifetime, gss_OID mechanism, ILUCPP_BOOL b_accept_only )

C++: static iluCString iluGSS::iluGSSNameToString ( gss_name_t name )

iluMainLoop

Subclass from the iluMainLoop class if you want to have your own version of the main loop. iluMainLoops cannot be copied or assigned. A single threaded application should supply all functions. An application making use of ILU's OS multi-threaded operation should not use a different mainloop. If you're using your own thread package, you must supply all functions, and see the comment for iluCppRuntime::iluInitialize

C++: virtual void iluMainLoop::iluRun ( int* p_i_stop_on_non_zero ) = 0;

Runs the main loop until *p_i_stop_on_non_zero is non-zero.

C++: virtual void iluMainLoop::iluExit ( int* p_i_stop_on_non_zero ) = 0;

Causes the main loop to exit

C++: virtual ILUCPP_BOOL iluMainLoop::iluRegisterInputHandler (int i_fd, void (* pfunction_input_handler )(int i_fd, void* pv_input_handler_arg ), void* pv_input_handler_arg ) = 0;

Input Handlers - When there is input activity on the file descriptor i_fd, the mainloop will call the registered handler procedure pfunction_input_handler, passing it i_fd and pv_input_handler_arg as arguments. Returns ILUCPP_FALSE if it can't do it's job due to some resource limitation.

C++: virtual ILUCPP_BOOL iluMainLoop::iluUnregisterInputHandler ( int i_fd, void (** ppfunction_input_handler )(int i_fd, void* pv_input_handler_arg ), void** ppv_input_handler_arg ) = 0;

Returns ILUCPP_FALSE if input on i_fd was being handled, else ILUCPP_TRUE. Sets function and arg ptrs to what they were if anything.

C++: virtual ILUCPP_BOOL iluMainLoop::iluRegisterOutputHandler (int i_fd, void (* pfunction_output_handler )(int i_fd, void* pv_output_handler_arg ), void* pv_output_handler_arg ) = 0;

Output Handlers - When it is possible to perform output on the file descriptor i_fd, the mainloop will call the registered handler procedure pfunction_output_handler, passing it i_fd and pv_output_handler_arg as arguments.

C++: virtual ILUCPP_BOOL iluMainLoop::iluUnregisterOutputHandler (int i_fd, void (** ppfunction_output_handler )(int i_fd, void* pv_output_handler_arg ), void** ppv_output_handler_arg ) = 0;

Returns ILUCPP_FALSE if output on i_fd had a handler, else ILUCPP_TRUE Sets function and arg ptrs to what they were if anything.

C++: virtual iluAlarm iluMainLoop::iluCreateAlarm ( ) = 0;

Creates an alarm. An alarm is an active object which can be set to asynchronously invoke a procedure with an argument at a specified time. An alarm may be something like a pointer to a structure that has some internal structure, but from the point of view of an alarm user, it's just a handle that is used to specify a particular alarm to be set or cleared.

C++: virtual void iluMainLoop::iluSetAlarm (iluAlarm the_alarm, iluFineTime alarm_time, void (*pfunction_alarm_handler)(void* pv_alarm_handler_arg), void* pv_alarm_handler_arg ) = 0;

Sets up an alarm to call the handler procedure pfunction_alarm_handler, passing it pv_alarm_handler_arg as an argument, when the alarm_time occurs. C++: virtual void iluMainLoop::iluClearAlarm ( iluAlarm the_alarm ) = 0;

Cancels the alarm (effectively sets the alarm time to infinity).

C++: virtual void iluMainLoop::iluDestroyAlarm ( iluAlarm the_alarm ) = 0;

Destroys the alarm (if alarm is set, does not invoke).

C++: static void iluMainLoop::iluSetFineTimeFromNow ( ilu_FineTime* p_finetime, ilu_integer i_secs, ilu_cardinal i_msecs )

Utility function to set the pointed to ilu_FineTime to a time i_secs + i_msecs in the future

C++: static void iluMainLoop::iluSetMainLoop ( iluMainLoop* p_mainloop_instance )

C++: static iluMainLoop* iluMainLoop::iluGetMainLoop ( )

Setting the Main Loop to be used - Call iluSetMainLoop set your mainloop as the one for ILU to use. It should called before any ILU initialization.

C++: static iluAlarm iluMainLoop::iluDefaultLoopCreateAlarm ( )

C++: static void iluMainLoop::iluDefaultLoopSetAlarm ( iluAlarm the_alarm, iluFineTime alarm_time, void (* pfunction_alarm_handler )(void* pv_alarm_handler_arg ), void* pv_alarm_handler_arg )

C++: static void iluMainLoop::iluDefaultLoopClearAlarm ( iluAlarm the_alarm )

C++: static void iluMainLoop::iluDefaultLoopDestroyAlarm ( iluAlarm the_alarm )

When you haven't set the main loop (i.e. you're using ILU's default loop), you can call these functions to create, set and unset alarms. (If you set your own main loop, just call its alarm functions.)

CORBA 2.0 C++ Considerations

ORB_init

The CORBA ORB_init function may be called instead of iluCppRuntime::iluInitialize (which ORB_init calls internally). The orb identifier passed to ORB_init should be "ilu". If the command line argument -iluthreaded is present in the command line arguments passed to ORB_init, then ILU will be run in threaded mode, otherwise ILU will run single-threaded.

Go to the previous, next section.