However, there is no need to compile the IDL in RTCORBA.idl to make use of the Real-Time CORBA features. Applications need only to include the
rtcorba.h header file that is provided with the other VisiBroker header files.
The Real-Time ORB does not need to be explicitly initialized—it is initialized implicitly as part of the regular CORBA::ORB_init call. Any Real-Time ORB initialization arguments are passed in to the call to
CORBA::ORB_init, along with non-Real-Time arguments. If any Real-Time initialization argument is invalid, the
ORB_init call fails, and a system exception is raised.
To use the Real-Time ORB operations, the application must have a reference to the RTCORBA::RTORB instance. This reference can be obtained any time after the call to
ORB_init, and is obtained by calling the resolve_initial_references operation on
CORBA::ORB, with the object id "
RTORB" as the parameter. Because
resolve_initial_references returns the reference as a
CORBA::Object_ptr, it must then be narrowed to a
RTCORBA::RTORB_ptr before it can be used.
The code example below shows how to obtain the RTCORBA::RTORB reference. Similar code can be found in the Real-Time CORBA examples included with the VisiBroker release:
priority_model,
threadpool,
visthread and
rtmutex.
Real-Time Object Adapters are created in the normal way, through a call to create_POA. Configuration of the extra, Real-Time properties is achieved through the passing of new Real-Time policies in the policy list parameter. An example of POA creation specifying one such new policy (and its associated value) is shown below:
The RTCORBA::Priority type is used to represent Real-Time CORBA Priority:
As per the Real-Time CORBA Specification, numerically higher RTCORBA::Priority values are defined to be of higher priority.
In practice, an application does not need to use the entire range of valid RTCORBA::Priority values (0 to 32767.) A smaller range, which suits the needs of the application, can be defined as the only admissible range. This is achieved through control of the Priority Mapping. Priority Mappings are described in the next section.
By default, VisiBroker for C++ installs a Priority Mapping that only allows RTCORBA::Priority values in the range 0 to 31 (the POSIX threading range of priorities). See the next section for details.
As the Real-Time CORBA application describes its priorities in terms of RTCORBA::Priority values, and the OS works in terms of native priority values, a mapping must be defined between these two priority schemes. The mapping is used by the ORB, to obtain the native priority corresponding to a given
RTCORBA::Priority value, and vice versa, as is required. This is done, for example, when an application specifies that it wants a Threadpool to have threads that are created with a particular
RTCORBA::Priority, and the ORB needs to know what native priority to tell the OS to use when it actually creates the threads.
To support Priority Mappings, a RTCORBA::NativePriority type and
RTCORBA::PriorityMapping type are defined:
RTCORBA::NativePriority values must be integers in the range –32768 to +32767. However, depending on the OS, the valid range is a subset of this range.
The RTCORBA::PriorityMapping type is defined as an IDL native interface. This means that the interface is defined directly in each implementation language, rather than being defined in IDL and mapped automatically to each language according to the rules of the particular CORBA language mapping. This is done for reasons of efficiency.
The C++ mapping of the RTCORBA::PriorityMapping interface is:
This method takes a RTCORBA::Priority value from the
corba_priority parameter and either maps it to a
RTCORBA::NativePriority value or fails to map it. If the value is mapped, the resulting native priority value is stored in the location referenced by the parameter
native_priority (which is a C++ reference parameter) and a true value is returned to indicate that the mapping was successful. If the value is not mapped, the contents of the
native_priority parameter are not altered, and a false value is returned to indicate that the mapping operation failed.
The converse of to_native, the
to_CORBA method takes a
RTCORBA::NativePriority value from the
native_priority parameter, and either maps it to a
RTCORBA::Priority value or fails to map it. If the value is mapped, the resulting
RTCORBA::Priority value is stored in the location referenced by the
corba_priority parameter (which is a C++ reference parameter) and a true value is returned to indicate that the mapping was successful. If the value is not mapped, the contents of the
corba_priority parameter are not altered, and a false value is returned to indicate that the mapping operation failed.
This method just returns the highest RTCORBA::Priority value that is valid in this mapping. The ORB needs to be explicitly told the highest value as there is no efficient way for it to determine it by examining the behavior of the
to_native and
to_CORBA methods given different input values.
•
|
The to_native and to_CORBA methods should be able to handle all values of their input parameter, in the range –32768 to +32767.
|
•
|
to_native must definitely fail to map values outside the range 0 to 32767, and might fail to map values within that range as well. (For example the default Priority Mapping fails to map all values outside the range 0 to 31.)
|
•
|
to_CORBA must definitely fail to map values outside the range of the native priority scheme and might fail to map values within that range as well. (The default Priority Mapping chooses to map all values in the 0 to 31 range.)
|
•
|
Lower RTCORBA::Priority values should always map to lower importance native priority values, and higher to higher. Note that in the case of a Pthreads based operating system, this means mapping numerically lower RTCORBA::Priority values to/from numerically higher Native Priorities. This follows the convention used by the majority of Real-Time Operations Systems. The convention maintains consistency with Real-Time CORBA applications developed on other Real-Time Operations Systems. Otherwise future porting and interworking with other Real-Time applications will be greatly complicated.
|
•
|
RTCORBA::Priority 0 should always be mapped, and always be mapped to the value of lowest importance in the range of native priority values that is mapped to/ from.
|
•
|
max_priority must return the highest RTCORBA::Priority value that is mapped by the mapping. (That is, the highest value for which a native priority value is returned.)
|
•
|
to_native and to_CORBA usually return the same value (or fail to map) every time they are called with the same input value.
|
•
|
to_native and to_CORBA are usually reverse mappings of one another.
|
•
|
The ranges of RTCORBA::Priority and native priority values that are mapped are usually each a single contiguous range of priority values.
|
•
|
Valid RTCORBA::Priority range is 0 to 31 only. This follows the POSIX threading model. All priorities outside of this range are invalid, which means an exception is raised if an attempt is made to use them.
|
•
|
The valid RTCORBA::Priority values are mapped one-to-one onto a 32 priority sub-range of the native operating system—the "native priority range".
|
•
|
The valid RTCORBA::Priority values are mapped onto the native priority range in such a way that RTCORBA::Priority value 0 corresponds to the lowest-importance native priority in the sub-range used, and RTCORBA::Priority 31 corresponds to the highest-importance native priority in the sub-range used.
|
•
|
To have more or fewer RTCORBA::Priority values in the range of valid (mapped) values. For example, to only map RTCORBA::Priority values in the range 0 to 8 or to map values in the range 0 to 128.
|
Note that the relationship between the ranges of RTCORBA::Priority and native priority values that are valid in the mapping will determine whether the mapping is a one-to-one mapping or not. The mapping does not have to be a one-to-one mapping, but this can be convenient. The default Priority Mapping is a one-to-one mapping.
Installed Priority Mappings should follow the convention, used in the default Priority Mapping, of making the RTCORBA::Priority 0 have the lowest importance. This means ensuring that
RTCORBA::Priority 0 maps to the numerically smallest native priority value (of the sub-range that is being mapped to.) This maintains consistency with Real-Time CORBA applications developed across operating systems. Otherwise future porting and interworking with other Real-Time applications will be greatly complicated.
A new Priority Mapping is installed by defining a new class, which must inherit from the class RTCORBA::PriorityMapping, and creating one static instance of it in the application. When the static instance is initialized (during the execution of static constructors) the base
RTCORBA::PriorityMapping class constructor will register the new mapping with the ORB.
For an example of writing and installing a new Priority Mapping, look at the files mapping.h and
mapping.C in the threadpool example included in the VisiBroker installation. Note the single instance of the new class that is created in global scope in
mapping.C. When the resulting
mapping.o is built with a VisiBroker application and static constructor initialization takes place during the execution of the application, it is the initialization of this instance that installs the mapping.
A Threadpool is created by invoking the create_threadpool operation on the Real-Time ORB. The arguments to
create_threadpool have the following significance:
The RTCORBA::Priority at which idle threads should remain while in the pool waiting for a CORBA invocation to execute. The priority at which the invocation is executed depends on the Real-Time CORBA Priority Model in use. See “Real-Time CORBA Priority Models” for details. This parameter determines the priority of the threads when they are not handling invocations.
If dynamic_threads is greater than zero, so that threads can be created dynamically, the threads are not immediately destroyed after they have completed executing the CORBA invocation that they were created to handle. They are returned to the Threadpool, in the same way that static threads are. However, dynamic threads that remain idle in the Threadpool might eventually be destroyed during garbage collection that occurs from time to time.
The amount of time a dynamically created thread must remain idle in a Threadpool before it is destroyed can be set using the threadpool_idle_time operation of
RTCORBA::RTORB. If the idle time is not set using this operation, it defaults to 300 seconds.
If successful, create_threadpool returns an identifier for the new Threadpool. The identifier is of type
RTCORBA::ThreadpoolId (an unsigned long), and is subsequently used to refer to that Threadpool.
The semantics of dynamic_threads value here in the Real-Time context differs from that of the Dispatcher Thread pool
threadMax value. (See
“Thread pool dispatch policy”.) A
dynamic_threads value of zero means that, even if needed, no additional threads are created for the RTCORBA Threadpool. In contrast, a
threadMax value of zero for the dispatcher threadpool means that the VisiBroker ORB has the freedom to create additional threads, as and when required.
Which Threadpool a POA is associated with is determined by passing the RTCORBA::ThreadpoolId of the desired Threadpool into the
create_POA operation as the value of a
RTCORBA::ThreadpoolPolicy policy. The following example associates a POA with a Threadpool at time of POA initialization.
create_POA fails if any part of the Real-Time CORBA configuration is invalid. For example, if the ThreadpoolId is not for a currently existing Threadpool, a
CORBA::BAD_PARAM system exception is raised.
The General Threadpool does not have to be created by a call to RTCORBA::RTORB’s
create_threadpool operation. Instead, the General Threadpool is created automatically by the ORB the first time it is required.
A CORBA::BAD_PARAM system exception is raised by the set attribute operation if an attempt is made to set a priority outside of the valid 0 to 32767 range. A
CORBA::DATA_CONVERSION exception is raised if an attempt is made to set a priority that is in the 0 to 32767 range, but outside of the range supported by the currently installed Priority Mapping.
A CORBA::INITIALIZE system exception is raised if an attempt is made to get the priority value from a thread that has not yet had a Real-Time CORBA Priority value set on it. (The native priority of the current thread is not just mapped to a Real-Time CORBA Priority and returned.)
To use the RTCORBA::Current object, a reference to it must be obtained. This is achieved by calling the
CORBA::ORB operation
resolve_initial_references with the parameter
RTCurrent, as shown in the following example:
Note that the RTCORBA::Current reference only needs to be obtained once. The same variable can be used by different threads, and will behave as if it is private to each of them (setting and getting their thread-specific priority value.) This behavior is inherited from the base
CORBA::Current object.
The Priority Model is selected at POA initialization time, by including a RTCORBA::PriorityModelPolicy instance in the Policy List passed as a parameter to
create_POA. The Policy is configured with one of the following values:
In either case, a RTCORBA::Priority value is also specified as part of the Policy. The two models use this priority value differently:
See the priority_model example included with the VisiBroker installation for further examples of configuring the two different Priority Models.
The priority to run invocations at can be overridden for a given object by using either the operation activate_object_with_priority or
activate_object_with_id_and_priority to activate the object in question. These operations work in the same way as
activate_object and
activate_object_with_id, but take a Real-Time CORBA Priority value as an additional parameter.
A new RTCORBA::Mutex object is obtained using the
create_mutex operation of
RTCORBA::RTORB. A Mutex object has two states: locked and unlocked. Mutex objects are created in the unlocked state. When the Mutex object is in the unlocked state the first thread to call the l
ock() operation will cause the Mutex object to change to the locked state and the calling thread will be assigned ownership of the Mutex object.
Subsequent threads that call the lock() operation while the Mutex object is still in the locked state will block until the owner thread unlocks it by calling the
unlock() operation.
The try_lock() operation works like the
lock() operation except that if it does not get the lock within
max_wait time it returns false. If the
try_lock() operation does get the lock within the
max_wait time period it returns true.
If the application does not configure the priority of these threads they all default to running at the highest RTCORBA::Priority in the installed priority mapping. That is the priority that is returned by the Priority Mapping’s
max_priority method. Hence, with the Default Priority Mapping installed, they will all run at
RTCORBA::Priority 31.
Where <SE name> is the name of a Server Engine and <SCM name> is the name of a Server Connection Manager. Sets the priority of the Listener thread associated with a specific SCM in a specific Server Engine. Can be set at any time prior to the creation of that Server Engine (which occurs during the creation of the first POA that uses that Server Engine.)
In earlier versions of the VisiBroker-RT product, the vbroker.agent.threadPriority property was called
vbroker.dsuser.thread.priority. The name has been changed to keep it consistent with other VisiBroker Smart Agent property names. However, the old property name is still supported and you can continue to use it in existing deployments.
-ORBRTPriorityRange is given as one argument, and the two values are given together in another argument, separated by a comma, as shown in the following example.
The two values give the minimum RTCORBA::Priority followed by the maximum
RTCORBA::Priority value that internal ORB threads are permitted to run at. If this argument is given, the VisiBroker internal ORB threads defaults to running at the maximum priority that is specified.
If the range is invalid, the ORB_init call fails and raises a CORBA system exception. If the range is invalid because one or both of the values is not a valid
RTCORBA::Priority value, or because min is greater than max, then a
CORBA::BAD_PARAM exception is raised. If the range is invalid because one or both of the values is outside of the range supported by the installed Priority Mapping, then a
CORBA::DATA_CONVERSION exception is raised.