Previous | Table of Contents | Next |
To support single-threaded ORBs, as well as multi-threaded ORBs that run multi-thread-unaware code, several operations are
included in the ORB interface. These operations can be used by single-threaded and multi-threaded applications. An application
that is a pure ORB client would not need to use these operations. Both the ORB::run and ORB::shutdown are useful in fully
multi-threaded programs.
These operations are defined on the ORB rather than on an object adapter to allow the main thread to be used for all kinds
of asynchronous processing by the ORB. Defining these operations on the ORB also allows the ORB to support multiple object
adapters, without requiring the application main to know about all the object adapters. The interface between the ORB and
an object adapter is not standardized.
4.2.5.1 work_pending
boolean work_pending( );
This operation returns an indication of whether the ORB needs the main thread to perform some work.
A result of TRUE indicates that the ORB needs the main thread to perform some work and a result of FALSE indicates that the
ORB does not need the main thread.
4.2.5.2 perform_work
void perform_work();
If called by the main thread, this operation performs an implementation-defined unit of work; otherwise, it does nothing.
It is platform-specific how the application and ORB arrange to use compatible threading primitives.
The work_pending() and perform_work() operations can be used to write a simple polling loop that multiplexes the main thread
among the ORB and other activities. Such a loop would most likely be needed in a single-threaded server. A multi-threaded
server would need a polling loop only if there were both ORB and other code that required use of the main thread.
Here is an example of such a polling loop:
// C++for (;;) {if (orb->work_pending()) {
orb->perform_work();};// do other things// sleep?
};
Once the ORB has shutdown, work_pending and perform_work will raise the BAD_INV_ORDER exception with minor code 4. An application
can detect this exception to determine when to terminate a polling loop.
4.2.5.3 run
void run();
This operation provides execution resources to the ORB so that it can perform its internal functions. Single threaded ORB
implementations, and some multi-threaded ORB implementations, need the use of the main thread in order to function properly.
For maximum portability, an application should call either run or perform_work on its main thread. run may be called by multiple
threads simultaneously.
This operation will block until the ORB has completed the shutdown process, initiated when some thread calls shutdown.
4.2.5.4 shutdown
void shutdown(in boolean wait_for_completion);
This operation instructs the ORB to shut down, that is, to stop processing in preparation for destruction.
Shutting down the ORB causes all object adapters to be destroyed, since they cannot exist in the absence of an ORB.
In the case of the POA, all POAManagers are deactivated prior to destruction of all POAs. The deactivation that the ORB performs
should be the equivalent of calling deactivate with the value TRUE for etherealize_objects and with the wait_for_completion
parameter same as what shutdown was called with.
Shut down is complete when all ORB processing has completed and the object adapters have been destroyed. ORB processing is
defined as including request processing and object deactivation or other operations associated with object adapters, and the
forwarding of the responses from deferred synchronous invocations to their associated reply handlers. In the case of the
POA, this means that all object etherealizations have finished and root POA has been destroyed (implying that all descendent
POAs have also been destroyed)
If the wait_for_completion parameter is TRUE, this operation blocks until the shut down is complete. If an application does
this in a thread that is currently servicing an invocation, the ORB will not shutdown, and the BAD_INV_ORDER system exception
will be raised with the OMG minor code 3, and completion status COMPLETED_NO, since blocking would result in a deadlock.
If the wait_for_completion parameter is FALSE, then shutdown may not have completed upon return. An ORB implementation may
require the application to call (or have a pending call to) run or perform_work after shutdown has been called with its parameter
set to FALSE, in order to complete the shutdown process.
Additionally in systems that have Portable Object Adapters (see Chapter 11) shutdown behaves as if POA::destroy is called
on the Root POA with its first parameter set to TRUE and the second parameter set to the value of the wait_for_completion
parameter that shutdown is invoked with.
While the ORB is in the process of shutting down, the ORB operates as normal, servicing incoming and outgoing requests until
all requests have been completed. An implementation may impose a time limit for requests to complete while a shutdown is pending.
Once an ORB has shutdown, only object reference management operations(duplicate, release and is_nil) may be invoked on the
ORB or any object reference obtained from it. An application may also invoke the destroy operation on the ORB itself. Invoking
any other operation will raise the BAD_INV_ORDER system exception with the OMG minor code 4.
4.2.5.5 destroy
void destroy();
This operation destroys the ORB so that its resources can be reclaimed by the application. Any operation invoked on a destroyed
ORB reference will raise the OBJECT_NOT_EXIST exception. Once an ORB has been destroyed, another call to ORB_init with the
same ORBid will return a reference to a newly constructed ORB.
If destroy is called on an ORB that has not been shut down, it will start the shut down process and block until the ORB has
shut down before it destroys the ORB. The behavior is similar to that achieved by calling shutdown with the wait_for_completion
parameter set to TRUE. If an application calls destroy in a thread that is currently servicing an invocation, the BAD_INV_ORDER
system exception will be raised with the OMG minor code 3, since blocking would result in a deadlock.
For maximum portability and to avoid resource leaks, an application should always call shutdown and destroy on all ORB instances
before exiting.