Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Advanced CORBA Programming wit C++ - M. Henning, S. Vinoski.pdf
Скачиваний:
65
Добавлен:
24.05.2014
Размер:
5 Mб
Скачать

IT-SC book: Advanced CORBA® Programming with C++

The relationship between the bottom consumer and the middle supplier represents the canonical push model.

The relationship between the bottom consumer and the bottom supplier represents the hybrid pull/push model.

Thus, Figure 20.7 shows that an event channel is capable of fulfilling all four roles simultaneously.

Although the event channel is fulfilling multiple roles, each consumer receives all events provided by all suppliers. The event channel decouples the consumers and suppliers so that none of them knows whether the other consumers and suppliers are connected for pushing or for pulling.

20.5 Event Service Interfaces

The CosEventComym module provides the IDL definitions needed to interact with event channels. Many of these interfaces, however, are concerned only with suppliers and consumers; they make no mention of event channels. As Figure 20.8 shows, the event channel is itself both a supplier and consumer.

Figure 20.8 Event channel proxy supplier and proxy consumer interfaces.

These supplier and consumer interfaces are called proxy interfaces because they represent the actual supplier and the actual consumer to each other. In other words, these interfaces provide the illusion to consumers and suppliers that they are interacting with the actual suppliers and actual consumers, respectively.

20.5.1 Interfaces for the Push Model

Following are the interfaces that support the push model.

module CosEventComm

exception Disconnected {};

interface PushConsumer {

void push(in any data) raises(Disconnected);

void disconnect_push_consumer();

};

interface PushSupplier {

void disconnect_push_supplier();

}; // ...

};

803

IT-SC book: Advanced CORBA® Programming with C++

A push consumer implements the PushConsumer interface and registers an object reference for it with a supplier. A supplier then uses that object reference to send event data to the PushConsumer object by invoking its push operation.

Both consumers and suppliers can disconnect from each other. If an event supplier decides that it no longer wants to send events to a particular consumer, it can invoke the disconnect_push_consumer operation on that consumer. If a supplier invokes push on a disconnected consumer, the supplier gets a Disconnected exception.

Alternatively, if a push consumer no longer wants to receive events, it can disconnect from its supplier by invoking disconnect_push_supplier on the supplier's PushSupplier object. This implies that the supplier must have given a PushSupplier object reference to the consumer. This normally occurs at registration time, as described in Section 20.5.3.

Event data is sent in the form of an any, and that allows any IDL data type to be used to convey information about the event. This implies that the consumer either knows what type to expect in the any or is willing to determine the contents dynamically using the DynAny interface (see Chapter 17). Use of the any type also allows the event data to be passed unchanged through an event channel implementation. Without it, either the event channel IDL would have to specify the precise data type that all suppliers and consumers would have to use regardless of their problem domain, or the event channel would somehow have to support dynamic extensibility to allow suppliers and consumers to add type-specific event delivery operations as necessary. Using the any type is much more practical than either of these approaches.

20.5.2 Interfaces for the Pull Model

The interfaces that support the pull model, shown next, are essentially a mirror image of the interfaces for the push model.

module CosEventComm { interface PullSupplier {

any pull() raises(Disconnected);

any try_pull(out boolean has_event) raises(Disconnected);

void disconnect_pull_supplier();

};

interface PullConsumer {

void disconnect_pull_consumer();

}; // ...

};

804

IT-SC book: Advanced CORBA® Programming with C++

A consumer pulls events from a supplier in one of two ways.

The consumer invokes the pull operation to block until an event is available and can be returned.

The consumer invokes the try_pull operation to poll for events without blocking. If no events are available, try_pull returns immediately with its out parameter has_event set to false to indicate that no event data was available. If an event is available, try_pull returns the event data and sets the has_event parameter to true. If a consumer is no longer interested in pulling events from a supplier, it invokes the disconnect_pull_supplier operation. Any further invocation of pull or try_pull will raise the Disconnected exception to the invoking consumer. A supplier can indicate its desire to break the pull connection by invoking disconnect_pull_consumer on the consumer object's PullConsumer interface. As with the push model, this capability implies that the supplier and consumer have already exchanged PullSupplier and PullConsumer object references.

20.5.3 Event Channel Interfaces

So far, our descriptions of the interfaces used for pushing and pulling have not mentioned the event channel. As Figure 20.8 shows, this is because the event channel presents itself as a consumer to suppliers and as a supplier to consumers. However, event channels also provide administrative interfaces that allow consumers and suppliers to establish logical connections with it. The IDL types related to event channel administration are defined in the CosEventChannelAdmin module.

module CosEventChannelAdmin { interface ProxyPushSupplier; interface ProxyPullSupplier;

interface ProxyPushConsumer; interface ProxyPullConsumer;

interface ConsumerAdmin {

ProxyPushSupplier obtain_push_supplier(); ProxyPullSupplier obtain_pull_supplier();

};

interface SupplierAdmin {

ProxyPushConsumer obtain_push_consumer(); ProxyPullConsumer obtain_pull_consumer();

};

interface EventChannel {

ConsumerAdmin

for_consumers();

SupplierAdmin

for_suppliers();

void

destroy();

};

 

// ...

 

};

805

IT-SC book: Advanced CORBA® Programming with C++

The EventChannel interface supplies three operations.

Consumers that want to connect to an event channel invoke its for_consumers operation, which returns a ConsumerAdmin object reference.

Suppliers that want to connect to an event channel invoke its for_suppliers operation, which returns a SupplierAdmin object reference.

Invoking destroy on an event channel permanently destroys it, including any events that it has not yet delivered. Moreover, destroying the event channel also destroys all administrative objects created by that channel and all proxy objects created by those administrative objects. Any connected consumers and suppliers are notified when their channel is destroyed.

After invoking for_consumers on an event channel, the consumer must decide whether it wants to use the push model or the pull model. If it wants to be a push consumer, it invokes the obtain_push_supplier operation on the ConsumerAdmin object returned from for_consumers. Otherwise, it invokes obtain_pull_supplier. Similarly, suppliers must decide whether they want to support the push or pull model, so they can invoke the appropriate operation on the

SupplierAdmin returned from EventChannel::for_suppliers.

Establishing Push Model Connections

A consumer that wants to register as a push consumer first obtains a

ProxyPushSupplier object reference by invoking obtain_push_supplier on a ConsumerAdmin object. Similarly, a supplier that wants to push events first obtains a

ProxyPushConsumer by invoking SupplierAdmin::obtain_push_consumer. These proxy interfaces are shown next.

module CosEventChannelAdmin { exception AlreadyConnected {}; exception TypeError {};

interface ProxyPushSupplier : CosEventComm::PushSupplier { void connect_push_consumer(

in CosEventComm::PushConsumer push_consumer ) raises(AlreadyConnected, TypeError);

};

interface ProxyPushConsumer : CosEventComm::PushConsumer { void connect_push_supplier(

in CosEventComm::PushSupplier push_supplier ) raises(AlreadyConnected);

}; // ...

};

806

IT-SC book: Advanced CORBA® Programming with C++

The ProxyPushSupplier interface inherits the CosEventComm:: PushSupplier interface, and ProxyPushConsumer inherits

CosEventComm::PushConsumer. These base interfaces are described in Section

20.5.1. These derived interfaces supply operations that allow consumers and suppliers, respectively, to establish connections to an event channel. A push consumer invokes connect_push_consumer on a ProxyPushSupplier in order to establish a connection to its PushConsumer object. Similarly, a push supplier invokes connect_push_supplier on a ProxyPushConsumer in order to connect itself.

A consumer invoking connect_push_consumer passes an object reference for its PushConsumer object. By invoking push on this object reference, the supplier delivers events to the consumer. As described in Section 20.5.1, the supplier can also invoke the disconnect_push_consumer to disconnect the consumer from the channel.

A supplier calls connect_push_supplier to make itself known to the target proxy push consumer. If it is interested in having the proxy push consumer notify it when it is about to be disconnected, it can pass a non-nil PushSupplier object reference as an argument. Otherwise, it must pass a nil object reference, in which case it will not be notified if it is disconnected by the proxy push consumer.

Establishing Pull Model Connections

A supplier that wants to register as a pull supplier first obtains a

ProxyPullConsumer object reference by invoking obtain_pull_consumer on a SupplierAdmin object. Similarly, a consumer that wants to pull events first obtains a ProxyPullSupplier by invoking ConsumerAdmin::obtain_pull_supplier. These proxy interfaces are shown next.

module CosEventChannelAdmin {

interface ProxyPullConsumer : CosEventComm::PullConsumer { void connect_pull_supplier(

in CosEventComm::PullSupplier pull_supplier ) raises(AlreadyConnected, TypeError);

};

interface ProxyPullSupplier : CosEventComm::PullSupplier { void connect_pull_consumer(

in CosEventComm::PullConsumer pull_consumer ) raises(AlreadyConnected);

}; // ...

};

Like their push counterparts described in the preceding section, these interfaces inherit the basic pull model interfaces defined in the CosEventComm module (see Section

20.5.2). ProxyPullConsumer and ProxyPullSupplier provide operations that

807

IT-SC book: Advanced CORBA® Programming with C++

allow pull suppliers and pull consumers, respectively, to establish connections to an event channel.

A supplier invoking connect_pull_supplier passes an object reference for its PullSupplier object. By invoking pull on this object reference, the consumer can retrieve events from the supplier. As described in Section 20.5.2, the consumer can also invoke the disconnect_pull_supplier to disconnect the supplier from the channel.

A consumer calls connect_pull_consumer to make itself known to the target proxy pull supplier. If it is interested in having the proxy pull supplier notify it when it is about to be disconnected, it can pass a non-nil PullConsumer object reference as an argument. Otherwise, it must pass a nil object reference, in which case it will not be notified if it is disconnected by the proxy pull supplier.

Connection Exceptions

A proxy supplier can be connected only to a single consumer; similarly, a proxy consumer can be connected only to a single supplier. To enforce this, all connection operations that the proxy interfaces provide can raise the AlreadyConnected exception. This exception is raised if a connection operation is invoked multiple times on the same proxy. For example, the following code will cause an AlreadyConnected exception to be raised.

proxy_push_supplier->connect_push_consumer(a_push_consumer); proxy_push_supplier->connect_push_consumer(another_push_consumer);

The second invocation of connect_push_consumer will raise the AlreadyConnected exception because the first invocation established a connection to the target proxy supplier.

The ProxyPushSupplier::connect_push_consumer and the ProxyPullConsumer::connect_pull_supplier can also raise the

TypeError exception. This exception is raised if the proxy supplier and proxy consumer objects of an event channel implementation impose additional type constraints on the consumers and suppliers that are connected to them. This exception is present primarily to support typed event channels, which are event channels that pass specific event data types rather than pass event data using the IDL any type. Because implementations of typed event channels are rare, there is little real-world experience with using them, so we do not cover them in this book.

Disconnection

Invoking disconnection operations on proxy supplier and consumer objects effectively destroys them. This is because the disconnection operations provide the only means by which an event channel knows it can clean up connections that are no longer needed. It

808

IT-SC book: Advanced CORBA® Programming with C++

might have been better if the designers of the OMG Event Service had made the names of the disconnection operations on the proxy supplier and consumer interfaces reflect their destructive side effects. However, this was not possible because the disconnection operations are inherited from the base consumer and supplier interfaces provided in the CosEventComm module. Because your user applications implement these base interfaces in order to send and receive events, you can make their disconnection operations perform whatever actions you deem necessary, including destroying the target object.

Although the Event Service specification does not require it, you should always explicitly invoke disconnection operations when you no longer want to supply or receive events. Otherwise, your event channel might have a difficult time determining whether and when it can clean up its proxy consumer and supplier objects. Over time, these stranded proxy objects can bloat an event channel process and affect its event delivery performance.

20.5.4 Event Channel Federation

Because event channels support the basic consumer and supplier interfaces for both push and pull, one event channel can be hooked to another event channel just as any other supplier or consumer can be. Figure 20.9 shows one event channel registered as a

PushConsumer of another.

Figure 20.9 Federated event channels.

Coupling event channels in this manner allows you to distribute the responsibility and costs of event delivery. In Figure 20.9 the consumer event channel has four consumers of its own, and the supplier event channel has two consumers. If the consumer event channel were not registered as a consumer of the supplier event channel, all four of its

809