[7862] Fixed infinity loop at search spell related summoned gameobject in owner list.
[getmangos.git] / dep / ACE_wrappers / FAQ
blobc184fbde84c8248d1b9c2df4262fbf1e9b897e5a
1 There are many changes and improvements in the new version of ACE.
2 The ChangeLog file contains complete details about all of them.
4 I've tested ACE thoroughly on Solaris 2.3 and 2.4 with the SunC++ 4.x
5 compiler and Centerline 2.x.  I've also tested it with the SunC++ 3.x
6 compiler on the SunOS 4.x platform.  However, I've not been able to
7 test it on other platforms.  If anyone has time to do that, and can
8 report the results back to me I'd appreciate that.
10 Please let me know if you have any questions or comments.
12         Doug
14 ----------------------------------------
16 1. SIGHUP
18 > 1) Where the heck does the HUP signal get registered for the 
19 > $ACE_ROOT/tests/Service_Configurator/server stuff? I looked there and
20 > in $ACE_ROOT/libsrc/Service_Configurator. No luck. I guess I am
21 > just blind from reading.
23         Take a look in ./libsrc/Service_Configurator/Service_Config.h.
24 The constructor for Service_Config is where it happens:
26   Service_Config (int ignore_defaults = 0, 
27                   size_t size = Service_Config::MAX_SERVICES, 
28                   int signum = SIGHUP);
30 ----------------------------------------
31 2. Multi-threaded Signal_Handler support
33 > It appears Signal_Handler is
34 > not setup for multi-threaded apps.  How do you handle signals
35 > in different threads? Do I have to put in the hooks in my app or should
36 > it go in the Threads arena?
38         Ah, good question...  My design follows the approach espoused
39 by Sun.  Basically, they suggest that you implement per-thread signal
40 handling atop of the basic UNIX signal handlers (or in the case of
41 ACE, the handle_signal() callbacks on Event_Handler subclasses) by
42 using the thread id returned by thr_self() to index into a search
43 structure containing the handlers.  This should be pretty straight
44 forward to layer atop the existing ACE Signal_Handler mechanisms.
45 However, you might ask yourself whether you really want (1) separate
46 signal handler *functionality* in different threads or (2) different
47 threads that mask out certain signals.  The latter might be easier to
48 implement and reason about!
50 ----------------------------------------
51 3. Problems compiling ACE with G++
53 > I substituted -lg++ for -lC in macro_wrappers.GNU and ran make.
54
55 > Most stuff seemed to build.  Continually got messages like the following:
56 > ld: /usr2/tss/jvm/ACE_wrappers/lib/libASX.a: warning: archive has no table of c
57 > ontents; add one using ranlib(1)
58 > ld: /usr2/tss/jvm/ACE_wrappers/lib/libThreads.a: warning: archive has no table 
59 > of contents; add one using ranlib(1)
60 > ld: /usr2/tss/jvm/ACE_wrappers/lib/libSPIPE.a: warning: archive has no table of
61 >  contents; add one using ranlib(1)
62 > ld: /usr2/tss/jvm/ACE_wrappers/lib/libASX.a: warning: archive has no table of c
63 > ontents; add one using ranlib(1)
64 > ld: /usr2/tss/jvm/ACE_wrappers/lib/libThreads.a: warning: archive has no table 
65 > of contents; add one using ranlib(1)
66 > ld: /usr2/tss/jvm/ACE_wrappers/lib/libSPIPE.a: warning: archive has no table of
67 >  contents; add one using ranlib(1)
69 > no matter how many times I used ranlib or removed the libraries and re-compiled
70 > or whatever.  Perhaps these are System V specific and will not work on 4.1.3?
72         Yes, that's exactly right.  If you look at the files, they all
73 contain ifdef's for features that aren't included in the
74 ./include/makeinclude/wrapper_macros.GNU file.  To make this more
75 obvious, I've enclosed the following message in the ACE-INSTALL.html file:
77         * Sun OS 4.1.x
79                   Note that on SunOS 4.x you may get warnings from the 
80                   linker that "archive has no table of contents; add
81                   one using ranlib(1)" for certain libraries (e.g.,
82                   libASX.a, libThreads.a, and libSPIPE.a).  This 
83                   occurs since SunOS 4.x does not support these features.
85 > never able to get .so -- assume these are shared libraries that gcc can not
86 > deal with.
88         Yes, if you use the stock gcc/gas/gnu ld
89 compiler/assembler/linker, you won't get shared libraries to work.  It
90 is possible to hack this by using the "collect" version of g++.
91 However, as usual, I strongly advise people to stay away from g++ if
92 you want to use shared libraries or templates.
94 > got some linker errors as follows:
95
96 > g++ -g  -DACE_NTRACE  -DACE_HAS_MT_SAFE_SOCKETS -DACE_HAS_NO_T_ERRNO -DACE_HAS_
97 > OLD_MALLOC -DACE_HAS_POLL -DACE_HAS_SEMUN -DACE_HAS_SETOWN -DACE_HAS_STRBUF_T -
98 > DACE_HAS_STREAMS -DACE_HAS_SVR4_DYNAMIC_LINKING -DACE_HAS_TIUSER_H -DACE_HAS_SY
99 > S_FILIO_H -DACE_PAGE_SIZE=4096 -DACE_HAS_ALLOCA -DACE_HAS_CPLUSPLUS_HEADERS -DA
100 > CE_HAS_SVR4_SIGNAL_T -DACE_HAS_STRERROR -DMALLOC_STATS -I/usr2/tss/jvm/ACE_wrap
101 > pers/include  -I/usr2/tss/jvm/ACE_wrappers/libsrc/Shared_Malloc  -o test_malloc
102 >  .obj/test_malloc.o -L/usr2/tss/jvm/ACE_wrappers/lib  -Bstatic -lSemaphores -lS
103 > hared_Malloc -lShared_Memory -lReactor -lThreads -lMem_Map -lLog_Msg -lFIFO -lI
104 > PC_SAP -lMisc -lnsl -lg++
105 > ld: /usr2/tss/jvm/ACE_wrappers/lib/libThreads.a: warning: archive has no table 
106 > of contents; add one using ranlib(1)
107 > ld: Undefined symbol 
108 >    _free__t6Malloc2Z18Shared_Memory_PoolZ13PROCESS_MUTEXPv 
109 >    _free__t6Malloc2Z17Local_Memory_PoolZ10Null_MutexPv 
110 >    _malloc__t6Malloc2Z18Shared_Memory_PoolZ13PROCESS_MUTEXUl 
111 >    _malloc__t6Malloc2Z17Local_Memory_PoolZ10Null_MutexUl 
112 >    _remove__t6Malloc2Z17Local_Memory_PoolZ10Null_Mutex 
113 >    ___t6Malloc2Z17Local_Memory_PoolZ10Null_Mutex 
114 >    _print_stats__t6Malloc2Z17Local_Memory_PoolZ10Null_Mutex 
115 >    _remove__t6Malloc2Z18Shared_Memory_PoolZ13PROCESS_MUTEX 
116 >    ___t6Malloc2Z18Shared_Memory_PoolZ13PROCESS_MUTEX 
117 >    _print_stats__t6Malloc2Z18Shared_Memory_PoolZ13PROCESS_MUTEX 
118 > collect2: ld returned 2 exit status
119 > gcc: file path prefix `static' never used
120 > make[2]: *** [test_malloc] Error 1
121 > make[2]: Leaving directory `/usr2/tss/jvm/ACE_wrappers/tests/Shared_Malloc'
122 > <========     End all: /usr2/tss/jvm/ACE_wrappers/tests/Shared_Malloc
124         That looks like a problem that G++ has with templates.  I
125 don't know of any reasonable solution to this problem using g++.
127 > Finally decided there was enough stuff that it looked like I might have some
128 > thing so I tried to run some tests and could not find so much as one piece
129 > of documentation that might give me some clue about running tests.
131 You should take a look at ./tests/Service_Configurator/server/README
132 file.  That explains how to run the more complicated tests.  As for
133 the other tests, it is pretty straight forward if you look at the
134 ./tests/IPC_SAP/SOCK_SAP and ./tests/Reactor/* directory code to
135 figure out how to run the tests.  I don't have a Q/A department, so
136 any documentation has to come from volunteers.
138 ----------------------------------------
139 4. Is there any docs or man pages on the Log_Record class?
141 There is a paper in the C++_wrappers_doc.tar.Z file on ics.uci.edu
142 called reactor2.ps that has some examples of using Log_Record.  The
143 ./apps/Logger directories show several examples using Log_Record.  
144 Finally, the source code for Log_Record is pretty short (though it
145 clearly could be commented better ;-)).
147 ----------------------------------------
148 5. Signal handling prototypes
150 > According to the man page on sigaction on our system, that line
151 > should look something like the following:
153 >       sa.sa_handler = SIG_DFL;
155         The problem is that most versions of UNIX I've come across
156 don't have a correct prototype for this field of struct sigaction.
157 That's why I define two variants of signal handler typedefs: one that
158 is a typedef of the "correct version" (which I call SignalHandler) and
159 one of which is a typedef of the "incorrect version" (which I call
160 SignalHandlerV).  You might check out the sysincludes.h file to see
161 how it is defining SignalHandlerV and make sure this matches what your
162 OS/Compiler defines in <sys/signal.h>
164 ----------------------------------------
165 6. Omitting shared libraries
167 > Can anyone tell me a way to turn off the creation of the shared libraries
168 > in the ACE build.
170 You can simply comment out the LIB target in the $ACE_ROOT/ace/Makefile
171 or change the BUILD target from
173 BUILD   = $(VLIB) $(VSHLIB) $(SHLIBA)
177 BUILD   = $(VSHLIB) $(SHLIBA)
179 ----------------------------------------
180 7. DCE threading and signal handling
182 >Reading the DCE docs leaves me confused as to how to make everyone
183 >work together in a happy hormonious whole. May basic need is to catch
184 >asynchronous signals so i can release some global resources before
185 >the process exits.
187 You need to spawn a separate thread to handle signals.  As part of
188 your init, do this:
189         pthread_create(&tid, thread_attr, signal_catcher, NULL);
190         pthread_detach(&tid);
192 Where signal_catcher is like this:
193 static void *
194 signal_catcher(void *arg)
196     static int          catch_sigs[] = {
197         SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGCHLD
198     };
199     sigset_t            catch_these;
200     int                 i;
201     error_status_t      st;
203     for ( ; ; ) {
204         sigemptyset(&catch_these);
205         for (i = 0; i < sizeof catch_sigs / sizeof catch_sigs[0]; i++)
206             sigaddset(&catch_these, catch_sigs[i]);
207         i = sigwait(&catch_these);
208         /* Note continue below, to re-do the loop. */
209         switch (i) {
210         default:
211             fprintf(stderr, "Caught signal %d.  Exiting.\n", i);
212             CLEANUP_AND_EXIT();
213             /* NOTREACHED */
214 #if     defined(SIGCHLD)
215         case SIGCHLD:
216             srvrexec__reap();
217             continue;
218 #endif  /* defined(SIGCHLD) */
219         }
220     }
221     return NULL;
223 ----------------------------------------
226 > I have installed ACE2.15.5 on SunOS 4.1.3 with gcc2.6.0. I run the test program
227 > ---server_test. The static is OK, but error found when I commented out the first
228 > one and uncommented out the second one in the svc.conf file: 
230 > #static Svc_Manager "-d -p 3912"
231 > dynamic Remote_Brdcast Service_Object * .shobj/Handle_Broadcast.so:remote_broad
232 > cast "-p 10001"
234 > The error goes like this:
236 > -----------
237 > jupiter[12] %server_test -d
238 > starting up daemon server_test
239 > opening static service Svc_Manager
240 > did static on Svc_Manager, error = 0
241 > signal signal 1 occurred
242 > beginning reconfiguration at Sat Feb 25 13:40:29 1995
243 > Segmentation fault (core dumped)
244 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
246 My guess is that the code generated by GCC on SunOS 4.x does not
247 correctly initialize static variables from shared libraries.  The
248 SunC++ 4.0.x compiler does this correctly on Solaris 2.x (though I
249 believe that on SunOS 4.x it doesn't work without some extra coaxing).
251 In general, I try to avoid using ACE's explicit dynamic linking
252 mechanisms on SunOS 4.x and GCC.  You can write plenty of interesting
253 and useful code with ACE without using those features.  Those tests
254 are mostly there to illustrate the "proof of concept."
255 ----------------------------------------
256 9. 
258 > a) I noticed the default constructor for the reactor does an open w/ defaults.
259 >    Does this mean I need to close it if I wish to re-open it with different
260 >    size and restart values?
262         No.  With the latest versions of ACE, you can now just call
263 open() with a new size and it will correctly resize the internal
264 tables to fit.
266 > b) What is the usage difference between the normal FD_Set objects 
267 >    (rd/wr/ex_handle_mask_) and the ready FD_Set objects 
268 >    (rd/wr/ex_handle_mask_ready)?
270         The normal FD_Sets (now called Handle_Set in ACE 3.0.5) holds
271 the "waitable" descriptors (these are the descriptors given to
272 select() or poll()).  In contrast, the ready FD_Sets may be set by
273 Event_Handler subclasses (by called the set_ready() API) to indicate
274 to the Reactor that they want to be redispatched on the next go-round
275 *without* blocking.  If you look at the Reactor code, you'll see that
276 the wait_for() method checks the ready sets first and doesn't block if
277 there are any bits set in those masks.  This features makes it
278 possible for Event_Handlers to control subsequent dispatching policies
279 of the Reactor.
281 > c) What does the positive return value do from an event handler callback:
282 >   -1 detaches the event handler for that mask
283 >    0 does nothing - keeps the event handler registered for that mask
284 >   >0 resets a bit in the current dispatching mask (I think) - does this mean 
285 >    this event will be called again before the current dispatch cycle is done?
287 Almost...  (it's tied in with my description of the ready sets above).
288 It means that once the Reactor finishes cycling through the set of
289 descriptors it got back from select() or poll(), it will redispatch
290 the ready set descriptors before sleeping.
292 >    Without direct access to the bit masks in X, I'm not sure I could emulate
293 >    this activity - what do you think?
295 I'm not sure.  I'm not enough of an X guru.  Maybe someone else on the
296 list knows the answer to this?
298 > d) If I let X do the select blocking, will that have any affect on 
299 >    the Reactor performing signal handling? 
301         Yes, I think that will cause problems since the Reactor relies
302 on a "handshake" between its Signal_Handler component and its
303 handle_events loop to properly handle signals.
305 > e) Is the Poll method preferred over Select if it is available - why?
307 For systems that implement select() in terms of poll() (e.g., Solaris
308 2.x) then it may be somewhat faster.  Otherwise, it doesn't really
309 matter since (1) they (should) do the same thing and (2) the end user
310 shouldn't notice any change in behavior.
312 ----------------------------------------
313 10. 
315 > I would very much like to evaluate/use the ACE Toolkit,
316 > but am limited as to disk space on our system.
317 > What is the total disk space required for a compiled,
318 > usable toolkit?
320 The source code itself is around 2 Meg, uncompressed.  
322 The compiled version of ACE is around 90 Meg compiled with the SunC++
323 4.x compiler (naturally, this will differ with other compilers).
324 However, of this amount, about 40 meg are for the libraries, and
325 another 50 meg are for the test programs.  Naturally, you don't need
326 to keep the test programs compiled.
328 The postscript documentation is around 5 Meg, compressed.
330 ----------------------------------------
333 > This is regarding the newer release of ACE and pertaining to the library
334 > archive file. My question is, if all the ".o" files are archived into one
335 > single "libACE.a", does it increase the size of the executable program?
337 No.  The use of a *.a file allows the linker to extract out only those
338 *.o files that are actually used by the program.
340 > If it does, then does a large executable program mean possibility of it being 
341 > slower?
343         No.
345 ----------------------------------------
348 > What happens if I have several reactors in a process (e.g. in different 
349 > threads)?
351 > Programmer 1 decides to register at reactor 1 in his thread 1 a signal handler 
352 > for SIGUSR.
353 > Programmer 2 decides to register at reactor 2 in his thread 2 a signal handler
354 > for SIGUSR.
356         Naturally, the behavior of this all depends on the semantics
357 of the threads package...  In Solaris 2.x, signal handlers are shared
358 by all threads.  Moreover, the Reactor uses a static table to hold the
359 thread handlers.  Thus, only one of the handler's would be registered
360 (i.e., whichever one was registered second).
362 > Programmer 3 designs the process and decides to have thread 1 and thread 2
363 > running in the same process and also makes use of a third party software library
364 > that internally has also registered a signal handler (not at the reactor) for
365 > SIGUSR.
367         Now you've got big problems!  This is an example of a
368 limitation with UNIX signal handlers...  In general, it's a bad idea
369 to use signal handlers if you can avoid it.  This is yet another
370 reason why.
372 > When looking into Ace/ACE_wrappers/tests/Reactor/misc/signal_tester.C you
373 > have shown a way to do this by marking the dummy file_descriptor of the
374 > Sig_Handler object ready for reading asynchronously. The handle_input()
375 > routine of Sig_Handler object will then be dispatched synchronously.
376 > But what happens if I have several reactors. 
377 > The asynchronously dispatched
378 > handle_signal() routine does not know via which reactor it has been registered
379 > so in which reactor to modify the dummy file_descriptor.
380 > Is your suggestion to have just one process global reactor in such a case?
382         Yes, precisely.  I would *strongly* recommend against using
383 several reactors within separate threads within the same process if
384 you are going to be having them handle signals.  Can you use 1
385 reactor and/or have one reactor handle signals within a process?
387 > One thing we want to do is the priorization of Event_Handlers. I.e. in case
388 > of concurrent events the sequence in which the Event_Handler methods will be
389 > activated depends on their priority relative to each other. 
390 > We have two choices:
391 > - complete priorization, which means a high priority Input Event_Handler may
392 >   be activated prior to a lower prioritized Output Event_Handler (and doing
393 >   so violating the 'hardcoded rule' that output must be done prior to input).
394 > - priorization only in categories, which means all Output Event_handler are
395 >   ordered by their priority regardless of priorities for the category of Input
396 >   Event_Handlers. The priority is fixed between the categories, i.e. first
397 >   output then input then out-of-band.
399 > Right now I would think that we have to use the second choice if we want to
400 > use the feature of asynchronous output with automatical re-queueing. Am I right
401 > ?
403         Hum, that's an interesting problem.  It might be better to
404 subclass the Reactor to form a new class called Priority_Reactor.
405 This subclass would override the Reactor's dispatch method and
406 dispatch the event handlers in "priority" order.  I've never done
407 that, but I don't think it would be all that difficult.
409 ----------------------------------------
410 13. 
412 >       Is the Orbix (aka CORBA) version still around?
414 Nope, IONA does not support Orbix-2.X nor Orbix-3.0 anymore (the
415 versions of Orbix that the ACE code was based upon).  Plus we didn't
416 maintain this code for ages, so it probably was broken too.
418 ----------------------------------------
419 14. 
420 > We are using your ACE software and ran into a problem which may or may not
421 > be related to the mutex locks.  The question may have more to do with how 
422 > mutex locks should be used.  We had a class which was using your mutex 
423 > lock wrapper.  Each member function of the class acquired the lock before 
424 > processing and released on exiting the function.  Some member functions may 
425 > call other member functions.  The following is an example:
427 > class foo {
429 > void a()
430 > {
431 >   MT( Mutex_Block<Mutex> m( this->lock_ ));
433 >   if( cond )
434 >     b();
435 > }
437 > void b()
438 > {
439 >   MT( Mutex_Block<Mutex> m( this->lock_ ));
441 >   if( cond )
442 >     a();
443 > }
445 > };
447 > Is this valid ?  My assumtpion is that the mutex lock is recursive and 
448 > the same thread can acquire the lock multiple times in different member
449 > functions.
451         Ah, that's a great question since there are subtle and
452 pernicious problems lurking in the approach you are trying above.
453 Basically, Solaris mutex locks are *not* recursive (don't ask why...)
454 Thus, if you want to design an application like the one above you'll
455 need to use one or more of the following patterns:
457 ----------------------------------------
458 A. Use recursive mutexes.  Although these are not available in
459    Solaris directly they are supported in the later versions
460    of ACE.  You might want to take a look at the latest
461    version (./gnu/ACE-3.1.9.tar.Z).  It's got lots of new
462    support for threading and synchronization.  In that case,
463    you simply do the following:
465         class Foo 
466         {
467           public:
468           void a()
469           {
470             MT( Guard<Recursive_Lock <Mutex> > m( this->lock_ ));
471             b ();
472           }
474           void b()
475           {
476             MT( Guard<Recursive_Lock <Mutex> > m( this->lock_ ));
477             b_i ();
478           }
480         };
482    The advantage with this is that it requires almost no
483    changes to existing code.  The disadvantage is that
484    recursive locks are just slightly more expensive.
486 B. Have two layers of methods (a) which are public and acquire
487    the Mutex and then call down to methods in layer (b), which
488    are private and do all the work.  Methods in layer b assume
489    that the locks are held.  This avoids the deadlock problem
490    caused by non-recursive mutexes.  Here's what this approach
491    looks like (using the more recent ACE class names):
493         class Foo 
494         {
495           public:
496           void b()
497           {
498             MT( Guard<Mutex> m( this->lock_ ));
499             b_i ();
500           }
502           void b_i()
503           {
504             if( cond )
505               a_i();
506           }
508           void a_i()
509           {
510             if( cond )
511               b_i();
512           }
514           void a()
515           {
516             MT( Guard<Mutex> m( this->lock_ ));
517             a_i ();
518           }
520         };
522     The advantage here is that inline functions can basically
523     remove all performance overhead.  The disadvantage is that
524     you need to maintain two sets of interfaces.
526 C. Yet another approach is to release locks when calling
527    other methods, like this:
529         class Foo 
530         {
531           public:
532           void b()
533           {
534             MT( Guard<Mutex> m( this->lock_ ));
535             m.release ();
536             a ();
537             m.acquire ();
538           }
540           void a()
541           {
542             MT( Guard<Mutex> m( this->lock_ ));
543             m.release ();
544             b ();
545             m.acquire ();
546           }
548         };
550    The disadvantage with this, of course, is that you
551    greatly increase your locking overhead.  In addition,
552    you need to be very careful about introducing race
553    conditions into the code.  The primary reason for
554    using this approach is if you need to call back to
555    code that you don't have any control over (such as
556    OS I/O routines) and you don't want to hold the 
557    lock for an indefinite period of time.
558 ----------------------------------------
559            
560         BTW, all three of these patterns are used in the ACE Reactor
561 class category.  The Reactor has a number of fairly complex
562 concurrency control and callback issues it must deal with and I've
563 found it useful to use all three of these patterns jointly.
565         I'd be interested to hear any comments on these approaches.
566         
567         Doug
568 ----------------------------------------
569 15. 
571 > I am working on Solaris 2.3 and trying to understand how to get around
572 > the problem of trying to open a Socket connection to a remote host that
573 > is "dead".  Of course you get a nice long process block if the socket
574 > is in Blocking mode (TCP lets you know when you can continue - how polite). 
576 > So how does a non-blocking connect work with respect to using
577 > the Reactor and a SOCK_Stream object to coordinate the opening
578 > of the connection? Do I wait on the OUTPUT event for the FD?
579 > How do I know if the connect worked or possibly timed-out?  Is
580 > this a reliable approach (I read somewhere that this will only
581 > work if the STREAMS module is at the top of the protocol stack
582 > - MAN page I think)?
584 An example of implementing this is in the Gateway sample application
585 in the new ACE.  It's also encapsulated in the Connector<> pattern of
586 the Connection class category in ./libsrc/Connection.  You may want to
587 take a look at those two things for concrete usage examples.
589 However, the basics of getting non-blocking to work are:
590 - set socket to non-blocking
591 - initiate connect() request
592 - if connect() returned 0 you're connected
593 - if connect() returned -1 and errno is EWOULDBLOCK (or EAGAIN, depending  
594 on where you are), then register an event handler for read and write events  
595 on the socket
596 - any other errno value is fatal
598 When an event is returned
599 - no matter which event you get back (read or write), you may have gotten  
600 the event out of error.  Thus, re-attempt the connect() and check to see if  
601 errno is EISCONN (if it's not there's a problem!)
602 - if errno was EISCONN, the connection is ready to go, otherwise you must  
603 handle an error condition
605 If you want to "time out" after a certain period of time, consider  
606 registering for a timer event with Reactor.  If the timer goes off before  
607 the connection succeeds, close down the appropriate socket.
609 > Is using a separate thread to make the connection a better way to avoid
610 > the potentialy long block in the main thread during the connect call?
612 You could do that, but it can all be accomplised in a single process using  
613 the facilities available.
614 ----------------------------------------
615 16. 
617 > I was wondering, does the Reactor class have the ability to prioritize 
618 > activity on the registered event handlers?
620         The default strategy for the Reactor's dispatch routine
621 (Reactor::dispatch) does not prioritize dispatching other than to
622 dispatch callbacks in ascending order from 0 -> maxhandlep1.
624 > We have a requirment to be able to process both real-time, as well as, stored
625 > telemetry and ERMs concurrently.  Real-time needs to be processed at a higher
626 > priority than stored data.  Our design is based on both real-time and stored 
627 > data coming into our process via separate sockets.  
629         I can think of several ways to do this:
630         
631         1. Use dup() or dup2() to organize your sockets such that the
632            higher priority sockets come first in the Handle_Sets that
633            the Reactor uses to dispatch sockets.  This is pretty easy
634            if you don't want to muck with the Reactor code at all.
636         2. You could subclass Reactor::dispatch() and revise it so
637            that it dispatches according to some other criteria that
638            you define in order to ensure your prioritization of
639            sockets.
641 BTW, I'm not sure what you mean by "real-time" but I assume that you
642 are aware that there is no true "real-time" scheduling for network I/O
643 in Solaris.  However, if by "real-time" you mean "higher priority"
644 then either of the above strategies should work fine.  
645 ----------------------------------------
646 17. 
648 >       I compiled the new ACE 3.2.0 's apps/Gateway. The compiling went
649 > through without any errors. But I could not get it running,  neither single
650 > threaded nor multi-threaded. The cc_config and rt_config files entries are given
651 > below. Also the machine configurations are given below. Does it need some more 
652 > settings or some patch !!??
654         I believe you are seeing the effects of the dreaded Sun MP bug
655 with non-blocking connects.  The easy work around for now is simply to
656 give the "-b" option to the Gateway::init() routine via the svc.conf
657 file:
659 dynamic Gateway Service_Object *.shobj/Gateway.so:_alloc_gatewayd() active 
660                                 "-b -d -c cc_config -f rt_config"
662 If you check line 137 of the Gateway::parse_args() method you'll see
663 what this does.
664 ----------------------------------------
667 How to get ACE to work with GCC C++ templates.
669 The first and foremost thing to do is to get the latest version of GCC
670 (2.7.2) and also get the template repository patches from
672 ftp://ftp.cygnus.com/pub/g++/gcc-2.7.1-repo.gz
674 This will get the ball rolling...
676 Here is some more info on G++ templates courtesy of Medhi TABATABAI
677 <Mehdi.TABATABAI@ed.nce.sita.int>:
679 Where's the Template?
680 =====================
682    C++ templates are the first language feature to require more
683 intelligence from the environment than one usually finds on a UNIX
684 system.  Somehow the compiler and linker have to make sure that each
685 template instance occurs exactly once in the executable if it is
686 needed, and not at all otherwise.  There are two basic approaches to
687 this problem, which I will refer to as the Borland model and the
688 Cfront model.
690 Borland model
691      Borland C++ solved the template instantiation problem by adding
692      the code equivalent of common blocks to their linker; template
693      instances are emitted in each translation unit that uses them, and
694      they are collapsed together at run time.  The advantage of this
695      model is that the linker only has to consider the object files
696      themselves; there is no external complexity to worry about.  This
697      disadvantage is that compilation time is increased because the
698      template code is being compiled repeatedly.  Code written for this
699      model tends to include definitions of all member templates in the
700      header file, since they must be seen to be compiled.
702 Cfront model
703      The AT&T C++ translator, Cfront, solved the template instantiation
704      problem by creating the notion of a template repository, an
705      automatically maintained place where template instances are
706      stored.  As individual object files are built, notes are placed in
707      the repository to record where templates and potential type
708      arguments were seen so that the subsequent instantiation step
709      knows where to find them.  At link time, any needed instances are
710      generated and linked in.  The advantages of this model are more
711      optimal compilation speed and the ability to use the system
712      linker; to implement the Borland model a compiler vendor also
713      needs to replace the linker.  The disadvantages are vastly
714      increased complexity, and thus potential for error; theoretically,
715      this should be just as transparent, but in practice it has been
716      very difficult to build multiple programs in one directory and one
717      program in multiple directories using Cfront.  Code written for
718      this model tends to separate definitions of non-inline member
719      templates into a separate file, which is magically found by the
720      link preprocessor when a template needs to be instantiated.
722    Currently, g++ implements neither automatic model.  The g++ team
723 hopes to have a repository working for 2.7.0.  In the mean time, you
724 have three options for dealing with template instantiations:
726   1. Do nothing.  Pretend g++ does implement automatic instantiation
727      management.  Code written for the Borland model will work fine, but
728      each translation unit will contain instances of each of the
729      templates it uses.  In a large program, this can lead to an
730      unacceptable amount of code duplication.
732   2. Add `#pragma interface' to all files containing template
733      definitions.  For each of these files, add `#pragma implementation
734      "FILENAME"' to the top of some `.C' file which `#include's it.
735      Then compile everything with -fexternal-templates.  The templates
736      will then only be expanded in the translation unit which
737      implements them (i.e. has a `#pragma implementation' line for the
738      file where they live); all other files will use external
739      references.  If you're lucky, everything should work properly.  If
740      you get undefined symbol errors, you need to make sure that each
741      template instance which is used in the program is used in the file
742      which implements that template.  If you don't have any use for a
743      particular instance in that file, you can just instantiate it
744      explicitly, using the syntax from the latest C++ working paper:
746           template class A<int>;
747           template ostream& operator << (ostream&, const A<int>&);
749      This strategy will work with code written for either model.  If
750      you are using code written for the Cfront model, the file
751      containing a class template and the file containing its member
752      templates should be implemented in the same translation unit.
754      A slight variation on this approach is to use the flag
755      -falt-external-templates instead; this flag causes template
756      instances to be emitted in the translation unit that implements
757      the header where they are first instantiated, rather than the one
758      which implements the file where the templates are defined.  This
759      header must be the same in all translation units, or things are
760      likely to break.
762      *See Declarations and Definitions in One Header: C++ Interface,
763      for more discussion of these pragmas.
765   3. Explicitly instantiate all the template instances you use, and
766      compile with -fno-implicit-templates.  This is probably your best
767      bet; it may require more knowledge of exactly which templates you
768      are using, but it's less mysterious than the previous approach,
769      and it doesn't require any `#pragma's or other g++-specific code.
770      You can scatter the instantiations throughout your program, you
771      can create one big file to do all the instantiations, or you can
772      create tiny files like
774           #include "Foo.h"
775           #include "Foo.cc"
776           
777           template class Foo<int>;
779      for each instance you need, and create a template instantiation
780      library from those.  I'm partial to the last, but your mileage may
781      vary.  If you are using Cfront-model code, you can probably get
782      away with not using -fno-implicit-templates when compiling files
783      that don't `#include' the member template definitions.
785 4. Placing a function that looks like this near the top of a .C file
786    that uses any inline template member functions permits proper inlining:
788    // #ifdef __GNUG__
789    // This function works around the g++ problem with inline template member
790    // calls not being inlined ONLY in the first block (in a compilation
791    // unit) from which they are called.
792    // This function is inline and is never called, so it does not produce
793    // any executable code.  The "if" statements avoid compiler warnings about
794    // unused variables.
795    inline
796    void
797    gcc_inline_template_member_function_instantiator()
798    {
799        if ( (List<FOO> *) 0 );
800    }
801    // #endif  // __GNUG__
803    other prerequisites:
804    -- All inline template member functions should be defined in
805       the template class header.  Otherwise, g++ will not inline
806       nested inline template member function calls.
807    -- Template .h and .C files should NOT include iostream.h
808       (and therefore debugging.h).
809       This is because iostream.h indirectly includes other
810       GNU headers that have unprotected #pragma interface,
811       which is incompatible with -fno-implicit-templates and optimal
812       space savings.
813    -- inline virtual destructors will not be inlined, unless necessary,
814       if you want to save every last byte
815    -- be sure that -Winline is enabled
817 ----------------------------------------
820 >       1. when are dynamically loaded objects removed from the Service_Config.
822 The Service Configurator calls dlclose() when a "remove Service_Name"
823 directive is encountered in the svc.conf file (or programmatically
824 when the Service_Config::remove() method is invoked).  Check out the
825 code in ./libsrc/Service_Config/Service_Repository.i and
826 ./libsrc/Service_Config/Service_Config.i to see exactly what happens.
828 >       2. In the Service Configurator, when an item is entered in the svc.conf
829 >               how dow you know which items will be invoked as threads and 
830 >               which items are forked. I know that static items are executed 
831 >               internally. 
833         No!  It's totally up to the subclass of Service_Object to
834 decide whetehr threading/forking/single-threading is used.  Check out
835 the ./apps/Logger/Service_Configurator_Logger for examples of
836 single-threaded and multi-threaded configuration.
837 ----------------------------------------
838 20. 
840 > I have been reading the Service Configurator Logger. I was wondering about 
841 > cleanup of new objects. In the handle_input method for the Acceptor a new
842 > svc_handler is allocated for each new input request and deleted in the 
843 > handle_close. I was wondering how handle close was called when a client who
844 > has created a socket terminates the connection (i.e., when is handle_close
845 > called).
847 handle_close() is automatically called by the Reactor when a
848 handle_input()/handle_output()/etc. method returns -1.  This is the
849 "hook" that instructs the Reactor to call handle_**() and then remove
850 the Event_Handler object from its internal tables.
852 ----------------------------------------
853 21. 
855 > How does the Logger know to remove the client socket and the svc_handler object.
856 > Does he recieve an exception. 
858         No.  when the client terminates the underlying TCP/IP
859 implementation sends a RESET message to the logger host.  This is
860 delivered to the logger process as a 0-sized read().  It then knows to
861 close down.
863 > What I am worried about is a leak. Where by alot of clients connect and 
864 > disconnect and the server does not cleanup correctly. Such as a core dump
865 > from the client where he cannot close correctly.
867         That's handled by the underlying TCP (assuming it is
868 implemented correctly...).
870 > What I am doing is attempting to convert the logger example into an alarm
871 > manager for remote nodes. In this application a node may be powered down
872 > there by terminating a Logger/Alarm server connection abnormally, this could
873 > leave the Logger with many dangling sockets and allocated svc_handler objects.
875         If the TCP implementation doesn't handle this correctly then
876 the standard way of dealing with it is to have an Event_Handler use a
877 watchdog timer to periodically "poll" the client to make sure it is
878 still connected.  BTW, PCs tend to have more problems with this than
879 UNIX boxes since when they are turned off the TCP implementation may
880 not be able to send a RESET...
881 ----------------------------------------
882 22. 
884 Using templates with Centerline.
886 Centerline uses ptlink to process the C++ templates. ptlink expect the
887 template declarations and definitions (app.h and app.C) to reside in
888 the same directory. This works fine for the ACE hierarchy since
889 everything is a link to the appropriate src directory (include/*.[hi]
890 --> ../src/). When a users of the ACE distribution attempts to include
891 the ACE classes in an existing application hierarchy this problem will
892 arise if ptlink is used.
894 The solution is to create a link to the declaration file from the
895 definition file directory and use the "-I" to point to the definition
896 directory.
898 ----------------------------------------
900 23. 
902 > When I try to compile $ACE_ROOT/src/Message_Queue.C on a Solaris
903 > 5.3 system using SUNPro CC 4.0, the compiler aborts with a Signal 10
904 > (Bus Error).  Our copy of CC 4.0 is over a year old and I do not
905 > know if any patches or upgrades exist for it.  If they do, then we
906 > have not applied them to our compiler.
908         Several other people have run across this as well.  It turns
909 out that there is a bug in the Sun 4.0.0 C++ compiler that will get a
910 bus error when -g is used.  If you compilg Message_Queue.C *without*
911 -g then it works fine.  The later versions of SunC++ don't have this
912 bug.  I'd recommend that you upgrade as soon as possible.
914 ----------------------------------------
916 24. 
918 > I have added a dynamic service to the Service Configurator. This new service
919 > fails on the load because it uses application libraries that are not shared 
920 > object libraries (i.e., objects in libApp.a). I am assuming from the error
921 > message that the problem is the mix match of shared and non-shared objects.
923         Right, exactly.
925 > I was wondering if there is an easy way to add static services to the 
926 > Service Configurator. The example directory listing static service is
927 > very tightly coupled with the Service_Config object. Is there another
928 > way of adding static services.
930         Sure, that's easy.  The best way to do this is to use the
931 interfaces of the Service_Respository class to configure static
932 services into the Service_Config.  A good example of how to do this is
933 in Service_Config.[Chi]:
936 Service_Config::load_defaults (void)
938   for (Static_Svc_Descriptor *sl = Service_Config::service_list_; sl->name_ != 0; sl++)
939     {
940       Service_Type *stp = ace_create_service_type (sl->name_, sl->type_, 
941                                                    (const void *) (*sl->alloc_)(),
942                                                    sl->flags_);
943       if (stp == 0)
944         continue;
946       const Service_Record *sr = new Service_Record (sl->name_, stp, 0, sl->active_);
948       if (Service_Config::svc_rep->insert (sr) == -1)
949         return -1;
950     }
951   return 0;
954 ----------------------------------------
955 25. 
957 > 8. Do you have examples of the SYNC/ASYNC pattern?
959         Yes.  Check out the following:
960         
961         1. The latest version of ./apps/Gateway/Gateway has
962            an example of this when you compile with the USE_OUTPUT_MT 
963            flag.  In this case, the Reactor performs the "Async"
964            processing, which multiplexes all incoming messages from peers
965            arriving on Input_Channels.  These messages are then queued
966            up at the appropriate Output_Channels.  Each Output_Channel
967            runs in a separate thread, performing the "Sync"
968            processing.
969            
970         2. Also, the latest version of the OOCP-tutorial4.ps.gz
971            file available from wuarchive.wustl.edu in the
972            directory /languages/c++/ACE/ACE-documentation shows
973            an example of using the Half-Sync/Half-Async pattern
974            to build an Image Server.  I'm using this as an
975            example in my tutorials these days.
977 ----------------------------------------
980 > We had a discussion about something we saw in the new ACE code.
981 > I thing there was a member function of a class that was doing a 
982 > "delete this".  Is this safe?
984 In general it is safe as long as (1) the object has been allocated
985 dynamically off the heap and (2) you don't try to access the object
986 after it has been deleted.  You'll note that I tend to use this idiom
987 in places where an object is registered with the Reactor, which must
988 then must ensure the object cleans itself up when handle_close() is
989 called.  Note that to ensure (1) I try to declare the destructor
990 "private" or "protected" so that the object must be allocated off the
991 heap (some compilers have a problem with this, so I may not be as
992 consistent as I ought to...).
994 ----------------------------------------
995 27. 
997 > 5. What is the correct way for building a modified ACE library?
998 >       Changing in "libsrc" or in "include" directory?
999 >       When I make a complete new directory, how can I get introduced
1000 >       the dependencies within my new makefile, can you give a short hint?
1002 Sure, no problem.  For instance, here's what I did tonight when I
1003 added the new Thread_Specific.[hiC] files to ACE:
1005         1. Created three new files Thread_Specific.[hiC] in
1006            ./libsrc/Threads. 
1008         2. cd'd to ../../include/ace and did a
1009         
1010            % ln -s ../../libsrc/Threads/Thread_Specific.[hi] .
1011            
1012         3. cd'd to ../../src and did a     
1014            % ln -s ../../libsrc/Threads/Thread_Specific.C .
1016         4. then I did
1017         
1018            % make depend
1020            on the ./src directory, which updated the dependencies. 
1022 ----------------------------------------
1023 28. The following is from Neil B. Cohen (nbc@metsci.com), who is
1024     writing about how to work around problems he's found with HP/UX.
1026 I've been trying to compile the latest beta (3.2.9) on an HP running
1027 HPUX9.05 for the past week or so. I've had problems with templates up
1028 and down the line. I finally discovered (after some discussions with
1029 the HP support people) that they have made numerous changes to their
1030 C++ compiler recently to fix problems with templates and
1031 exceptions. If you are trying to compile ACE under HPUX with anything
1032 less than version 3.70 of the HP compiler, you may have serious
1033 problems (we were using v3.50 which came with the machine when we
1034 bought it a few months ago).
1036 Also, unlike earlier ACE versions, I was forced to add the following
1037 line to the rules.lib.GNU file to "close" the library - ie. force the
1038 various template files to be instantiated and linked to the ACE
1039 library itself. I don't know if this is necessary, or the only way to
1040 make things work, but it seems to do the job for my system.
1042 in rules.lib.GNU...
1044 $(VLIB): $(VOBJS)
1045     - CC -pts -pth -ptb -ptv -I$(ACE_ROOT)/include $(VOBJS)
1046     $(AR) $(ARFLAGS) $@ $? ./ptrepository/*.o
1047     -$(RANLIB) $@
1048     -chmod a+r $@
1050 I added the CC line, and added the "./ptrepository/*.o" to the $(AR)
1051 cmd.  Sun has an -xar option, I believe that does something similar to
1052 this.  Also - note that I'm not sure that the "-ptb" option is
1053 necessary. I added that before we upgraded the compiler, so it may not
1054 be needed now...
1056 ----------------------------------------
1057 29. 
1059 > I just ran my program with Purify, and it is telling me that there
1060 > is at least one large (~4k) memory leak in
1061 > ACE_Thread_Specific<ACE_Log_Msg>.  This may or may not be serious,
1062 > but it is probably worth looking into.
1064 Right, that's ok.  This is data that's allocated on a "per-thread"
1065 basis the first time a thread makes a call using the LM_ERROR or
1066 LM_DEBUG macros.  The data isn't freed-up until the thread exits.
1068 ----------------------------------------
1070 30. 
1072 >     In my trying to use the Reactor pattern for my application I
1073 > noticed that I had to couple my eventHandler derived objects with a
1074 > specific IPC_SAP mechanism. To use some of your own examples your
1075 > Client_Stream object contains a TLI_Stream object to use in data
1076 > transfer. My application calls for determining the communication
1077 > mechanism at run time. To do this my eventHandler must be able to
1078 > create the appropriate IPC_Stream object at run time and use its
1079 > methods through a super class casting. The problem is that there is no
1080 > super class with the virtual methods for send, recv, etc. To solve my
1081 > problem I will create that super class and have the TLI ( as well as
1082 > other wrapper objects) inherit from it instead of IPC_SAP. My question
1083 > is I am suspicious of why ACE wasn't designed with that in mind? Is my
1084 > application that unique ? or is there a better way to do this that I
1085 > am not aware of ?  Your help in this matter will be much appreciated.
1087 ACE was developed using static binding for IPC_SAP in order to
1088 emphasize speed of execution over dynamic flexibility *in the core
1089 infrastructure*.  To do otherwise would have penalized the performance
1090 of *all* applications in order to handle the relatively infrequent
1091 case where you want to be able to swap mechanisms at run-time.
1093 Since it is straightforward to create an abstract class like the one
1094 you describe above I decided to make this a "layered" service rather
1095 than use this mechanism in the core of ACE.
1097 BTW, I would not modify TLI_SAP and SOCK_SAP to inherit from a new
1098 class. Instead, I would use the Bridge and Adapter patterns from the
1099 "Gang of Four" patterns catalog and do something like this:
1101 ----------------------------------------
1102 // Abstract base class
1103 class ACE_IPC_Stream
1105 public:
1106         virtual ssize_t recv (void *buf, size_t bytes) = 0;
1107         virtual ssize_t send (const void *buf, size_t bytes) = 0;
1108         virtual ACE_HANDLE get_handle (void) const = 0;
1109         // ...
1111 ----------------------------------------
1113 and then create new classes like 
1115 ----------------------------------------
1116 template <class IPC>
1117 class ACE_IPC_Stream_T : public ACE_IPC_Stream
1119 public:
1120         virtual ssize_t recv (void *buf, size_t bytes)
1121         {
1122                 return this->ipc_.recv (buf, bytes);
1123         }
1125         virtual ssize_t send (const void *buf, size_t bytes)
1126         {
1127                 return this->ipc_.send (buf, bytes);
1128         }
1130         virtual ACE_HANDLE get_handle (void)
1131         {
1132                 return this->ipc_.get_handle ();
1133         }
1134         // ...
1136 private:
1137         IPC ipc_;
1138         // Target of delegation 
1139         // (e.g., ACE_SOCK_Stream or ACE_TLI_Stream).
1141 ----------------------------------------
1143 Then you could write code that operated on ACE_SAP *'s to get a
1144 generic interface, but that reused existing code like SOCK_SAP and
1145 TLI_SAP, e.g.,
1147 ----------------------------------------
1148 class My_Event_Handler : public ACE_Event_Handler
1150 public:
1151         My_Event_Handler (void) {
1152                 // Figure out which IPC mechanism to use somehow:
1153                 
1154                 if (use_tli)
1155                         this->my_ipc_ = new ACE_SAP_IPC<ACE_TLI_Stream>;
1156                 else if (use_sockets)
1157                         this->my_ipc_ = new ACE_SAP_IPC<ACE_SOCK_Stream>;
1158                 else
1159                         ...
1160         }
1162 private:
1163         ACE_IPC_Stream *my_ipc_;
1165 ----------------------------------------
1167 There are obviously details left out here, but this is the general idea.
1169 ----------------------------------------
1170 31. 
1172 > I was trying to view your 'Writting example applications in CORBA' article
1173 > /tutorial using ghostview but the .ps file seems to be corrupted ( I tried to
1174 > ftp it more than once). Any help would be much appreciated.
1176 There are two solutions to this problem (which seems to be caused by a
1177 weird interaction between ghostview and the "psnup" program I use to
1178 generate the slides 4-up on a page):
1180         1. If you want to print them or view them 1-up on a page you
1181            can edit the postscript file and remove the first 551
1182            lines or so (which are generated by the psnup script).
1183            This will cause the document to be printed 1-up rather than
1184            4-up.
1186         2. You can try to print the 4-up file on a postscript printer. 
1187            Believe it or not, this typically works, even though ghostview
1188            can't handle it!
1190 ----------------------------------------
1193 > We would like to use the Reactor class as a static member on some of
1194 > our classes (one per process) so that we can see and use the Reactor
1195 > witnin each process on a global level.  We are using it to set
1196 > timers several levels down in our class trees and don't want to pass
1197 > a pointer to it through all of our constructors.  My question is:
1198 > are there any static initialization dependencies that you know of
1199 > when using the default "do nothing" constructor of the Reactor that
1200 > could prevent use from using it as a static member variable?  Thanks
1201 > for any advice on this issue.
1203 The only problems you'll have are the typical ones about "order of
1204 initialization" of statics in separate files.  You'll also have to
1205 live with the default size of the I/O handler table, which probably
1206 isn't a problem since the max is something like 1024 or so.
1208 BTW, I solve this problem in ACE via the Service_Config::reactor,
1209 which is a static *pointer* to a Reactor.  If you really wanted to
1210 make this work nicely, you could use the Singleton pattern from the
1211 "Gang of Four" patterns catalog.  That should solve your problem even
1212 more elegantly!
1214 ----------------------------------------
1215 33. 
1216 > I just got the ACE-3.3 version and am trying it on the HP-UX.
1217 > I run into a small problem while cloning the directories that
1218 > might be worth fixing.
1220 > I made a directory called ACE_WRAPPERS/HP-UXA.09.05-g1, cd to it
1221 > and run "make -f ../Makefile clone".  when I look in src, I have:
1222 > Acceptor.C@ -> ../libsrc/Connection/Acceptor.C
1224 > However, ../libsrc does not exist.  It is not one of the CLONE
1225 > variables in ACE_WRAPPERS/Makefile.  I don't think you'd want to
1226 > clone libsrc too, since its files don't change.
1228 I think you can solve this problem as follows:
1230 % cd ACE_WRAPPERS
1231 % setenv ACE_ROOT $cwd
1232 % cd HP-UXA.09.05-g1
1233 % make -f ../Makefile clone
1234 % setenv ACE_ROOT $cwd
1235 % make
1237 That should build the links correctly since they'll point to the
1238 absolute, rather than relative, pathnames!
1240 ----------------------------------------
1243 > Our quality personal has asked me the following questions for which
1244 > I think you are the right guy for answering that:
1246 > o How long is ACE used in industrial products?
1248 It was first used at Ericsson starting in the fall of 1992, so that
1249 makes it about 3 years now.
1251 > o What are reference projects comparable to ours that use ACE?
1253 The ones I have directly worked with include:
1255 Motorola -- satellite communication control
1256 Kodak Health Imaging Systems -- enterprise medical imaging
1257 Siemens -- enterprise medical imaging
1258 Ericsson/GE Mobile Communications -- telecommunication switch management
1259 Bellcore -- ATM switch signal software
1261 In addition, there are probably about 100 or more other companies that
1262 have used ACE in commercial products.  The current mailing list has
1263 about 300 people from about 230 different companies and universities.
1264 If you'd like additional info, please let me know.
1266 > o How many persons have contributed on testing and writing error
1267 > reports for ACE?
1269 Around 60 or so.  All the contributors are listed by name and email
1270 address at the end of the README file distributed with the ACE release.
1272 > o How many bug fixes have been made since ACE was public domain?
1274 All information related to bug fixes is available in the ChangeLog
1275 file distributed with the ACE release (I could count these for you if
1276 you need that level of detail).
1278 > o How many literature is there on ACE?
1280 All articles published about ACE are referenced in the BIBLIOGRAPHY
1281 file in the top-level directory of ACE.
1283 ----------------------------------------
1287 > We are currently evaluating ACE for use on a new telecom switch.
1288 > Many of us like ACE but are having trouble convincing some team
1289 > members that wrappers are better than using the direct Unix
1290 > system calls.
1292 > I have read your papers that came with ACE, but was wondering if there
1293 > are other papers that address the benefits (or problems) of wrappers?
1295 This topic has been discussed in other places, most notably the book
1296 by Erich Gamma and Richard Helm and Ralph Johnson and John Vlissides
1297 called "Design Patterns: Elements of Reusable Object-Oriented
1298 Software" (Addison-Wesley, 1994), where it is described in terms of
1299 the "Adapter" pattern.
1301 Very briefly, there are several key reasons why you should *not* use
1302 UNIX system calls directly (regardless of whether you use ACE or not).
1304 1. Portability -- 
1306         Unless you plan to develop code on only 1 UNIX platform (and
1307         you never plan to upgrade from that platform as it goes
1308         through new releases of the OS) you'll run across many, many
1309         non-portable features.   It's beyond the scope of this
1310         FAQ to name them all, but just take a look at ACE sometime
1311         and you'll see all the #ifdefs I've had to add to deal with
1312         non-compatible OSs and compilers.  Most of these are centralized
1313         in one place in ACE (in the ace/OS.*files), but it took a lot
1314         of work to factor this out.  By using wrappers, you can avoid
1315         most of this problem in the bulk of your application code
1316         and avoid revisiting all of these issues yourself.
1318         In addition, ACE is now ported to other platforms (e.g.,
1319         Windows NT and Windows 95).  If you want to write code that
1320         is portable across platforms, wrappers are a good way to
1321         accomplish this. 
1323 2. Ease of programming --
1325         I'd go as far as to say that anyone who wants to program
1326         applications using C-level APIs like sockets or TLI is not
1327         serious about developing industrial strength, robust, and easy
1328         to maintain software.  Sockets and TLI are *incredibly*
1329         error-prone and tedious to use, in addition to being
1330         non-portable.  I've got a paper that discusses this in detail
1331         at URL http://www.cs.wustl.edu/~schmidt/PDF/COOTS-95.pdf
1332         
1333 3. Incorporation with higher-level patterns and programming methods -- 
1335         Here's where the Adapter pattern stuff really pays
1336         off.  For example, by making all the UNIX network
1337         programming interfaces and synchronization mechanisms
1338         have the same API I can write very powerful higher-level
1339         patterns (e.g., Connector and Acceptor) that generalize
1340         over these mechanisms.  For proof of this, take a look
1341         at the ./tests/Connection/non_blocking directory
1342         in the latest ACE-beta.tar.gz at wuarchive.wustl.edu
1343         in the /languages/c++/ACE directory.  It implements
1344         the same exact program that can be parameterized
1345         with sockets, TLI, and STREAM pipes *without*
1346         modifying any application source code.  It is 
1347         literally impossible to do this without wrappers.
1349 ----------------------------------------
1352 > How can I use a kind of "Reactor" in such a way that a reading
1353 > thread can notice the arrival of new data on several shared memory
1354 > areas ?
1356 Ah, that is a tricky issue!  The underlying problem is that UNIX is
1357 inconsistent with respect to the ability to "wait" on different
1358 sources of events.  In this case, Windows NT is much more consistent
1359 (but it has its own set of problems...).
1361 > Poll, Select and Reactor (so far I read) assume that file
1362 > descriptors are present, which is not the case with shared memory.
1364 That's correct (though to be more precise, the Reactor can also deal
1365 with signals, as I discuss below).  
1367 > Is there a common and efficient way to deal with that kind of
1368 > situation, or do I have to insert extra ipc mechanisms (based on
1369 > descriptors) ?
1371 There are several solutions:
1373 1. Use the Reactor's signal handling capability (see the
1374    ./tests/Reactor/misc/signal_tester.C for an example)
1375    and have the process/thread that writes to shared 
1376    data send a signal to the reader process(es).  The
1377    disadvantage of this is that your code needs to 
1378    be signal-safe now...
1380 2. Use a combination of SPIPE_Streams and the Reactor
1381    to implement a simple "notification protocol," e.g.,
1382    the receiver process has an Event_Handler with a
1383    SPIPE_Stream in it that can be notified when the
1384    sender process writes data to shared memory.
1385    The disadvantage here is that there's an extra
1386    trip through the kernel, though the overhead
1387    is very small since you only need to send 1 byte.
1389 3. Use threads and either bypass the Reactor altogether
1390    or integrate the threads with the Reactor using its
1391    Reactor::notify() mechanism (see the 
1392    ./tests/Reactor/misc/notification.C file for an
1393    example of how Reactor::notify() works).  The
1394    disadvantage of this approach is that it won't
1395    work for platforms that lack threads.
1397 ----------------------------------------
1400 > What do you think about wrapping communication methodologies in C++ streams?
1401 > What I mean is having defining a stream and extractor/insertor functions
1402 > which the underlying implementation reads/writes on comm mechanisms instead of
1403 > files.  I would think this to be a very general interface for all comms
1404 > implementations.  All user code would look the same, but the underlying stream
1405 > implementations would be different.  Whether the stream functionality would
1406 > be defined by the stream itself (eg tcpstream) or with manipulators
1407 > (eg commstream cs; cs << tcp;) is up for grabs in my mind.
1409 > Anyhow, I was wondering your input...
1411 That technique has been used for a long time.  In fact, there are
1412 several freely available versions of iostreams that do this and
1413 RogueWave also sells a new product (Net.h++) that does this.  I think
1414 this approach is fine for simple applications.
1416 However, it doesn't really work well if you need to write
1417 sophisticated distributed applications that must use features like
1418 non-blocking I/O, concurrency, or that must be highly robust against
1419 the types of errors that occur in a distributed system.
1421 For these kinds of systems you either need some type of ORB, or you
1422 need to write the apps with lower-level C++ wrappers like the ones
1423 provided by ACE.
1425 ----------------------------------------
1429 > What is the difference between cont() and next() in an ACE_Message_Block?
1431 Ah, good question.  cont() gives you a pointer to the next
1432 Message_Block in a chain of Message_Block fragments that all belong to
1433 the same logical message.  In contrast, next() (and prev()) return
1434 pointers to the next (and previous) Message_Block in the doubly linked
1435 list of Message_Blocks on a Message_Queue.  
1437 BTW, this is *exactly* the same structure as in System V Streams...
1439 > Which would I use if I wanted to add a header and a trailer, each stored in
1440 > ACE_Message_Blocks of their own, to another ACE_Message_Block?
1442 You should use cont() for that.  Does that make sense?
1443 ----------------------------------------
1447 > I think that your site is cool, but it's being a terrible tease in
1448 > that I really want to read the contents, but don't know anything
1449 > about x-gzip formatting.  I'm running Netscape 2.0 under MS Windows
1450 > NT.
1452 To view PostScript files under Win32 you will need a PostScript 
1453 viewer such as GSview.  You can find GSview and Ghostscript (which is
1454 needed to run GSview) at http://www.cs.wisc.edu/~ghost/.  
1456 It seems that both Netscape and Internet Explorer mangles the names 
1457 of downloaded files to reflect their content type, so *.ps.gz files 
1458 are saved as *_ps.ps instead.  Fortunately, GSview as of version 2.2
1459 supports gzip compressed postscript.  When set up as a viewer for
1460 Postscript files, files with mangled names can be viewed by GSview 
1461 without any preprocessing.
1463 ----------------------------------------
1465 40. 
1467 > What I am doing is
1468 > 1. Making an ACE_SOCK_Dgram and let it choose the next available port number.
1469 > 2. Making a message that will be broadcasted to X number of servers. This
1470 >    message has a port number which the server will use to send its reply.
1471 > 3. Broadcast the message to a fixed port number.
1472 > 4. Wait for replies from the servers.
1475 > It looks like I need "ACE::bind_port" to return the port number that
1476 > it picked and "ACE_SOCK_Dgram::shared_open" will need it store the
1477 > port number so I could call some function like
1478 > ACE_SOCK_Dgram::get_port_number or it would need to return the port
1479 > number instead of the handle(I could always call
1480 > ACE_SOCK_Dgram::get_handle if I needed the handle).
1482 > Is there I way to get the port number that I have missed?
1484 Sure, can't you just do this:
1486 // Defaults to all "zeros", so bind will pick port.
1487 ACE_INET_Addr dg_addr;
1489 ACE_SOCK_Dgram dg;
1491 dg.open (dg_addr);
1493 dg.get_local_addr (dg_addr);
1495 dg_addr.get_port_number ();
1497 ----------------------------------------
1499 41. How can you rename a core file?
1501 new_disposition.sa_handler = &Handle_Coredump_Signal;
1502 sigemptyset(&new_disposition.sa_mask);
1503 sigaddset(&new_disposition.sa_mask,SIGCHLD);
1504 new_disposition.sa_flags = 0;
1505 sigaction(SIGSEGV,&new_disposition,&old_disposition);
1507 *****************
1509 void
1510 Handle_Coredump_Signal(void)
1512     int   status;
1513     pid_t child;
1514     char  new_core_name[64];
1515     
1516     if(0 == (child = fork()))
1517     {
1518         abort();
1519     }
1520     else
1521     {
1522         if(-1 == waitpid(child,&status,NULL))
1523         {
1524             exit(-1);
1525         }
1526         sprintf(new_core_name,"core_%d",getpid());
1527         rename("core",new_core_name);
1528         exit(0);
1529     }
1532 ----------------------------------------
1534 42. 
1536 > I have seen 2 different inlining policies in ACE
1538 > 1) The .i file is included unconditionally by both the .h and .C file
1539 >    and all functions in the .i file carry the "inline" keyword.
1541 Right.  Those are for cases where I *always* want to inline those
1542 methods.  I do this mostly for very short wrapper methods (e.g.,
1543 read() or write()) that are likely to be on the "fast path" of an
1544 application.
1546 > 2) The .i file is included by the .h file ONLY if __INLINE__ is defined
1547 >    for the compile.  This causes the functions in the .i file to be
1548 >    compiled as inline functions (INLINE translates to inline in this case).
1549 >    If __INLINE__ is not defined, the .i file is only included by the .C
1550 >    file and the functions do NOT carry the "inline" keyword.
1552 I do this for cases where it's really not essential to have those
1553 methods inline, but some users might want to compile ACE that was if
1554 they want to eliminate all the wrapper function-call overhead.  For
1555 instance, I'll typically do this when I'm running benchmarks.
1557 ----------------------------------------
1559 43. Integrating ACE and CORBA
1561 > Our goal is to implement a CORBA-II compliant application.  I am
1562 > trying to conceptually visualize the applicability to ACE to this
1563 > attempt (which we're pretty excited about), and I was hoping you'd
1564 > offer any opinions / observations that you might have.
1566 We've successfully integrated ACE with several implementations of
1567 CORBA (in particular Orbix 1.3 and 2.0) and used it in a number of
1568 commercial applications.  In these systems, we use ACE for a number of
1569 tasks, including the following:
1571 1. Intra-application concurrency control, threading, and
1572    synchronization via the ACE_Thread_Manager and Synch* classes. 
1573    
1574 2. Dynamic linking of services via the ACE_Service_Config.
1576 3. Integration of event loops via the ACE_Reactor.
1578 4. Management of shared memory via ACE_Malloc.
1580 5. High-performance network I/O via the ACE_SOCK* wrappers.
1582 plus many more.
1584 You can find out more info about the ACE/CORBA integration and the
1585 performance issues associated with it in the following paper:
1587 http://www.cs.wustl.edu/~schmidt/PDF/COOTS-96.pdf
1589 ----------------------------------------
1591 44. 
1593 > Can the Reactor's event loop be called recursively?
1595 This is not advisable.  The Reactor's dispatch() method is not
1596 reentrant (though it is thread-safe) since it maintains state about
1597 the active descriptors it is iterating over.  Therefore, depending on
1598 the descriptors you're selecting on, you could end up with spurious
1599 handle_*() callbacks if you make nested calls to the
1600 Reactor::handle_events() method.
1602 > For example, if I have a program that sets up some event handlers
1603 > and then calls, in an infinite loop, ACE_Reactor::handle_events().
1604 > Can one of the event handlers call handle_events() again if it needs
1605 > to block, while allowing other event handlers a chance to run?
1607 I'm not sure if this is really a good idea, even if the Reactor were
1608 reentrant.  In particular, what good does it do for one Event_Handler
1609 to "block" by calling handle_events() again?  The event the handler is
1610 waiting for will likely be dispatched by the nested handle_events()
1611 call!  So when you returned back from the nested call to
1612 handle_events() it will be tricky to know what state you were in and
1613 how to proceed.
1615 Here's how I design my single-threaded systems that have to deal with
1616 this:
1618         1. I use a single event loop based on the Reactor, which acts
1619            a cooperative multi-tasking scheduler/dispatcher.
1620            
1621         2. I then program all Event_Handler's as non-blocking I/O
1622            objects.  This is straightforward to do for both input and
1623            output using the ACE_Reactor::schedule_wakeup() and
1624            ACE_Reactor::cancel_wakeup() methods (available with the
1625            latest version of ACE).  
1626            
1627         3. Then, whenever an Event_Handler must block on I/O, it 
1628            queues up its state on an ACE_Message_Queue, calls
1629            ACE_Reactor::schedule_wakeup(), and returns to the 
1630            main event loop so that other Event_Handlers can be
1631            dispatched.  When the I/O is ready, the Reactor will
1632            call back to the appropriate handle_* method, which
1633            can pick up the state it left in the Message_Queue and
1634            continue. 
1636 There are a number of places to find more information on this sort of
1637 design:
1639         1. $ACE_ROOT/apps/Gateway/Gateway/Channel.cpp --
1640            This Gateway application example shows the C++ code.
1642         2. http://www.cs.wustl.edu/~schmidt/PDF/TAPOS-00.pdf --
1643            This paper describes the underlying patterns.
1645         3. http://www.cs.wustl.edu/~schmidt/PDF/OONP-tutorial4.pdf
1646            -- This tutorial explains the source code and 
1647            the patterns.
1649 BTW, I'll be describing patterns for this type of design challenge in
1650 my tutorial at USENIX COOTS in June.  Please check out
1651 http://www.cs.wustl.edu/~schmidt/COOTS-96.html for more info.
1653 ----------------------------------------
1655 45. 
1657 >   In one of my programs, a process needs to receive input from
1658 > multiple input sources. One of the input sources is a file
1659 > descriptor while another is a message queue. Is there a clean way to
1660 > integrate this a message queue source into the Reactor class so that
1661 > both inputs are handled uniformly?
1663 Do you have multiple threads on your platform?  If not, then life will
1664 be *very* tough and you'll basically have to use multiple processes to
1665 do what you're trying to do.  There is *no* portable way to combine
1666 System V message queues and file descriptors on UNIX, unfortunately.
1668 If you do have threads, the easiest thing to do is to have a thread
1669 reading the message queue and redirecting the messages into the
1670 Reactor via its notify() method.  
1672 Please take a look at the program called
1674 examples/Reactor/Misc/notification.cpp
1676 for an example.
1678 ----------------------------------------
1680 46. 
1682 > I'm writing a program to find out the address for a socket.  The
1683 > idea is that we open an ACE_Acceptor (and will eventually perform
1684 > accept() on it.)  Before we can do that we need to find out the
1685 > address of the ACE_Acceptor so that we can publish it (for others to
1686 > be able to connect to it.)  The trouble is that the call
1687 > ACE_INET_Addr::get_host_name () prints "localhost" as the host name
1688 > while I would like to principal host name to be printed instead.
1690 All ACE_INET_Addr::get_host_name() is doing is calling
1691 ACE_OS::gethostbyaddr(), which in turn will call the socket
1692 gethostbyaddr() function.  I suspect that what you should do is
1693 something like the following:
1695 ACE_Acceptor listener (ACE_Addr::sap_any);
1697 ACE_INET_Addr addr;
1699 listener.get_local_addr (addr);
1701 char *host = addr.get_host_name ();
1703 if (::strcmp (host, "localhost") == 0)
1705   char name[MAXHOSTNAMELEN];
1706   ACE_OS::hostname (name, sizeof name);
1707   cerr << name << endl;
1709 else
1710   cerr << host << endl;
1712 ----------------------------------------
1714 47. 
1716 > Could you please point me to stuff dealing with asynchronous cross
1717 > platform socket calls. I want to use non blocking socket calls on
1718 > both UNIX and NT.
1720 Sure, no problem.  Take a look at the
1722 ./examples/Connection/non_blocking/
1724 directory.  There are a number of examples there.  In addition, there
1725 are examples of non-blocking connections in 
1727 ./examples/IPC_SAP/SOCK_SAP/CPP-inclient.cpp
1729 The code that actually enables the non-blocking socket I/O is in
1730 ace/IPC_SAP.cpp
1732 ----------------------------------------
1736 > Is ACE exception-safe?  If I throw an exception out of event 
1737 > handler, will the Reactor code clean itself?
1739 Yes, that should be ok.  In general, the two things to watch out for
1740 with exceptions are:
1742         1. Memory leaks -- There shouldn't be any memory leaks internally
1743            to the Reactor since it doesn't allocate any memory when 
1744            dispatching event handlers.
1745           
1746         2. Locks -- In the MT_SAFE version of ACE, the Reactor acquires
1747            an internal lock before dispatching Event_Handler callbacks.
1748            However, this lock is controlled by an ACE_Guard, whose
1749            destructor will release the lock if exceptions are thrown
1750            from an Event_Handler.
1752 ----------------------------------------
1756 >   I am building a Shared memory manager object using MMAP and MALLOC
1757 > basically as:
1759 > typedef ACE_Malloc<ACE_MMAP_Memory_Pool, ACE_Process_Mutex> SHMALLOC;
1761 > I noticed that the ACE_MMAP_Memory_Pool class provides for the users
1762 > to specify a Semaphore key. However, once I use it via the
1763 > ACE_Malloc<..>::ACE_Malloc(const char* poolname) constructor, I lose
1764 > this option. 
1766 Yes, that is correct.  That design decision was made to keep a clean
1767 interface that will work for all the various types of memory pools.
1769 > Is there any recommended way to specialize ACE classes to allow this
1770 > key to be overridden?
1772 Yes indeed, you just create a new subclass (e.g., class
1773 My_Memory_Pool) that inherits from ACE_MMAP_Memory_Pool and then you
1774 pass in the appropriate key to the constructor of ACE_MMAP_Memory_Pool
1775 in the constructor of My_Memory_Pool.  Then you just say:
1777 typedef ACE_Malloc<My_Memory_Pool, ACE_Process_Mutex> SHMALLOC;
1779 Please check out the file:
1781 examples/Shared_Malloc/Malloc.cpp 
1783 which illustrates more or less how to do this.
1785 ----------------------------------------
1789 > What is the best way to turn on TRACE output in ACE.  I commented
1790 > out the #define ACE_NTRACE 1 in config.h and rebuilt ACE and the
1791 > examples.
1793 The best way to do this is to say
1795 #define ACE_NTRACE 0
1797 in config.h.
1799 > When I run the CPP-inserver example in examples/IPC_SAP/SOCK_SAP, I
1800 > get some trace output but not everything I would expect to see.
1802 Can you please let me know what you'd expect to see that you're not
1803 seeing?  Some of the ACE_TRACE macros for the lower-level ACE methods
1804 are commented out to avoid problems with infinite recursion (i.e.,
1805 tracing the ACE_Trace calls...).  I haven't had a chance to go over
1806 all of these indepth, but I know that it should be possible to turn
1807 many of them back on.
1809 > It would be nice to have a runtime option for turning trace on and
1810 > off.
1812 There already is.  In fact, there are two ways to do it.
1813 If you want to control tracing for the entire process, please check
1814 out ACE_Trace::start_tracing() and ACE_Trace::stop_tracing().  
1816 If you want to control tracing on a per-thread basis please take a
1817 look at the ACE_Log_Msg class.  There are methods called
1818 stop_tracing() and start_tracing() that do what you want.
1820 ----------------------------------------
1822 51. 
1824 > I've been using an acceptor and a connector in one (OS-) process.
1825 > What does happen, if a signal is sent to this process? Is the signal
1826 > processed by every ACE_Event_Handler (or its descendants) that is
1827 > around?  The manual page simply states that handle signal is called
1828 > as soon as a signal is triggered by the OS.
1830 How this signal is handled depends on several factors:
1832 1. Whether your using ACE_Sig_Handler or ACE_Sig_Handlers to register
1833    the signal handlers.
1835 2. If you're using ACE_Sig_Handler, then the ACE_Event_Handler * that
1836    you've most recently registered to handle the signal will
1837    have it's handle_signal() method called back by the Reactor.
1839 3. If you're using ACE_Sig_Handlers, then all of the ACE_Event_Handler *
1840    that you've register will be called back.
1842 For examples of how this works, please check out
1844 $ACE_ROOT/examples/Reactor/Misc/test_signals.cpp
1846 This contains a long comment that explains precisely how everything
1847 works!