Changes to attempt to silence bcc64x
[ACE_TAO.git] / TAO / docs / events_tutorial.html
blob28aef50aee7f72c3b7c71dc9f06d39a4d495e3ea
1 <html>
2 <!-- -->
3 <head>
4 <title>Using the Real-Time Event Service</title>
5 </head>
7 <BODY text = "#000000"
8 link="#000fff"
9 vlink="#ff0f0f"
10 bgcolor="#ffffff">
12 <br>
13 <br>
15 <center>
16 <h1>Using the Real-Time Event Service</h1><P>
18 <A HREF="http://www.cs.wustl.edu/~cdgill/">Chris Gill</a>,
19 <A HREF="http://www.cs.wustl.edu/~harrison/">Tim Harrison</a>, and
20 <A HREF="http://www.cs.wustl.edu/~coryan/">Carlos O'Ryan</a><br><br>
22 <A HREF="mailto:cdgill@cs.wustl.edu">cdgill@cs.wustl.edu</a>,
23 <A HREF="mailto:harrison@cs.wustl.edu">harrison@cs.wustl.edu</a>, and
24 <A HREF="mailto:coryan@cs.wustl.edu">coryan@cs.wustl.edu</a><br>
25 </center>
27 <br>
28 <br>
30 <P><HR><P>
31 <!-- ************************************************************ -->
33 <center>
34 <table cellpadding=10 border=0 cellspacing=4>
35 <tr><td>
36 <h2><a name="Section0">Overview</a></h2>
37 <BR>
38 <BR>
39 <tr><td>
40 <h3>Contents</h3>
41 <BR>
42 <ol>
43 <li> <a href="events_tutorial.html#Section0">Overview</a>
44 <li> <a href="events_tutorial.html#Section1">The COS Event Model</a>
45 <li> <a href="events_tutorial.html#Section2">Real-Time Event Service Enhancements</a>
46 <li> <a href="events_tutorial.html#Section3">The Real-Time Event Service</a>
47 <li> <a href="events_tutorial.html#Section4">Developing Consumers</a>
48 <li> <a href="events_tutorial.html#Section5">Developing Suppliers</a>
49 <li> <a href="events_tutorial.html#Section6">Caring For Your Event Channel</a>
50 <li> <a href="events_tutorial.html#Section7">Sample Applications</a>
51 <li> <a href="events_tutorial.html#Section8">Reference Materials</a>
52 </ol>
54 <P><HR><P>
55 <tr><td>
56 <h3>Introduction</h3>
57 <BR>
58 This material is intended to provide an introduction to the COS Event Model,
59 the Real-Time extensions to that model in TAO, and a set of examples that
60 illustrate the techniques used to build systems using these models. The CORBA
61 Event Service provides a flexible model for asynchronous communication among
62 objects. However, the standard CORBAEvent Service specification lacks
63 important features required by real-time applications. These features include
64 event filtering, event correlation, and periodic event processing.<P>
66 The standard CORBA operation invocation model supports twoway, oneway,
67 and deferred synchronous interactions between clients and servers.
68 The primary strength of the twoway model is its intuitive mapping onto
69 the <code>object->operation()</code> paradigm supported by OO languages.
70 In principle, twoway invocations simplify the development of
71 distributed applications by supporting an implicit request/response
72 protocol that makes remote operation invocations transparent to the
73 client. <P>
75 In practice, however, the standard CORBA operation invocation models
76 are too restrictive for real-time applications. In particular, these
77 models lack asynchronous message delivery, do not support timed
78 invocations or group communication, and can lead to excessive polling
79 by clients. Moreover, standard oneway invocations might not implement
80 reliable delivery and deferred synchronous invocations require the use
81 of the CORBA Dynamic Invocation Interface (DII), which yields
82 <A HREF="http://www.cs.wustl.edu/~schmidt/GLOBECOM-96.ps.gz">excessive
83 overhead</A> for most real-time applications. <P>
85 The Event Service is a CORBA Object Service (COS) that is designed to
86 alleviate some of the restrictions with standard CORBA invocation
87 models. In particular, the COS Event Service supports asynchronous
88 message delivery and allows one or more suppliers to send messages to
89 one or more consumers. Event data can be delivered from suppliers to
90 consumers without requiring these participants to know about each
91 other explicitly. <P>
93 There are two models (<EM>i.e.</EM>, <EM>push</EM> vs. <EM>pull</EM>)
94 of participant collaborations in the COS Event Service architecture.
95 This material focuses on real-time enhancements to the push model, which
96 allows suppliers of events to initiate the transfer of event data to
97 consumers. Suppliers push events to the Event Channel, which in turn
98 pushes the events to consumers. <P>
100 Suppliers use Event Channels to push data to consumers. Likewise,
101 consumers can explicitly pull data from suppliers. The push and pull
102 semantics of event propagation help to free consumers and suppliers
103 from the overly restrictive synchronous semantics of the standard
104 CORBA twoway communication model. In addition, Event Channels can
105 implement group communication by serving as a replicator, broadcaster,
106 or multicaster that forward events from one or more suppliers to
107 multiple consumers.<p>
109 </table>
110 </center>
112 <hr><P>
113 <!-- ************************************************************ -->
115 <center><table cellpadding=1 border=0 cellspacing=4>
116 <tr><td align=center>
117 <center><h2><a name="Section1">The COS Event Model</a></h2></center>
118 </table></center>
120 <table cellpadding=1 border=0 cellspacing=4>
121 <h3>Relationships Between Modules</h3>
123 The role of each component in the COS Event Model is outlined
124 below:<P>
126 <ul>
127 <li> <b><i>EventChannel</i></b> -- The EventChannel interface provides
128 two factory methods, which allow applications to obtain consumer and
129 supplier administration objects, respectively, and use them to create
130 the other objects described below, to connect to the event channel. <P>
132 <li> <b><i>SupplierAdmin</i></b> -- The SupplierAdmin interface provides
133 factory methods which create the appropriate supplier proxy objects. <P>
135 <li> <b><i>ConsumerAdmin</i></b> -- The ConsumerAdmin interface provides
136 factory methods which create the appropriate consumer proxy objects. <P>
138 <li> <b><i>ProxyPullSupplier</i></b> -- The ProxyPullSupplier
139 interface is used by consumers in the pull model to connect and
140 disconnect from the channel. This interface inherits from the
141 PullSupplier interface, and acts as a proxy for the suppliers
142 from which the channel will pull events. <P>
144 <li> <b><i>ProxyPushSupplier</i></b> -- The ProxyPushSupplier
145 interface is used by consumers in the push model to connect and
146 disconnect from the channel. This interface inherits from the
147 PushSupplier interface, and acts as a proxy for the suppliers
148 which will push events to the channel. <P>
150 <li> <b><i>ProxyPullConsumer</i></b> -- The ProxyPullConsumer
151 interface is used by suppliers in the pull model to connect and
152 disconnect from the channel. This interface inherits from the
153 PullConsumer interface, and acts as a proxy for the consumers
154 on whose behalf the channel will pull events. <P>
156 <li> <b><i>ProxyPushConsumer</i></b> -- The ProxyPushConsumer
157 interface is used by suppliers in the push model to connect and
158 disconnect from the channel. This interface inherits from the
159 PushConsumer interface, and acts as a proxy for the consumers
160 to which the channel will push events. <P>
162 <li> <b><i>PullSupplier</i></b> -- The PullSupplier interface provides
163 the necessary methods of a supplier of events in the pull model. <P>
165 <li> <b><i>PushSupplier</i></b> -- The PushSupplier interface provides
166 the necessary methods of a supplier of events in the push model. <P>
168 <li> <b><i>PullConsumer</i></b> -- The PullConsumer interface provides
169 the necessary methods of a consumer of events in the pull model. <P>
171 <li> <b><i>PushConsumer</i></b> -- The PushConsumer interface provides
172 the necessary methods of a consumer of events in the push model. <P>
173 </ul>
175 <tr><td>
176 </table>
177 <br>
178 <br>
179 <center><table cellpadding=1 border=0 cellspacing=4>
180 <tr><td align=center>
181 <center><IMG SRC="http://www.cs.wustl.edu/~schmidt/gifs/ec_participants2.gif"></center>
182 </table></center>
184 <P><hr width="75%"><P> <!-- intra-section separator -->
186 <center><table cellpadding=1 border=0 cellspacing=4>
187 <h3>The Push Model</h3>
188 <tr><td>
189 <center><IMG SRC="http://www.cs.wustl.edu/~schmidt/gifs/ec_push.gif"></center>
191 <tr><td>
192 <UL>
193 <LI> Consumers - Ultimate targets of events
194 <LI> Suppliers - Generate events
195 <LI> Event Channel - Decouple consumers and suppliers by propagating
196 events to consumers on behalf of suppliers
197 </UL>
198 </table></center>
200 <P><HR><P>
201 <!-- ************************************************************ -->
203 <center><table cellpadding=1 border=0 cellspacing=4>
204 <tr><td>
206 <h2><a name="Section2">Real-Time Event Service Enhancements</a></h2>
208 <tr><td>
209 <ul>
210 <li> <b><i>Prioritized dispatching within preemption
211 classes</i></b> -- The current implementation can dispatch
212 events in the same queue by their order of importance, which is
213 necessary to support priorities within a rate group. <p>
215 <li> <b><i>Suspend/resume</i></b> -- If a consumer's event
216 dependencies change at run-time, it can utilize the
217 suspend/resume functionality through the new
218 <code>ProxyPushSupplier::suspend</code> and
219 <code>ProxyPushSupplier::resume</code> methods. When a
220 consumer invokes <code>ProxyPushSupplier::suspend</code>, the
221 dependencies registered with that proxy will be disabled until
222 the <code>resume</code> methods is called. These enhancements
223 allow run-time flexibility of event dependencies, but maintains
224 the determinism required by the system scheduling policy (i.e.,
225 consumers can not add and remove dependencies at run-time -
226 just suspend and resume them).<p>
228 <LI> <B><I>Event data model</I></B> -- The data model may use
229 unions, untyped buffers, or type anys.<P>
231 <LI> <B><I>Event filtering</I></B> -- Consumers may register for
232 events based on event type, or supplier id. The event channel filters events
233 based on these registrations, to ensure efficient event delivery.<P>
235 <LI> <B><I>Event correlation</I></B> -- Consumers may register
236 for event delivery based on conjunctive or disjunctive sets of events. Conjunctive
237 registrations cause the event channel to notify the consumer when <I>all</I>
238 events in the set have arrived. Disjunctive registrations cause the event channel
239 to notify the consumer when <I>any</I> event in the set has arrived.<P>
241 <LI> <B><I>Periodic event processing</I></B> -- Consumers
242 may register for suppliers based on timed events. Periodic suppliers push events
243 into the channel at well defined intervals.<P>
245 <LI> <B><I>Active consumers and suppliers</I></B> -- See
246 <a href="events_tutorial.html#Section3">The Real-Time Event Service</a><P>.
248 </ul>
249 </table>
250 </center>
252 <P><HR><P>
253 <!-- ************************************************************ -->
255 <center><table cellpadding=1 border=0 cellspacing=4>
256 <tr><td align=center>
257 <h2><a name="Section3">The Real-Time Event Service</a></h2>
258 </table></center>
260 <center><table cellpadding=1 border=0 cellspacing=4>
261 <h3>Real-Time ORB and Services</h3>
262 <tr><td>
263 <center><IMG SRC="http://www.cs.wustl.edu/~schmidt/gifs/corbaopt10.gif"></center>
265 <br>
266 <center><tr><td>
267 <ul>
268 <li> Real-time event dispatching<P>
269 <UL>
270 <LI> Priority-based queueing and preemption mechanisms<P>
271 </UL>
272 <li> Centralized event filtering and correlation<P>
273 <ul>
274 <LI> Source/type-based filtering<P>
275 <LI> Conjunction/Disjunction (AND/OR) correlations<P>
276 </ul>
278 <li> Periodic and Aperiodic processing <P>
279 <UL>
280 <LI> Canonical timeouts<P>
281 <LI> Dependency timeouts
282 </UL>
283 </ul>
284 </center>
285 </table></center>
286 <br>
288 <P><hr width="75%"><P> <!-- intra-section separator -->
290 <center><table cellpadding=1 border=0 cellspacing=4>
291 <tr><td align=center>
292 <h3>Real-Time Event Service Internals</h3>
293 <BR>
294 <tr><td>
295 <center><IMG SRC="http://www.cs.wustl.edu/~schmidt/gifs/ec_dispatching.gif"></center>
296 </table></center>
297 <br>
299 <P><hr width="75%"><P> <!-- intra-section separator -->
301 <center><table cellpadding=1 border=0 cellspacing=4>
302 <h3>Characteristics of Real-Time Push Event Service Participants</h3>
304 <tr><td>
305 Two major roles are played by the participants in a real-time push event
306 service.<P>
308 <tr><td>
309 The first role is that of an event consumer, which receives events from the
310 event channel. A consumer specifies the type and/or source id for each event
311 it is interested in receiving.<P>
313 In hard real-time applications, a consumer must also specify RT_Info data for
314 each event it is interested in receiving, and any other events on which that
315 event depends. The RT_Info structure resides in the Scheduler, and is
316 accessed through the scheduler interface. A unique handle is returned to the
317 consumer when an RT_Info is created, which can then be used to set the
318 information in the RT_Info. An RT_Info handle may also be obtained via the
319 Scheduler's lookup method.<P>
321 <tr><td>
322 The second role is that of an event supplier, which generates events and
323 passes them into the event channel. A supplier must specify its source id,
324 and the type of each event it will generate.
326 <tr><td>
327 In hard real-time applications, a supplier must also specify RT_Info data for
328 the events it will generate. In particular, it must specify the maximum rate
329 at which it will generate each event. This information is used by a real-time
330 scheduler to assign appropriate dispatch priorities.<P>
332 <tr><td>
333 Note that the event channel may also be configured to use a null scheduling service. This will
334 cause all operations to be dispatched at the same priority, and will not require the application
335 to specify worst case execution times, periods, etc.
337 <tr><td>
338 The consumer and supplier roles may be combined, as illustrated in the tables below. There are
339 two main cases in which the roles are combined: a passive one termed Consumer/Supplier which
340 borrows a thread of execution to produce events, and an active one termed Supplier/Consumer
341 which produces events in its own thread. Both consume events and produce events.<P>
342 </table></center>
344 <br>
345 <br>
346 <center><table cellpadding=4 border=1 cellspacing=4>
347 <h4>EC Roles and Specified RT_Info Contents</h4>
349 <tr>
350 <th>EC Roles
351 <th>RT_Info Contents
352 <th>Domain Examples
353 </tr>
355 <tr>
356 <td> Consumer
357 <td> dependencies (and optionally, importance)
358 <td> Display, Exception & Maintenance Logs
359 </tr>
361 <tr>
362 <td> Consumer/Supplier
363 <td> dependencies (and optionally, importance)
364 <td> Navigation Component (NAV)
365 </tr>
367 <tr>
368 <td> Supplier/Consumer
369 <td> rate, dependencies (and optionally, importance)
370 <td> Kalman Filter
371 </tr>
373 <tr>
374 <td> Supplier
375 <td> rate
376 <td> Operator Control Panel, EC Reactor Threads
377 </tr>
379 </table></center>
380 <BR>
381 <BR>
384 <center><table cellpadding=1 border=1 cellspacing=4>
385 <h4>EC Roles and Scheduler Dependency Chain</h4>
387 <tr>
388 <th> EC Roles
389 <th> Scheduler Dependency Chain
390 </tr>
392 <tr>
393 <td> Pure Consumer
394 <td> root node
395 </tr>
397 <tr>
398 <td> Consumer/Supplier
399 <td> internal node
400 </tr>
402 <tr>
403 <td> Supplier/Consumer
404 <td> internal node
405 </tr>
407 <tr>
408 <td> Pure Supplier
409 <td> leaf node
410 </tr>
412 </table></center>
413 <BR>
414 <BR>
416 <center><table cellpadding=1 border=1 cellspacing=4>
417 <h4>EC Roles, Threading, and CORBA Roles</h4>
419 <tr>
420 <th> EC Roles
421 <th> Activity
422 <th> Thread Behavior
423 <th> CORBA Roles
424 </tr>
426 <tr>
427 <td> Pure Consumer
428 <td> Passive
429 <td> Threads optional, "internal", wait for an event to occur
430 <td> Servant
431 </tr>
433 <tr>
434 <td> Consumer/Supplier
435 <td> Passive
436 <td> Threads optional, "internal", wait for an event to occur
437 <td> Client and/or Servant
438 </tr>
440 <tr>
441 <td> Supplier/Consumer
442 <td> Active
443 <td> Threads required and visible to EC: consume events and actively produce other events
444 <td> Client and/or Servant
445 </tr>
447 <tr>
448 <td> Pure Supplier
449 <td> Active
450 <td> Threads required and visible to EC: actively produce events
451 <td> Client
452 </tr>
453 </table></center>
455 <P><hr width="75%"><P> <!-- intra-section separator -->
457 <center><table cellpadding=1 border=0 cellspacing=4>
458 <tr><td>
459 <center><IMG SRC="http://www.cs.wustl.edu/~cdgill/ec_roles.GIF"></center>
460 </table></center>
462 <P><hr width="75%"><P> <!-- intra-section separator -->
464 <center><table cellpadding=1 border=0 cellspacing=4>
465 <tr><td>
466 <center><IMG SRC="http://www.cs.wustl.edu/~cdgill/ec_roles2.GIF"></center>
467 </table></center>
469 <P><hr width="75%"><P> <!-- intra-section separator -->
471 <center><table cellpadding=1 border=0 cellspacing=4>
472 <tr><td>
473 <center><IMG SRC="http://www.cs.wustl.edu/~cdgill/ec_backbone.GIF"></center>
474 </table></center>
476 <P><hr width="75%"><P> <!-- intra-section separator -->
478 <center><table cellpadding=1 border=0 cellspacing=4>
479 <tr><td>
480 <center><IMG SRC="http://www.cs.wustl.edu/~cdgill/distributed_ec_roles.GIF"></center>
481 </table></center>
483 <P><hr width="75%"><P> <!-- intra-section separator -->
485 <center><table cellpadding=1 border=0 cellspacing=4>
486 <tr><td>
487 <center><IMG SRC="http://www.cs.wustl.edu/~cdgill/ec_orb_view.GIF"></center>
488 </table></center>
490 <P><HR><P>
491 <!-- ************************************************************ -->
493 <center><table cellpadding=1 border=0 cellspacing=4>
494 <tr><td>
495 <center><h2><a name="Section4">Developing Consumers</a></h2></center>
496 <br>
497 <ul>
498 <li> <a href="events_tutorial.html#Section4_1">Providing QoS Information</a>
499 <li> <a href="events_tutorial.html#Section4_2">Connecting Consumers to the Event Channel</a>
500 <li> <a href="events_tutorial.html#Section4_3">Receiving Events</a>
501 <li> <a href="events_tutorial.html#Section4_4">Disconnecting Consumers from the Event Channel</a>
502 </ul>
503 </table></center>
505 <P><hr width="75%"><P> <!-- intra-section separator -->
506 <center><table cellpadding=1 border=0 cellspacing=4>
507 <center><h3><a name="Section4_1">Providing QoS Information</a><h3></center><p>
509 <tr><td>
510 The following steps are only necessary for applications that make use of the
511 Event Service's hard real-time features. Applications that do not need these
512 features and are configured with a null scheduler may skip the following
513 operations on the scheduling server.
515 <tr><td>
516 For each operation, a Consumer should provide the worst case, expected, and
517 cached execution time for that operation. It must also specify criticality and
518 importance values for each operation. A real-time scheduler uses this information
519 to order dispatches within a set of operations whose dependencies have been met.
521 <tr><td>
522 If it is a Consumer/Supplier (one which consumes an event and passively generates
523 one or more events from the thread in which it was called, as illustrated in the
524 tables above), it must provide dependencies on one or more other events to the
525 scheduler.
527 <tr><td>
528 If it is a Supplier/Consumer (one which consumes an event and actively generates
529 one or more events from its own thread, as illustrated in the tables above), it
530 must also specify the rate at which it will generate the new events by passing a
531 positive value in the period argument to the scheduler set method. It may also
532 indicate a positive number of threads in which the dispatch will be made. If the
533 number of threads given is zero, but a period is specified, the number of threads
534 defaults to 1.
536 </table>
537 </center>
540 <center><table cellpadding=1 border=0 cellspacing=4>
542 <tr><td>
543 <pre>
545 // Obtain a reference to the scheduler server.
546 RtecScheduler::Scheduler_ptr server =
547 ACE_Scheduler_Factory::server ();
549 // Create new RT_Info descriptors for three events.
551 RtecScheduler::handle_t handle1 =
552 server->create ("event_1"); // Name of entry point
554 RtecScheduler::handle_t handle2 =
555 server->create ("event_2"); // Name of entry point
557 RtecScheduler::handle_t handle3 =
558 server->create ("event_3"); // Name of entry point
561 // Register as a consumer/supplier: act as a supplier of event_1 but with
562 // a consumer dependency on event_3. Therefore, the actual period and
563 // number of threads for event_1 depends on the characteristics of event_3.
564 server->set (handle1, // RT_Info handle
565 RtecScheduler::HIGH_CRITICALITY, // Criticality
566 500, // Worst case time (in 100 nanosecs)
567 500, // Typical time (in 100 nanosecs)
568 500, // Cached time (in 100 nanosecs)
569 0, // Period - will depend on event_3
570 RtecScheduler::LOW_IMPORTANCE, // Importance
571 0, // Quantum (unused)
572 0, // Threads - will depend on event_3
573 RtecScheduler::OPERATION); // Info type
575 // Register as a producer of event_2.
576 server->set (handle2, // RT_Info handle
577 RtecScheduler::HIGH_CRITICALITY, // Criticality
578 500, // Worst case time (in 100 nanosecs)
579 500, // Typical time (in 100 nanosecs)
580 500, // Cached time (in 100 nanosecs)
581 50000 * 10, // Period in 100 nsec (= 20 Hz)
582 RtecScheduler::LOW_IMPORTANCE, // Importance
583 0, // Quantum (unused)
584 1, // Threads
585 RtecScheduler::OPERATION); // Info type
587 // Register as a consumer of event_3.
588 server->set (handle3, // RT_Info handle
589 RtecScheduler::HIGH_CRITICALITY, // Criticality
590 500, // Worst case time (in 100 nanosecs)
591 500, // Typical time (in 100 nanosecs)
592 500, // Cached time (in 100 nanosecs)
593 0, // Period - will depend on supplier
594 RtecScheduler::LOW_IMPORTANCE, // Importance
595 0, // Quantum (unused)
596 0, // Threads - will depend on supplier
597 RtecScheduler::OPERATION); // Info type
600 // Establish a dependency of event_1 on event_3.
601 server->add_dependency (handle1, // handle that depends
602 handle3, // handle that is depended on
603 1); // number of calls per event occurrence
605 </pre>
606 </table>
607 </center>
609 <P><hr width="75%"><P> <!-- intra-section separator -->
611 <center><table cellpadding=1 border=0 cellspacing=4>
612 <h3>
613 <a name="Section4_2">Connecting Consumers to the Event Channel</a>
614 </h3>
616 <tr><td>
617 The following code is derived from the EC_Throughput consumer code, which can be
618 found in TAO in the file:
619 <A HREF="../orbsvcs/tests/EC_Throughput/ECT_Consumer.cpp">
620 $TAO_ROOT/orbsvcs/tests/EC_Throughput/ECT_Consumer.cpp</a>
622 <tr><td>
623 <pre>
625 void
626 Test_Consumer::connect (const char* name,
627 int event_a, int event_b,
628 RtecEventChannelAdmin::EventChannel_ptr ec,
629 CORBA::Environment& _env)
632 // Register operations with the scheduling service. The following steps are
633 // only necessary for applications that make use of the Event Service's hard
634 // real-time features. Applications that do not need these features and are
635 // configured with a null scheduler may skip the following operations on the
636 // scheduling server.
638 // Obtain a reference to the scheduler from the ACE_Scheduler_Factory.
639 RtecScheduler::Scheduler_ptr server =
640 ACE_Scheduler_Factory::server ();
642 // Create a new RT_Info entry for the function identifier
643 // we were passed, and hang onto the handle to the RT_Info.
644 RtecScheduler::handle_t rt_info =
645 server->create (name, _env);
646 TAO_CHECK_ENV_RETURN_VOID(_env);
648 // Set the attributes for the RT_Info.
649 ACE_Time_Value tv (0, 2000);
650 TimeBase::TimeT time;
651 ORBSVCS_Time::Time_Value_to_TimeT (time, tv);
652 server->set (rt_info,
653 RtecScheduler::VERY_HIGH_CRITICALITY,
654 time, time, time,
656 RtecScheduler::VERY_LOW_IMPORTANCE,
657 time,
659 RtecScheduler::OPERATION,
660 _env);
661 TAO_CHECK_ENV_RETURN_VOID(_env);
663 // Specify a disjunctive dependency on the arrival of event_a, the arrival
664 // of event b, OR the arrival of an event service shutdown event. Note that
665 // the same RT_Info is used for each event. This can be used to simplify
666 // code in applications using a null scheduler, or to consolidate events
667 // with identical characteristics in hard real-time applications.
668 ACE_ConsumerQOS_Factory qos;
669 qos.start_disjunction_group ();
670 qos.insert_type (ACE_ES_EVENT_SHUTDOWN, rt_info);
671 qos.insert_type (event_a, rt_info);
672 qos.insert_type (event_b, rt_info);
674 // = Connect as a consumer.
676 // Obtain a reference to the consumer administration object.
677 RtecEventChannelAdmin::ConsumerAdmin_var consumer_admin =
678 ec->for_consumers (_env);
679 TAO_CHECK_ENV_RETURN_VOID(_env);
681 // Obtain a reference to the push supplier proxy.
682 this->supplier_proxy_ =
683 consumer_admin->obtain_push_supplier (_env);
684 TAO_CHECK_ENV_RETURN_VOID(_env);
686 // Obtain a reference to this object.
687 RtecEventComm::PushConsumer_var objref = this->_this (_env);
688 TAO_CHECK_ENV_RETURN_VOID(_env);
690 // Connect as a consumer.
691 this->supplier_proxy_->connect_push_consumer (objref.in (),
692 qos.get_ConsumerQOS (),
693 _env);
694 TAO_CHECK_ENV_RETURN_VOID(_env);
697 </pre>
699 <tr><td>
700 The following code is derived from the EC_Throughput consumer driver code, which
701 can be found in TAO in the file:
702 <A HREF="../orbsvcs/tests/EC_Throughput/ECT_Consumer_Driver.cpp">
703 $TAO_ROOT/orbsvcs/tests/EC_Throughput/ECT_Consumer_Driver.cpp</a>
705 <tr><td>
706 <pre>
709 ECT_Consumer_Driver::run (int argc, char* argv[])
711 // argc/argv are used to initialize the ORB and the options
712 // for this particular test. Other applications may hard-code
713 // the ORB options, obtain them from another source, etc.
715 TAO_TRY
717 // The use of TAO_TRY macros isolate us from the differences
718 // between platforms with and without native C++ exceptions.
719 // This is work in progress and may change in the future!
721 // Below is some boiler plate code to initialize the ORB and
722 // the POA. Notice that applications that connect to the Event
723 // Channel play the server role in some instances, because
724 // they receive push() requests (as Consumers) or
725 // disconnect_push_supplier() requests (as Suppliers).
727 // Initialize the ORB reference.
728 this->orb_ =
729 CORBA::ORB_init (argc, argv, "");
731 // Initialize the root POA reference.
732 CORBA::Object_var poa_object =
733 this->orb_->resolve_initial_references("RootPOA");
734 if (CORBA::is_nil (poa_object.in ()))
735 ACE_ERROR_RETURN ((LM_ERROR,
736 " (%P|%t) Unable to initialize the POA.\n"),
739 // Obtain the narrowed root POA reference.
740 PortableServer::POA_var root_poa =
741 PortableServer::POA::_narrow (poa_object.in ());
743 // Obtain a reference to the POA manager.
744 PortableServer::POAManager_var poa_manager =
745 root_poa->the_POAManager ();
747 // Now some boiler plate code to obtain a reference to the
748 // naming service.....
750 // Resolve a reference to the naming service.
751 CORBA::Object_var naming_obj =
752 this->orb_->resolve_initial_references ("NameService");
753 if (CORBA::is_nil (naming_obj.in ()))
754 ACE_ERROR_RETURN ((LM_ERROR,
755 " (%P|%t) Unable to get the Naming Service.\n"),
758 // Narrow the naming service reference.
759 CosNaming::NamingContext_var naming_context =
760 CosNaming::NamingContext::_narrow (naming_obj.in ());
762 // Use the Naming Service to locate the Scheduling Service and
763 // use the Scheduler_Factory to keep a global pointer to the
764 // latter.
766 // Initialize the scheduler factory to operate in configuration mode.
767 if (ACE_Scheduler_Factory::use_config (naming_context.in ()) == -1)
768 return -1;
770 // Use the Naming Service to locate the Event Service....
772 // Set up the event service lookup name.
773 CosNaming::Name name (1);
774 name.length (1);
775 name[0].id = CORBA::string_dup ("EventService");
777 // Resolve a reference to the event service.
778 CORBA::Object_var ec_obj =
779 naming_context->resolve (name);
781 // Narrow the reference to the event service.
782 RtecEventChannelAdmin::EventChannel_var channel;
783 if (CORBA::is_nil (ec_obj.in ()))
784 channel = RtecEventChannelAdmin::EventChannel::_nil ();
785 else
786 channel = RtecEventChannelAdmin::EventChannel::_narrow (ec_obj.in ());
788 // Activate the POA so we can start receiving requests...
790 // Activate the POA manager.
791 poa_manager->activate ();
793 // Connect consumers to the event service.
794 this->connect_consumers (channel.in ());
796 ACE_DEBUG ((LM_DEBUG, "connected consumer(s)\n"));
797 ACE_DEBUG ((LM_DEBUG, "running the test\n"));
799 // Run the event loop.
800 if (this->orb_->run () == -1)
801 ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "orb->run"), -1);
802 ACE_DEBUG ((LM_DEBUG, "event loop finished\n"));
804 this->dump_results ();
806 // Disconnect consumers from the event service.
807 this->disconnect_consumers ();
809 // Destroy the event service.
810 channel->destroy ();
812 catch (const CORBA::SystemException& sys_ex)
814 sys_ex.print_exception ("SYS_EX");
816 catch (const CORBA::Exception& any_ex)
818 any_ex.print_exception ("NON SYS EX");
820 return 0;
823 </pre>
824 </table>
825 </center>
827 <P><hr width="75%"><P> <!-- intra-section separator -->
829 <!-- Must be after suppliers connect. -->
831 <center><table cellpadding=1 border=0 cellspacing=4>
832 <h3><a name="Section4_3">Receiving Events</a></h3><p>
834 <tr><td>
835 The following code is derived from the EC_Throughput consumer code, which
836 can be found in TAO in the file:
837 <A HREF="../orbsvcs/tests/EC_Throughput/ECT_Consumer.cpp">
838 $TAO_ROOT/orbsvcs/tests/EC_Throughput/ECT_Consumer.cpp</a>
840 <tr><td>
841 <pre>
843 void
844 Test_Consumer::push (const RtecEventComm::EventSet& events,
845 CORBA::Environment &_env)
847 // Make sure at least one event was pushed.
848 if (events.length () == 0)
850 // ACE_DEBUG ((LM_DEBUG, "no events\n"));
851 return;
854 // Make sure only one thread has access.
855 ACE_GUARD (TAO_SYNCH_MUTEX, ace_mon, this->lock_);
857 // We start the timer as soon as we receive the first event.
858 if (this->recv_count_ == 0)
859 this->timer_.start ();
861 // Update the count of received events.
862 this->recv_count_ += events.length ();
864 if (TAO_debug_level > 0
865 && this->recv_count_ % 1000 == 0)
867 ACE_DEBUG ((LM_DEBUG,
868 "ECT_Consumer (%P|%t): %d events received\n",
869 this->recv_count_));
872 // Loop through the events, looking for shutdown events.
873 for (u_int i = 0; i < events.length (); ++i)
875 if (events[i].header.type == ACE_ES_EVENT_SHUTDOWN)
877 this->shutdown_count_++;
878 if (this->shutdown_count_ >= this->n_suppliers_)
880 // We stop the timer as soon as we realize it is time to
881 // do so.
882 this->timer_.stop ();
883 this->driver_->shutdown_consumer (this->cookie_, _env);
889 </pre>
890 </table>
891 </center>
893 <P><hr width="75%"><P> <!-- intra-section separator -->
895 <center><table cellpadding=1 border=0 cellspacing=4>
896 <h3>
897 <a name="Section4_4">Disconnecting Consumers from the Event Channel</a>
898 </h3>
900 <tr><td>
901 The following code is derived from the EC_Throughput consumer code, which can be
902 found in TAO in the file:
903 <A HREF="../orbsvcs/tests/EC_Throughput/ECT_Consumer.cpp">
904 $TAO_ROOT/orbsvcs/tests/EC_Throughput/ECT_Consumer.cpp</a>
906 <tr><td>
907 <pre>
909 void
910 Test_Consumer::disconnect (CORBA::Environment &_env)
912 // Make sure the supplier proxy reference is valid.
913 if (CORBA::is_nil (this->supplier_proxy_.in ()))
914 return;
916 // Disconnect from further communication with the push
917 // supplier(s). Each consumer is represented by a unique
918 // ACE_ES_ConsumerModule instance. Which connection to
919 // disconnect is determined by the instance for the consumer.
920 this->supplier_proxy_->disconnect_push_supplier (_env);
921 TAO_CHECK_ENV_RETURN_VOID(_env);
923 // Mark the supplier proxy reference invalid.
924 this->supplier_proxy_ =
925 RtecEventChannelAdmin::ProxyPushSupplier::_nil ();
927 // We want to stop processing events for this consumer. Above,
928 // we disconnected the consumer from the Event Channel, so no
929 // more events will be sent, but we could have some events in
930 // transit.
932 // Without a flushing protocol we need to deactivate the
933 // servant to stop accepting push () requests for any
934 // incoming events.
936 // Deactivate the servant
937 PortableServer::POA_var poa =
938 this->_default_POA (_env);
939 TAO_CHECK_ENV_RETURN_VOID (_env);
940 PortableServer::ObjectId_var id =
941 poa->servant_to_id (this, _env);
942 TAO_CHECK_ENV_RETURN_VOID (_env);
943 poa->deactivate_object (id.in (), _env);
944 TAO_CHECK_ENV_RETURN_VOID (_env);
947 </pre>
948 </table>
949 </center>
952 <P><HR><P>
953 <!-- ************************************************************ -->
955 <center><table cellpadding=1 border=0 cellspacing=4>
956 <td>
957 <h2><a name="Section5">Developing Suppliers</a></h2>
959 <ul>
960 <li> <a href="events_tutorial.html#Section5_1">Providing QoS Information</a>
961 <li> <a href="events_tutorial.html#Section5_2">Connecting Suppliers to the Event Channel</a>
962 <li> <a href="events_tutorial.html#Section5_3">Generating Events</a>
963 <li> <a href="events_tutorial.html#Section5_4">Disconnecting Suppliers from the Event Channel</a>
964 </ul>
965 </table>
966 </center>
969 <center><table cellpadding=1 border=0 cellspacing=4>
970 <h3><a name="Section5_1">Providing QoS Information</a></h3><p>
971 <tr><td>
972 In applications that use hard real-time scheduling, a Supplier should provide
973 the worst case, expected, and cached execution time for each operation on the
974 supplier side. Even if these values are small and highly deterministic, it is
975 generally better to specify them in the supplier's RT_Info rather than folding
976 them into the RT_Info of each consumer.
978 <tr><td>
979 Such a supplier must also specify criticality and importance values, a period,
980 and the number of threads for each operation. A real-time scheduler propagates
981 this information to consumer RT_Infos along the graph of dependencies. The
982 scheduler then uses the propagated information to order dispatches within a
983 set of operations whose dependencies have been met.
985 <tr><td>
986 The Event Service matches supplier publications with consumer subscriptions to
987 provide efficient event filtering. Providing incorrect publications or
988 subscriptions will result in missed events. The Event Service also uses the
989 subscription information to create additional dependencies between registered
990 RT_Infos. Thus, providing correct supplier publication and consumer
991 subscription information is also critical for correct scheduling in hard
992 real-time applications.
995 <tr><td>
996 As noted before in the discussion of consumers, the following steps are only
997 necessary for applications that make use of the Event Service's hard real-time
998 features. Applications that do not need these features and are configured
999 with a null scheduler may skip the following operations on the scheduling
1000 server.
1002 </table>
1003 </center>
1005 <center><table cellpadding=1 border=0 cellspacing=4>
1007 <tr><td>
1008 <pre>
1010 // Obtain a reference to the scheduler server.
1011 RtecScheduler::Scheduler_ptr server =
1012 ACE_Scheduler_Factory::server ();
1014 // Create new RT_Info descriptors for two events.
1016 RtecScheduler::handle_t handle0 =
1017 server->create ("event_0"); // Name of entry point
1019 RtecScheduler::handle_t handle1 =
1020 server->create ("event_1"); // Name of entry point
1022 // Register as a producer of event_0.
1023 server->set (handle0, // RT_Info handle
1024 RtecScheduler::HIGH_CRITICALITY, // Criticality
1025 10, // Worst case time (in 100 nanosecs)
1026 10, // Typical time (in 100 nanosecs)
1027 10, // Cached time (in 100 nanosecs)
1028 50000 * 10, // Period in 100 nanosecs (= 20 Hz)
1029 RtecScheduler::LOW_IMPORTANCE, // Importance
1030 0, // Quantum (unused)
1031 1, // Threads
1032 RtecScheduler::OPERATION); // Info type
1034 // Register as a producer of event_1.
1035 server->set (handle1, // RT_Info handle
1036 RtecScheduler::HIGH_CRITICALITY, // Criticality
1037 10, // Worst case time (in 100 nanosecs)
1038 10, // Typical time (in 100 nanosecs)
1039 10, // Cached time (in 100 nanosecs)
1040 50000 * 10, // Period in 100 nanosecs (= 20 Hz)
1041 RtecScheduler::LOW_IMPORTANCE, // Importance
1042 0, // Quantum (unused)
1043 1, // Threads
1044 RtecScheduler::OPERATION); // Info type
1046 </pre>
1047 </table>
1048 </center>
1050 <P><hr width="75%"><P> <!-- intra-section separator -->
1052 <center><table cellpadding=1 border=0 cellspacing=4>
1053 <td>
1054 <h3><a name="Section5_2">Connecting Suppliers to Event Channel</a></h3><P>
1057 <tr><td>
1058 The following code is derived from the EC_Throughput supplier code, which
1059 can be found in TAO in the file:
1060 <A HREF="../orbsvcs/tests/EC_Throughput/ECT_Supplier.cpp">
1061 $TAO_ROOT/orbsvcs/tests/EC_Throughput/ECT_Supplier.cpp</a>
1064 <tr><td>
1065 <pre>
1067 void
1068 Test_Supplier::connect (const char* name,
1069 int burst_count,
1070 int burst_size,
1071 int event_size,
1072 int burst_pause,
1073 int event_a,
1074 int event_b,
1075 RtecEventChannelAdmin::EventChannel_ptr ec,
1076 CORBA::Environment &_env)
1078 // Some application-specific setup code.
1080 // Store the passed parameters in the object.
1081 this->burst_count_ = burst_count;
1082 this->burst_size_ = burst_size;
1083 this->event_size_ = event_size;
1084 this->burst_pause_ = burst_pause;
1085 this->event_a_ = event_a;
1086 this->event_b_ = event_b;
1088 // Register operations with the scheduling service. The following steps are
1089 // only necessary for applications that make use of the Event Service's hard
1090 // real-time features. Applications that do not need these features and are
1091 // configured with a null scheduler may skip the following operations on the
1092 // scheduling server.
1094 // Obtain a reference to the scheduling service.
1095 RtecScheduler::Scheduler_ptr server =
1096 ACE_Scheduler_Factory::server ();
1098 // Create an RT_Info descriptor for the passed operation name.
1099 RtecScheduler::handle_t rt_info =
1100 server->create (name, _env);
1101 TAO_CHECK_ENV_RETURN_VOID (_env);
1103 // Calculate the period at which to supply events.
1104 ACE_Time_Value tv (0, burst_pause);
1105 RtecScheduler::Period_t rate = tv.usec () * 10;
1107 // Set the information in the RT_Info descriptor.
1108 tv.set (0, 2000);
1109 TimeBase::TimeT time;
1110 ORBSVCS_Time::Time_Value_to_TimeT (time, tv);
1111 server->set (rt_info,
1112 RtecScheduler::VERY_HIGH_CRITICALITY,
1113 time, time, time,
1114 rate,
1115 RtecScheduler::VERY_LOW_IMPORTANCE,
1116 time,
1118 RtecScheduler::OPERATION,
1119 _env);
1120 TAO_CHECK_ENV_RETURN_VOID (_env);
1122 // Now, create a supplier id, and publish the events
1123 // that will be supplied under this id.
1125 // Create a supplier id from the passed name
1126 this->supplier_id_ = ACE::crc32 (name);
1127 ACE_DEBUG ((LM_DEBUG, "ID for <%s> is %04.4x\n", name,
1128 this->supplier_id_));
1130 // Publish the events the supplier provides.
1131 ACE_SupplierQOS_Factory qos;
1132 qos.insert (this->supplier_id_,
1133 event_a,
1134 rt_info, 1);
1135 qos.insert (this->supplier_id_,
1136 event_b,
1137 rt_info, 1);
1138 qos.insert (this->supplier_id_,
1139 ACE_ES_EVENT_SHUTDOWN,
1140 rt_info, 1);
1142 // And finally, some boiler plate code to connect a supplier
1143 // to the Event Service. This is where the connection is
1144 // actually made.
1146 // Obtain a reference to the supplier administration object.
1147 RtecEventChannelAdmin::SupplierAdmin_var supplier_admin =
1148 ec->for_suppliers (_env);
1149 TAO_CHECK_ENV_RETURN_VOID (_env);
1151 // Obtain a reference to the consumer proxy object.
1152 this->consumer_proxy_ =
1153 supplier_admin->obtain_push_consumer (_env);
1154 TAO_CHECK_ENV_RETURN_VOID (_env);
1156 // Obtain a reference to this supplier object.
1157 RtecEventComm::PushSupplier_var objref =
1158 this->supplier_._this (_env);
1159 TAO_CHECK_ENV_RETURN_VOID (_env);
1161 // Connect as a supplier of the published events.
1162 this->consumer_proxy_->connect_push_supplier (objref.in (),
1163 qos.get_SupplierQOS (),
1164 _env);
1165 TAO_CHECK_ENV_RETURN_VOID (_env);
1168 </pre>
1171 <tr><td>
1172 The following code is derived from the EC_Throughput supplier driver code, which
1173 can be found in TAO in the file:
1174 <A HREF="../orbsvcs/tests/EC_Throughput/ECT_Supplier_Driver.cpp">
1175 $TAO_ROOT/orbsvcs/tests/EC_Throughput/ECT_Supplier_Driver.cpp</a>
1177 <tr><td>
1178 <pre>
1181 ECT_Supplier_Driver::run (int argc, char* argv[])
1183 // argc/argv are used to initialize the ORB and the options
1184 // for this particular test. Other applications may hard-code
1185 // the ORB options, obtain them from another source, etc.
1187 TAO_TRY
1189 // The use of TAO_TRY macros isolate us from the differences
1190 // between platforms with and without native C++ exceptions.
1191 // This is work in progress and may change in the future!
1193 // Below is some boiler plate code to initialize the ORB and
1194 // the POA. Notice that applications that connect to the Event
1195 // Channel play the server role in some instances, because
1196 // they receive push() requests (as Consumers) or
1197 // disconnect_push_supplier() requests (as Suppliers).
1199 // Initialize the ORB reference.
1200 CORBA::ORB_var orb =
1201 CORBA::ORB_init (argc, argv, "");
1203 // Initialize the root POA reference.
1204 CORBA::Object_var poa_object =
1205 orb->resolve_initial_references("RootPOA");
1206 if (CORBA::is_nil (poa_object.in ()))
1207 ACE_ERROR_RETURN ((LM_ERROR,
1208 " (%P|%t) Unable to initialize the POA.\n"),
1211 // Obtain the narrowed root POA reference.
1212 PortableServer::POA_var root_poa =
1213 PortableServer::POA::_narrow (poa_object.in ());
1215 // Obtain a reference to the POA manager.
1216 PortableServer::POAManager_var poa_manager =
1217 root_poa->the_POAManager ();
1219 // Now some boiler plate code to obtain a reference to the
1220 // naming service.....
1222 // Resolve a reference to the naming service.
1223 CORBA::Object_var naming_obj =
1224 orb->resolve_initial_references ("NameService");
1225 if (CORBA::is_nil (naming_obj.in ()))
1226 ACE_ERROR_RETURN ((LM_ERROR,
1227 " (%P|%t) Unable to get the Naming Service.\n"),
1230 // Narrow the naming service reference.
1231 CosNaming::NamingContext_var naming_context =
1232 CosNaming::NamingContext::_narrow (naming_obj.in ());
1234 // Use the Naming Service to locate the Scheduling Service and
1235 // use the Scheduler_Factory to keep a global pointer to the
1236 // latter.
1238 // Initialize the scheduler factory to operate in configuration mode.
1239 if (ACE_Scheduler_Factory::use_config (naming_context.in ()) == -1)
1240 return -1;
1242 // Use the Naming Service to locate the Event Service....
1244 // Set up the event service lookup name.
1245 CosNaming::Name name (1);
1246 name.length (1);
1247 name[0].id = CORBA::string_dup ("EventService");
1249 // Resolve a reference to the event service.
1250 CORBA::Object_var ec_obj =
1251 naming_context->resolve (name);
1253 // Narrow the reference to the event service.
1254 RtecEventChannelAdmin::EventChannel_var channel;
1255 if (CORBA::is_nil (ec_obj.in ()))
1256 channel = RtecEventChannelAdmin::EventChannel::_nil ();
1257 else
1258 channel = RtecEventChannelAdmin::EventChannel::_narrow (ec_obj.in ());
1260 // Activate the POA so we can start receiving requests...
1262 // Activate the POA manager.
1263 poa_manager->activate ();
1265 // Connect suppliers to the event service.
1266 this->connect_suppliers (channel.in ());
1268 ACE_DEBUG ((LM_DEBUG, "connected supplier(s)\n"));
1270 // Activate the supplier objects
1271 this->activate_suppliers ();
1273 ACE_DEBUG ((LM_DEBUG, "suppliers are active\n"));
1275 // Wait for the supplier threads.
1276 if (ACE_Thread_Manager::instance ()->wait () == -1)
1278 ACE_ERROR ((LM_ERROR, "Thread_Manager wait failed\n"));
1279 return 1;
1282 ACE_DEBUG ((LM_DEBUG, "suppliers finished\n"));
1284 this->dump_results ();
1286 // Disconnect suppliers from the event service.
1287 this->disconnect_suppliers ();
1289 catch (const CORBA::SystemException& sys_ex)
1291 sys_ex.print_exception ("SYS_EX");
1293 catch (const CORBA::Exception& any_ex)
1295 any_ex.print_exception ("NON SYS EX");
1297 return 0;
1300 </pre>
1301 </table>
1302 </center>
1304 <P><hr width="75%"><P> <!-- intra-section separator -->
1306 <center><table cellpadding=1 border=0 cellspacing=4>
1307 <h3><a name="Section5_3">Generating Events</a></h3><P><p>
1309 <tr><td>
1310 The following code is derived from the EC_Throughput supplier code, which
1311 can be found in TAO in the file:
1312 <A HREF="../orbsvcs/tests/EC_Throughput/ECT_Supplier.cpp">
1313 $TAO_ROOT/orbsvcs/tests/EC_Throughput/ECT_Supplier.cpp</a>
1315 <tr><td>
1316 <pre>
1319 Test_Supplier::svc ()
1321 TAO_TRY
1323 // First, a bunch of code that is specific to this test.
1325 // Set pause (sleep) value between message bursts.
1326 ACE_Time_Value tv (0, this->burst_pause_);
1328 // Set up message block for event data.
1329 ACE_Message_Block mb (this->event_size_);
1330 mb.wr_ptr (this->event_size_);
1332 // Create an event set for one event, initialize event header.
1333 RtecEventComm::EventSet event (1);
1334 event.length (1);
1335 event[0].header.source = this->supplier_id ();
1336 event[0].header.ttl = 1;
1338 // Set up time stamps in event header. This is for performance
1339 // measurements, so this step can be omitted at will.
1340 ACE_hrtime_t t = ACE_OS::gethrtime ();
1341 ORBSVCS_Time::hrtime_to_TimeT (event[0].header.creation_time, t);
1342 event[0].header.ec_recv_time = ORBSVCS_Time::zero;
1343 event[0].header.ec_send_time = ORBSVCS_Time::zero;
1345 // Initialize data fields in event.
1346 event[0].data.x = 0;
1347 event[0].data.y = 0;
1349 // We use replace to minimize the copies. This should result
1350 // in just one memory allocation;
1351 event[0].data.payload.replace (this->event_size_,
1352 &mb);
1354 // This is where the events are actually pushed into
1355 // the event channel. The test pushes bursts of events,
1356 // pausing a specified interval between bursts.
1358 // Start the timer, and begin pushing events.
1359 this->timer_.start ();
1360 for (int i = 0; i < this->burst_count_; ++i)
1362 // Send a burst of events.
1363 for (int j = 0; j < this->burst_size_; ++j)
1365 if (j % 2 == 0)
1366 event[0].header.type = this->event_a_;
1367 else
1368 event[0].header.type = this->event_b_;
1370 // ACE_DEBUG ((LM_DEBUG, "(%t) supplier push event\n"));
1371 this->consumer_proxy ()->push (event);
1374 // Sleep until it's time to send the next burst.
1375 ACE_OS::sleep (tv);
1378 // Send a "magic" type of event to inform the consumer that we are
1379 // not sending anything else...
1381 // Send one event shutdown from each supplier
1382 event[0].header.type = ACE_ES_EVENT_SHUTDOWN;
1383 this->consumer_proxy ()->push(event);
1384 this->timer_.stop ();
1387 catch (CORBA::SystemException& sys_ex)
1389 sys_ex.print_exception ("SYS_EX");
1391 catch (CORBA::Exception& any_ex)
1393 any_ex.print_exception ("NON SYS EX");
1395 return 0;
1398 </pre>
1399 </table>
1400 </center>
1402 <P><hr width="75%"><P> <!-- intra-section separator -->
1404 <center><table cellpadding=1 border=0 cellspacing=4>
1405 <td>
1406 <h3><a name="Section5_4">Disconnecting Suppliers from the Event Channel</a></h3><P>
1409 <tr><td>
1410 The following code is derived from the EC_Throughput supplier code, which
1411 can be found in TAO in the file:
1412 <A HREF="../orbsvcs/tests/EC_Throughput/ECT_Supplier.cpp">
1413 $TAO_ROOT/orbsvcs/tests/EC_Throughput/ECT_Supplier.cpp</a>
1416 <tr><td>
1417 <pre>
1419 void
1420 Test_Supplier::disconnect (CORBA::Environment &_env)
1422 // Make sure the consumer proxy reference is valid.
1423 if (CORBA::is_nil (this->consumer_proxy_.in ()))
1424 return;
1426 // Disconnect communication with the push consumer(s).
1427 this->consumer_proxy_->disconnect_push_consumer (_env);
1428 TAO_CHECK_ENV_RETURN_VOID (_env);
1430 // Mark the consumer proxy reference invalid.
1431 this->consumer_proxy_ =
1432 RtecEventChannelAdmin::ProxyPushConsumer::_nil ();
1434 // We need to stop accepting disconnect_push_supplier () requests
1435 // for this supplier, before it is safe to destroy the supplier.
1436 // As required by the CORBA spec, you must explicitly deactivate
1437 // a servant before destroying it.
1439 // Deactivate the servant
1440 PortableServer::POA_var poa =
1441 this->supplier_._default_POA (_env);
1442 TAO_CHECK_ENV_RETURN_VOID (_env);
1443 PortableServer::ObjectId_var id =
1444 poa->servant_to_id (&this->supplier_, _env);
1445 TAO_CHECK_ENV_RETURN_VOID (_env);
1446 poa->deactivate_object (id.in (), _env);
1447 TAO_CHECK_ENV_RETURN_VOID (_env);
1448 RtecEventChannelAdmin::ProxyPushConsumer::_nil ();
1451 </pre>
1453 </table>
1454 </center>
1456 <P><HR><P>
1457 <!-- ************************************************************ -->
1459 <center><table cellpadding=1 border=0 cellspacing=4>
1460 <td>
1461 <h2><a name="Section6">Caring for your Event Channel</a></h2>
1464 <BR>
1466 The following code is derived from the Event_Service executable, which can be
1467 found in TAO in the file:
1468 <A HREF="../orbsvcs/Event_Service/Event_Service.cpp">
1469 $TAO_ROOT/orbsvcs/Event_Service/Event_Service.cpp</a>
1471 <tr><td>
1472 <pre>
1474 int main (int argc, char *argv[])
1476 TAO_TRY
1478 // argc/argv are used to initialize the ORB and the options
1479 // for the Event Service executable. Other applications may
1480 // hard code the ORB options, obtain them from another source, etc.
1482 // Again the boiler plate code for ORB and POA initialization.
1484 // Initialize ORB.
1485 CORBA::ORB_var orb =
1486 CORBA::ORB_init (argc, argv, "internet");
1488 if (parse_args (argc, argv) == -1)
1489 return 1;
1491 CORBA::Object_var poa_object =
1492 orb->resolve_initial_references("RootPOA");
1493 if (CORBA::is_nil (poa_object.in ()))
1494 ACE_ERROR_RETURN ((LM_ERROR,
1495 " (%P|%t) Unable to initialize the POA.\n"),
1498 PortableServer::POA_var root_poa =
1499 PortableServer::POA::_narrow (poa_object.in ());
1501 PortableServer::POAManager_var poa_manager =
1502 root_poa->the_POAManager ();
1504 CORBA::Object_var naming_obj =
1505 orb->resolve_initial_references ("NameService");
1506 if (CORBA::is_nil (naming_obj.in ()))
1507 ACE_ERROR_RETURN ((LM_ERROR,
1508 " (%P|%t) Unable to initialize the Naming Service.\n"),
1511 CosNaming::NamingContext_var naming_context =
1512 CosNaming::NamingContext::_narrow (naming_obj.in ());
1514 // Notice the use of unique_ptr<> to automagically manage the
1515 // destruction of the servant. When the unique_ptr goes out
1516 // of scope, its destructor is called, which in turn destroys
1517 // the servant.
1518 std::unique_ptr<POA_RtecScheduler::Scheduler> scheduler_impl;
1519 RtecScheduler::Scheduler_var scheduler;
1522 // Create a new servant to implement the Scheduling Service,
1523 // register it with the Naming Service, and use the
1524 // Scheduler_Factory to keep a global pointer to the new
1525 // Scheduling Service.
1527 // This is the name we (potentially) use to register the Scheduling
1528 // Service in the Naming Service.
1529 CosNaming::Name schedule_name (1);
1530 schedule_name.length (1);
1531 schedule_name[0].id = CORBA::string_dup ("ScheduleService");
1533 if (global_scheduler == 0)
1535 scheduler_impl =
1536 std::unique_ptr<POA_RtecScheduler::Scheduler>(new ACE_Config_Scheduler);
1537 if (scheduler_impl.get () == 0)
1538 return 1;
1539 scheduler = scheduler_impl->_this ();
1541 CORBA::String_var str =
1542 orb->object_to_string (scheduler.in ());
1543 ACE_DEBUG ((LM_DEBUG, "The (local) scheduler IOR is <%C>\n", str.in ()));
1545 // Register the servant with the Naming Context....
1546 naming_context->bind (schedule_name, scheduler.in ());
1549 ACE_Scheduler_Factory::use_config (naming_context.in ());
1551 // The Event Service can be configured to support priority based
1552 // dispatching (the "default_Module_Factory") or best effort (the
1553 // "Reactive_Module_Factory"). We pick the right module factory
1554 // according to the command line options processed above.
1556 TAO_Default_Module_Factory default_module_factory;
1557 TAO_Reactive_Module_Factory reactive_module_factory;
1559 TAO_Module_Factory* module_factory = &default_module_factory;
1560 if (reactive)
1561 module_factory = &reactive_module_factory;
1563 // Now, create a new event channel servant to implement the
1564 // Event Service, and register it with Naming Service.
1566 // Construct the event channel using the given module factory.
1567 ACE_EventChannel ec_impl (1,
1568 ACE_DEFAULT_EVENT_CHANNEL_TYPE,
1569 module_factory);
1571 // Obtain an object reference to the new channel.
1572 RtecEventChannelAdmin::EventChannel_var ec =
1573 ec_impl._this ();
1575 // Convert the EC object reference to a string.
1576 CORBA::String_var str =
1577 orb->object_to_string (ec.in ());
1579 // Output the EC object reference string (debug only).
1580 ACE_DEBUG ((LM_DEBUG, "The EC IOR is <%C>\n", str.in ()));
1582 // Register the EC with the Naming Service.
1583 CosNaming::Name channel_name (1);
1584 channel_name.length (1);
1585 channel_name[0].id = CORBA::string_dup (service_name);
1586 naming_context->bind (channel_name, ec.in ());
1588 // Activate the POA so we can start receiving requests...
1590 // Activate the POA manager.
1591 poa_manager->activate ();
1593 // Run the ORB event loop
1594 ACE_DEBUG ((LM_DEBUG, "%s; running event service\n", __FILE__));
1595 if (orb->run () == -1)
1596 ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "run"), 1);
1598 // Now the Event Service is finished. We could deactivate the
1599 // EC and SS here, but we don't need to, as the server is
1600 // going down anyway.
1603 // Remove the event service and the scheduling service from
1604 // the Naming Service.
1606 naming_context->unbind (channel_name);
1608 if (global_scheduler == 0)
1610 naming_context->unbind (schedule_name);
1614 catch (const CORBA::Exception& ex)
1616 ex.print_exception ("EC");
1619 return 0;
1622 </pre>
1623 </table>
1624 </center>
1626 <P><hr width="75%"><P> <!-- intra-section separator -->
1628 <P><HR><P>
1629 <!-- ************************************************************ -->
1631 <center><table cellpadding=1 border=0 cellspacing=4>
1632 <tr><td>
1633 <h2><a name="Section7">Sample Applications</a></h2>
1635 <tr><td>
1636 A number of sample applications are available in the directories under
1637 <a href="../orbsvcs/tests/">
1638 TAO's ORB Services tests</a>.
1640 <tr><td>
1641 In particular, much of the code shown in this tutorial was drawn from the
1642 <a href="../orbsvcs/tests/EC_Throughput/">
1643 EC_Throughput</a> test. This test exercises the Event Service and measures its
1644 throughput capabilities.
1646 <tr><td>
1647 A similar test,
1648 <a href="../orbsvcs/tests/Event_Latency/">
1649 Event_Latency</a>, measures the latency of events through the Event Service.
1651 <tr><td>
1653 <a href="../orbsvcs/tests/EC_Basic/">
1654 EC_Basic</a> test demonstrates the basic use the Event Service.
1656 <tr><td>
1658 <a href="../orbsvcs/tests/EC_Multiple/">
1659 EC_Multiple</a> test shows a number of ways to connect multiple Event Channels.
1662 <tr><td>
1663 For the IDL source for the various interfaces, please see
1664 <a href="../orbsvcs/orbsvcs/RtecScheduler.idl">RtecScheduler.idl</a>,
1665 <a href="../orbsvcs/orbsvcs/CosEventChannelAdmin.idl">CosEventChannelAdmin.idl</a>,
1666 <a href="../orbsvcs/orbsvcs/CosEventComm.idl">CosEventComm.idl</a>
1668 <a href="../orbsvcs/orbsvcs/CosNaming.idl">CosNaming.idl</a>.
1671 </table>
1672 </center>
1674 <P><HR><P>
1675 <!-- ************************************************************ -->
1677 <center><table cellpadding=1 border=0 cellspacing=4>
1678 <tr><td>
1679 <h2><a name="Section8">Reference Materials</a></h2>
1681 <tr><td>
1682 The following materials were used in developing this tutorial: please refer to them for further information.
1684 <tr><td>
1685 <br>
1686 <tr><td>
1687 <h3>Books</h3>
1689 <tr><td>
1690 Mowbray, T. and Zahavi, R. The Essential CORBA, Systems Integration Using Distributed Objects. Wiley, 1995.
1691 ISBN 0-471-10611-9
1693 <tr><td>
1694 <br>
1696 <tr><td>
1697 Baker, S. CORBA Distributed Objects Using Orbix. Addison-Wesley, 1997. ISBN 0-201-92475-7
1699 <tr><td>
1700 <br>
1701 <tr><td>
1702 <h3>Papers</h3>
1704 <tr><td>
1705 <ul>
1707 <li><a href="http://www.cs.wustl.edu/~schmidt/Arch.ps.gz">
1708 Architectural Considerations for Deterministic Real-Time ORB
1709 Endsystems and Applications</a>
1711 <li><a href="http://www.cs.wustl.edu/~schmidt/JSAC-98.ps.gz"> The
1712 Design and Performance of a Real-Time CORBA Object Event Service</a>
1714 <li><a href="http://www.cs.wustl.edu/~schmidt/RT-ORB.ps.gz"> The
1715 Design of the TAO Real-Time Object Request Broker</a>
1717 </ul>
1720 <tr><td>
1722 </table>
1723 </center>
1725 <P><HR><P>
1726 <!-- ************************************************************ -->
1729 <center><table cellpadding=1 border=0 cellspacing=4>
1730 <tr><td>
1731 </table></center>
1733 </body></html>