summaryrefslogtreecommitdiff
path: root/ACE/FAQ
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/FAQ')
-rw-r--r--ACE/FAQ1847
1 files changed, 1847 insertions, 0 deletions
diff --git a/ACE/FAQ b/ACE/FAQ
new file mode 100644
index 00000000000..c184fbde84c
--- /dev/null
+++ b/ACE/FAQ
@@ -0,0 +1,1847 @@
+There are many changes and improvements in the new version of ACE.
+The ChangeLog file contains complete details about all of them.
+
+I've tested ACE thoroughly on Solaris 2.3 and 2.4 with the SunC++ 4.x
+compiler and Centerline 2.x. I've also tested it with the SunC++ 3.x
+compiler on the SunOS 4.x platform. However, I've not been able to
+test it on other platforms. If anyone has time to do that, and can
+report the results back to me I'd appreciate that.
+
+Please let me know if you have any questions or comments.
+
+ Doug
+
+----------------------------------------
+
+1. SIGHUP
+
+> 1) Where the heck does the HUP signal get registered for the
+> $ACE_ROOT/tests/Service_Configurator/server stuff? I looked there and
+> in $ACE_ROOT/libsrc/Service_Configurator. No luck. I guess I am
+> just blind from reading.
+
+ Take a look in ./libsrc/Service_Configurator/Service_Config.h.
+The constructor for Service_Config is where it happens:
+
+ Service_Config (int ignore_defaults = 0,
+ size_t size = Service_Config::MAX_SERVICES,
+ int signum = SIGHUP);
+
+----------------------------------------
+2. Multi-threaded Signal_Handler support
+
+> It appears Signal_Handler is
+> not setup for multi-threaded apps. How do you handle signals
+> in different threads? Do I have to put in the hooks in my app or should
+> it go in the Threads arena?
+
+ Ah, good question... My design follows the approach espoused
+by Sun. Basically, they suggest that you implement per-thread signal
+handling atop of the basic UNIX signal handlers (or in the case of
+ACE, the handle_signal() callbacks on Event_Handler subclasses) by
+using the thread id returned by thr_self() to index into a search
+structure containing the handlers. This should be pretty straight
+forward to layer atop the existing ACE Signal_Handler mechanisms.
+However, you might ask yourself whether you really want (1) separate
+signal handler *functionality* in different threads or (2) different
+threads that mask out certain signals. The latter might be easier to
+implement and reason about!
+
+----------------------------------------
+3. Problems compiling ACE with G++
+
+> I substituted -lg++ for -lC in macro_wrappers.GNU and ran make.
+>
+> Most stuff seemed to build. Continually got messages like the following:
+> ld: /usr2/tss/jvm/ACE_wrappers/lib/libASX.a: warning: archive has no table of c
+> ontents; add one using ranlib(1)
+> ld: /usr2/tss/jvm/ACE_wrappers/lib/libThreads.a: warning: archive has no table
+> of contents; add one using ranlib(1)
+> ld: /usr2/tss/jvm/ACE_wrappers/lib/libSPIPE.a: warning: archive has no table of
+> contents; add one using ranlib(1)
+> ld: /usr2/tss/jvm/ACE_wrappers/lib/libASX.a: warning: archive has no table of c
+> ontents; add one using ranlib(1)
+> ld: /usr2/tss/jvm/ACE_wrappers/lib/libThreads.a: warning: archive has no table
+> of contents; add one using ranlib(1)
+> ld: /usr2/tss/jvm/ACE_wrappers/lib/libSPIPE.a: warning: archive has no table of
+> contents; add one using ranlib(1)
+
+> no matter how many times I used ranlib or removed the libraries and re-compiled
+> or whatever. Perhaps these are System V specific and will not work on 4.1.3?
+
+ Yes, that's exactly right. If you look at the files, they all
+contain ifdef's for features that aren't included in the
+./include/makeinclude/wrapper_macros.GNU file. To make this more
+obvious, I've enclosed the following message in the ACE-INSTALL.html file:
+
+ * Sun OS 4.1.x
+
+ Note that on SunOS 4.x you may get warnings from the
+ linker that "archive has no table of contents; add
+ one using ranlib(1)" for certain libraries (e.g.,
+ libASX.a, libThreads.a, and libSPIPE.a). This
+ occurs since SunOS 4.x does not support these features.
+
+> never able to get .so -- assume these are shared libraries that gcc can not
+> deal with.
+
+ Yes, if you use the stock gcc/gas/gnu ld
+compiler/assembler/linker, you won't get shared libraries to work. It
+is possible to hack this by using the "collect" version of g++.
+However, as usual, I strongly advise people to stay away from g++ if
+you want to use shared libraries or templates.
+
+> got some linker errors as follows:
+>
+> g++ -g -DACE_NTRACE -DACE_HAS_MT_SAFE_SOCKETS -DACE_HAS_NO_T_ERRNO -DACE_HAS_
+> OLD_MALLOC -DACE_HAS_POLL -DACE_HAS_SEMUN -DACE_HAS_SETOWN -DACE_HAS_STRBUF_T -
+> DACE_HAS_STREAMS -DACE_HAS_SVR4_DYNAMIC_LINKING -DACE_HAS_TIUSER_H -DACE_HAS_SY
+> S_FILIO_H -DACE_PAGE_SIZE=4096 -DACE_HAS_ALLOCA -DACE_HAS_CPLUSPLUS_HEADERS -DA
+> CE_HAS_SVR4_SIGNAL_T -DACE_HAS_STRERROR -DMALLOC_STATS -I/usr2/tss/jvm/ACE_wrap
+> pers/include -I/usr2/tss/jvm/ACE_wrappers/libsrc/Shared_Malloc -o test_malloc
+> .obj/test_malloc.o -L/usr2/tss/jvm/ACE_wrappers/lib -Bstatic -lSemaphores -lS
+> hared_Malloc -lShared_Memory -lReactor -lThreads -lMem_Map -lLog_Msg -lFIFO -lI
+> PC_SAP -lMisc -lnsl -lg++
+> ld: /usr2/tss/jvm/ACE_wrappers/lib/libThreads.a: warning: archive has no table
+> of contents; add one using ranlib(1)
+> ld: Undefined symbol
+> _free__t6Malloc2Z18Shared_Memory_PoolZ13PROCESS_MUTEXPv
+> _free__t6Malloc2Z17Local_Memory_PoolZ10Null_MutexPv
+> _malloc__t6Malloc2Z18Shared_Memory_PoolZ13PROCESS_MUTEXUl
+> _malloc__t6Malloc2Z17Local_Memory_PoolZ10Null_MutexUl
+> _remove__t6Malloc2Z17Local_Memory_PoolZ10Null_Mutex
+> ___t6Malloc2Z17Local_Memory_PoolZ10Null_Mutex
+> _print_stats__t6Malloc2Z17Local_Memory_PoolZ10Null_Mutex
+> _remove__t6Malloc2Z18Shared_Memory_PoolZ13PROCESS_MUTEX
+> ___t6Malloc2Z18Shared_Memory_PoolZ13PROCESS_MUTEX
+> _print_stats__t6Malloc2Z18Shared_Memory_PoolZ13PROCESS_MUTEX
+> collect2: ld returned 2 exit status
+> gcc: file path prefix `static' never used
+> make[2]: *** [test_malloc] Error 1
+> make[2]: Leaving directory `/usr2/tss/jvm/ACE_wrappers/tests/Shared_Malloc'
+> <======== End all: /usr2/tss/jvm/ACE_wrappers/tests/Shared_Malloc
+
+ That looks like a problem that G++ has with templates. I
+don't know of any reasonable solution to this problem using g++.
+
+> Finally decided there was enough stuff that it looked like I might have some
+> thing so I tried to run some tests and could not find so much as one piece
+> of documentation that might give me some clue about running tests.
+
+You should take a look at ./tests/Service_Configurator/server/README
+file. That explains how to run the more complicated tests. As for
+the other tests, it is pretty straight forward if you look at the
+./tests/IPC_SAP/SOCK_SAP and ./tests/Reactor/* directory code to
+figure out how to run the tests. I don't have a Q/A department, so
+any documentation has to come from volunteers.
+
+----------------------------------------
+4. Is there any docs or man pages on the Log_Record class?
+
+There is a paper in the C++_wrappers_doc.tar.Z file on ics.uci.edu
+called reactor2.ps that has some examples of using Log_Record. The
+./apps/Logger directories show several examples using Log_Record.
+Finally, the source code for Log_Record is pretty short (though it
+clearly could be commented better ;-)).
+
+----------------------------------------
+5. Signal handling prototypes
+
+> According to the man page on sigaction on our system, that line
+> should look something like the following:
+>
+> sa.sa_handler = SIG_DFL;
+
+ The problem is that most versions of UNIX I've come across
+don't have a correct prototype for this field of struct sigaction.
+That's why I define two variants of signal handler typedefs: one that
+is a typedef of the "correct version" (which I call SignalHandler) and
+one of which is a typedef of the "incorrect version" (which I call
+SignalHandlerV). You might check out the sysincludes.h file to see
+how it is defining SignalHandlerV and make sure this matches what your
+OS/Compiler defines in <sys/signal.h>
+
+----------------------------------------
+6. Omitting shared libraries
+
+> Can anyone tell me a way to turn off the creation of the shared libraries
+> in the ACE build.
+
+You can simply comment out the LIB target in the $ACE_ROOT/ace/Makefile
+or change the BUILD target from
+
+BUILD = $(VLIB) $(VSHLIB) $(SHLIBA)
+
+to
+
+BUILD = $(VSHLIB) $(SHLIBA)
+
+----------------------------------------
+7. DCE threading and signal handling
+
+>Reading the DCE docs leaves me confused as to how to make everyone
+>work together in a happy hormonious whole. May basic need is to catch
+>asynchronous signals so i can release some global resources before
+>the process exits.
+
+You need to spawn a separate thread to handle signals. As part of
+your init, do this:
+ pthread_create(&tid, thread_attr, signal_catcher, NULL);
+ pthread_detach(&tid);
+
+Where signal_catcher is like this:
+static void *
+signal_catcher(void *arg)
+{
+ static int catch_sigs[] = {
+ SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGCHLD
+ };
+ sigset_t catch_these;
+ int i;
+ error_status_t st;
+
+ for ( ; ; ) {
+ sigemptyset(&catch_these);
+ for (i = 0; i < sizeof catch_sigs / sizeof catch_sigs[0]; i++)
+ sigaddset(&catch_these, catch_sigs[i]);
+ i = sigwait(&catch_these);
+ /* Note continue below, to re-do the loop. */
+ switch (i) {
+ default:
+ fprintf(stderr, "Caught signal %d. Exiting.\n", i);
+ CLEANUP_AND_EXIT();
+ /* NOTREACHED */
+#if defined(SIGCHLD)
+ case SIGCHLD:
+ srvrexec__reap();
+ continue;
+#endif /* defined(SIGCHLD) */
+ }
+ }
+ return NULL;
+}
+----------------------------------------
+8.
+
+> I have installed ACE2.15.5 on SunOS 4.1.3 with gcc2.6.0. I run the test program
+> ---server_test. The static is OK, but error found when I commented out the first
+> one and uncommented out the second one in the svc.conf file:
+>
+> #static Svc_Manager "-d -p 3912"
+> dynamic Remote_Brdcast Service_Object * .shobj/Handle_Broadcast.so:remote_broad
+> cast "-p 10001"
+>
+> The error goes like this:
+>
+> -----------
+> jupiter[12] %server_test -d
+> starting up daemon server_test
+> opening static service Svc_Manager
+> did static on Svc_Manager, error = 0
+> signal signal 1 occurred
+> beginning reconfiguration at Sat Feb 25 13:40:29 1995
+> Segmentation fault (core dumped)
+> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+My guess is that the code generated by GCC on SunOS 4.x does not
+correctly initialize static variables from shared libraries. The
+SunC++ 4.0.x compiler does this correctly on Solaris 2.x (though I
+believe that on SunOS 4.x it doesn't work without some extra coaxing).
+
+In general, I try to avoid using ACE's explicit dynamic linking
+mechanisms on SunOS 4.x and GCC. You can write plenty of interesting
+and useful code with ACE without using those features. Those tests
+are mostly there to illustrate the "proof of concept."
+----------------------------------------
+9.
+
+> a) I noticed the default constructor for the reactor does an open w/ defaults.
+> Does this mean I need to close it if I wish to re-open it with different
+> size and restart values?
+
+ No. With the latest versions of ACE, you can now just call
+open() with a new size and it will correctly resize the internal
+tables to fit.
+
+> b) What is the usage difference between the normal FD_Set objects
+> (rd/wr/ex_handle_mask_) and the ready FD_Set objects
+> (rd/wr/ex_handle_mask_ready)?
+
+ The normal FD_Sets (now called Handle_Set in ACE 3.0.5) holds
+the "waitable" descriptors (these are the descriptors given to
+select() or poll()). In contrast, the ready FD_Sets may be set by
+Event_Handler subclasses (by called the set_ready() API) to indicate
+to the Reactor that they want to be redispatched on the next go-round
+*without* blocking. If you look at the Reactor code, you'll see that
+the wait_for() method checks the ready sets first and doesn't block if
+there are any bits set in those masks. This features makes it
+possible for Event_Handlers to control subsequent dispatching policies
+of the Reactor.
+
+> c) What does the positive return value do from an event handler callback:
+> -1 detaches the event handler for that mask
+> 0 does nothing - keeps the event handler registered for that mask
+> >0 resets a bit in the current dispatching mask (I think) - does this mean
+> this event will be called again before the current dispatch cycle is done?
+
+Almost... (it's tied in with my description of the ready sets above).
+It means that once the Reactor finishes cycling through the set of
+descriptors it got back from select() or poll(), it will redispatch
+the ready set descriptors before sleeping.
+
+> Without direct access to the bit masks in X, I'm not sure I could emulate
+> this activity - what do you think?
+
+I'm not sure. I'm not enough of an X guru. Maybe someone else on the
+list knows the answer to this?
+
+> d) If I let X do the select blocking, will that have any affect on
+> the Reactor performing signal handling?
+
+ Yes, I think that will cause problems since the Reactor relies
+on a "handshake" between its Signal_Handler component and its
+handle_events loop to properly handle signals.
+
+> e) Is the Poll method preferred over Select if it is available - why?
+
+For systems that implement select() in terms of poll() (e.g., Solaris
+2.x) then it may be somewhat faster. Otherwise, it doesn't really
+matter since (1) they (should) do the same thing and (2) the end user
+shouldn't notice any change in behavior.
+
+----------------------------------------
+10.
+
+> I would very much like to evaluate/use the ACE Toolkit,
+> but am limited as to disk space on our system.
+> What is the total disk space required for a compiled,
+> usable toolkit?
+
+The source code itself is around 2 Meg, uncompressed.
+
+The compiled version of ACE is around 90 Meg compiled with the SunC++
+4.x compiler (naturally, this will differ with other compilers).
+However, of this amount, about 40 meg are for the libraries, and
+another 50 meg are for the test programs. Naturally, you don't need
+to keep the test programs compiled.
+
+The postscript documentation is around 5 Meg, compressed.
+
+----------------------------------------
+11.
+
+> This is regarding the newer release of ACE and pertaining to the library
+> archive file. My question is, if all the ".o" files are archived into one
+> single "libACE.a", does it increase the size of the executable program?
+
+No. The use of a *.a file allows the linker to extract out only those
+*.o files that are actually used by the program.
+
+> If it does, then does a large executable program mean possibility of it being
+> slower?
+
+ No.
+
+----------------------------------------
+12.
+
+> What happens if I have several reactors in a process (e.g. in different
+> threads)?
+>
+> Programmer 1 decides to register at reactor 1 in his thread 1 a signal handler
+> for SIGUSR.
+> Programmer 2 decides to register at reactor 2 in his thread 2 a signal handler
+> for SIGUSR.
+
+ Naturally, the behavior of this all depends on the semantics
+of the threads package... In Solaris 2.x, signal handlers are shared
+by all threads. Moreover, the Reactor uses a static table to hold the
+thread handlers. Thus, only one of the handler's would be registered
+(i.e., whichever one was registered second).
+
+> Programmer 3 designs the process and decides to have thread 1 and thread 2
+> running in the same process and also makes use of a third party software library
+> that internally has also registered a signal handler (not at the reactor) for
+> SIGUSR.
+
+ Now you've got big problems! This is an example of a
+limitation with UNIX signal handlers... In general, it's a bad idea
+to use signal handlers if you can avoid it. This is yet another
+reason why.
+
+> When looking into Ace/ACE_wrappers/tests/Reactor/misc/signal_tester.C you
+> have shown a way to do this by marking the dummy file_descriptor of the
+> Sig_Handler object ready for reading asynchronously. The handle_input()
+> routine of Sig_Handler object will then be dispatched synchronously.
+> But what happens if I have several reactors.
+> The asynchronously dispatched
+> handle_signal() routine does not know via which reactor it has been registered
+> so in which reactor to modify the dummy file_descriptor.
+> Is your suggestion to have just one process global reactor in such a case?
+
+ Yes, precisely. I would *strongly* recommend against using
+several reactors within separate threads within the same process if
+you are going to be having them handle signals. Can you use 1
+reactor and/or have one reactor handle signals within a process?
+
+> One thing we want to do is the priorization of Event_Handlers. I.e. in case
+> of concurrent events the sequence in which the Event_Handler methods will be
+> activated depends on their priority relative to each other.
+> We have two choices:
+> - complete priorization, which means a high priority Input Event_Handler may
+> be activated prior to a lower prioritized Output Event_Handler (and doing
+> so violating the 'hardcoded rule' that output must be done prior to input).
+> - priorization only in categories, which means all Output Event_handler are
+> ordered by their priority regardless of priorities for the category of Input
+> Event_Handlers. The priority is fixed between the categories, i.e. first
+> output then input then out-of-band.
+>
+> Right now I would think that we have to use the second choice if we want to
+> use the feature of asynchronous output with automatical re-queueing. Am I right
+> ?
+
+ Hum, that's an interesting problem. It might be better to
+subclass the Reactor to form a new class called Priority_Reactor.
+This subclass would override the Reactor's dispatch method and
+dispatch the event handlers in "priority" order. I've never done
+that, but I don't think it would be all that difficult.
+
+----------------------------------------
+13.
+
+> Is the Orbix (aka CORBA) version still around?
+
+Nope, IONA does not support Orbix-2.X nor Orbix-3.0 anymore (the
+versions of Orbix that the ACE code was based upon). Plus we didn't
+maintain this code for ages, so it probably was broken too.
+
+----------------------------------------
+14.
+> We are using your ACE software and ran into a problem which may or may not
+> be related to the mutex locks. The question may have more to do with how
+> mutex locks should be used. We had a class which was using your mutex
+> lock wrapper. Each member function of the class acquired the lock before
+> processing and released on exiting the function. Some member functions may
+> call other member functions. The following is an example:
+>
+> class foo {
+>
+> void a()
+> {
+> MT( Mutex_Block<Mutex> m( this->lock_ ));
+>
+> if( cond )
+> b();
+> }
+>
+> void b()
+> {
+> MT( Mutex_Block<Mutex> m( this->lock_ ));
+>
+> if( cond )
+> a();
+> }
+>
+> };
+>
+> Is this valid ? My assumtpion is that the mutex lock is recursive and
+> the same thread can acquire the lock multiple times in different member
+> functions.
+
+ Ah, that's a great question since there are subtle and
+pernicious problems lurking in the approach you are trying above.
+Basically, Solaris mutex locks are *not* recursive (don't ask why...)
+Thus, if you want to design an application like the one above you'll
+need to use one or more of the following patterns:
+
+----------------------------------------
+A. Use recursive mutexes. Although these are not available in
+ Solaris directly they are supported in the later versions
+ of ACE. You might want to take a look at the latest
+ version (./gnu/ACE-3.1.9.tar.Z). It's got lots of new
+ support for threading and synchronization. In that case,
+ you simply do the following:
+
+ class Foo
+ {
+ public:
+ void a()
+ {
+ MT( Guard<Recursive_Lock <Mutex> > m( this->lock_ ));
+ b ();
+ }
+
+ void b()
+ {
+ MT( Guard<Recursive_Lock <Mutex> > m( this->lock_ ));
+ b_i ();
+ }
+
+ };
+
+ The advantage with this is that it requires almost no
+ changes to existing code. The disadvantage is that
+ recursive locks are just slightly more expensive.
+
+B. Have two layers of methods (a) which are public and acquire
+ the Mutex and then call down to methods in layer (b), which
+ are private and do all the work. Methods in layer b assume
+ that the locks are held. This avoids the deadlock problem
+ caused by non-recursive mutexes. Here's what this approach
+ looks like (using the more recent ACE class names):
+
+ class Foo
+ {
+ public:
+ void b()
+ {
+ MT( Guard<Mutex> m( this->lock_ ));
+ b_i ();
+ }
+
+ void b_i()
+ {
+ if( cond )
+ a_i();
+ }
+
+ void a_i()
+ {
+ if( cond )
+ b_i();
+ }
+
+ void a()
+ {
+ MT( Guard<Mutex> m( this->lock_ ));
+ a_i ();
+ }
+
+ };
+
+ The advantage here is that inline functions can basically
+ remove all performance overhead. The disadvantage is that
+ you need to maintain two sets of interfaces.
+
+C. Yet another approach is to release locks when calling
+ other methods, like this:
+
+ class Foo
+ {
+ public:
+ void b()
+ {
+ MT( Guard<Mutex> m( this->lock_ ));
+ m.release ();
+ a ();
+ m.acquire ();
+ }
+
+ void a()
+ {
+ MT( Guard<Mutex> m( this->lock_ ));
+ m.release ();
+ b ();
+ m.acquire ();
+ }
+
+ };
+
+ The disadvantage with this, of course, is that you
+ greatly increase your locking overhead. In addition,
+ you need to be very careful about introducing race
+ conditions into the code. The primary reason for
+ using this approach is if you need to call back to
+ code that you don't have any control over (such as
+ OS I/O routines) and you don't want to hold the
+ lock for an indefinite period of time.
+----------------------------------------
+
+ BTW, all three of these patterns are used in the ACE Reactor
+class category. The Reactor has a number of fairly complex
+concurrency control and callback issues it must deal with and I've
+found it useful to use all three of these patterns jointly.
+
+ I'd be interested to hear any comments on these approaches.
+
+ Doug
+----------------------------------------
+15.
+
+> I am working on Solaris 2.3 and trying to understand how to get around
+> the problem of trying to open a Socket connection to a remote host that
+> is "dead". Of course you get a nice long process block if the socket
+> is in Blocking mode (TCP lets you know when you can continue - how polite).
+>
+> So how does a non-blocking connect work with respect to using
+> the Reactor and a SOCK_Stream object to coordinate the opening
+> of the connection? Do I wait on the OUTPUT event for the FD?
+> How do I know if the connect worked or possibly timed-out? Is
+> this a reliable approach (I read somewhere that this will only
+> work if the STREAMS module is at the top of the protocol stack
+> - MAN page I think)?
+
+An example of implementing this is in the Gateway sample application
+in the new ACE. It's also encapsulated in the Connector<> pattern of
+the Connection class category in ./libsrc/Connection. You may want to
+take a look at those two things for concrete usage examples.
+
+However, the basics of getting non-blocking to work are:
+- set socket to non-blocking
+- initiate connect() request
+- if connect() returned 0 you're connected
+- if connect() returned -1 and errno is EWOULDBLOCK (or EAGAIN, depending
+on where you are), then register an event handler for read and write events
+on the socket
+- any other errno value is fatal
+
+When an event is returned
+- no matter which event you get back (read or write), you may have gotten
+the event out of error. Thus, re-attempt the connect() and check to see if
+errno is EISCONN (if it's not there's a problem!)
+- if errno was EISCONN, the connection is ready to go, otherwise you must
+handle an error condition
+
+If you want to "time out" after a certain period of time, consider
+registering for a timer event with Reactor. If the timer goes off before
+the connection succeeds, close down the appropriate socket.
+
+> Is using a separate thread to make the connection a better way to avoid
+> the potentialy long block in the main thread during the connect call?
+
+You could do that, but it can all be accomplised in a single process using
+the facilities available.
+----------------------------------------
+16.
+
+> I was wondering, does the Reactor class have the ability to prioritize
+> activity on the registered event handlers?
+
+ The default strategy for the Reactor's dispatch routine
+(Reactor::dispatch) does not prioritize dispatching other than to
+dispatch callbacks in ascending order from 0 -> maxhandlep1.
+
+> We have a requirment to be able to process both real-time, as well as, stored
+> telemetry and ERMs concurrently. Real-time needs to be processed at a higher
+> priority than stored data. Our design is based on both real-time and stored
+> data coming into our process via separate sockets.
+
+ I can think of several ways to do this:
+
+ 1. Use dup() or dup2() to organize your sockets such that the
+ higher priority sockets come first in the Handle_Sets that
+ the Reactor uses to dispatch sockets. This is pretty easy
+ if you don't want to muck with the Reactor code at all.
+
+ 2. You could subclass Reactor::dispatch() and revise it so
+ that it dispatches according to some other criteria that
+ you define in order to ensure your prioritization of
+ sockets.
+
+BTW, I'm not sure what you mean by "real-time" but I assume that you
+are aware that there is no true "real-time" scheduling for network I/O
+in Solaris. However, if by "real-time" you mean "higher priority"
+then either of the above strategies should work fine.
+----------------------------------------
+17.
+
+> I compiled the new ACE 3.2.0 's apps/Gateway. The compiling went
+> through without any errors. But I could not get it running, neither single
+> threaded nor multi-threaded. The cc_config and rt_config files entries are given
+> below. Also the machine configurations are given below. Does it need some more
+> settings or some patch !!??
+
+ I believe you are seeing the effects of the dreaded Sun MP bug
+with non-blocking connects. The easy work around for now is simply to
+give the "-b" option to the Gateway::init() routine via the svc.conf
+file:
+
+dynamic Gateway Service_Object *.shobj/Gateway.so:_alloc_gatewayd() active
+ "-b -d -c cc_config -f rt_config"
+
+If you check line 137 of the Gateway::parse_args() method you'll see
+what this does.
+----------------------------------------
+18.
+
+How to get ACE to work with GCC C++ templates.
+
+The first and foremost thing to do is to get the latest version of GCC
+(2.7.2) and also get the template repository patches from
+
+ftp://ftp.cygnus.com/pub/g++/gcc-2.7.1-repo.gz
+
+This will get the ball rolling...
+
+Here is some more info on G++ templates courtesy of Medhi TABATABAI
+<Mehdi.TABATABAI@ed.nce.sita.int>:
+
+Where's the Template?
+=====================
+
+ C++ templates are the first language feature to require more
+intelligence from the environment than one usually finds on a UNIX
+system. Somehow the compiler and linker have to make sure that each
+template instance occurs exactly once in the executable if it is
+needed, and not at all otherwise. There are two basic approaches to
+this problem, which I will refer to as the Borland model and the
+Cfront model.
+
+Borland model
+ Borland C++ solved the template instantiation problem by adding
+ the code equivalent of common blocks to their linker; template
+ instances are emitted in each translation unit that uses them, and
+ they are collapsed together at run time. The advantage of this
+ model is that the linker only has to consider the object files
+ themselves; there is no external complexity to worry about. This
+ disadvantage is that compilation time is increased because the
+ template code is being compiled repeatedly. Code written for this
+ model tends to include definitions of all member templates in the
+ header file, since they must be seen to be compiled.
+
+Cfront model
+ The AT&T C++ translator, Cfront, solved the template instantiation
+ problem by creating the notion of a template repository, an
+ automatically maintained place where template instances are
+ stored. As individual object files are built, notes are placed in
+ the repository to record where templates and potential type
+ arguments were seen so that the subsequent instantiation step
+ knows where to find them. At link time, any needed instances are
+ generated and linked in. The advantages of this model are more
+ optimal compilation speed and the ability to use the system
+ linker; to implement the Borland model a compiler vendor also
+ needs to replace the linker. The disadvantages are vastly
+ increased complexity, and thus potential for error; theoretically,
+ this should be just as transparent, but in practice it has been
+ very difficult to build multiple programs in one directory and one
+ program in multiple directories using Cfront. Code written for
+ this model tends to separate definitions of non-inline member
+ templates into a separate file, which is magically found by the
+ link preprocessor when a template needs to be instantiated.
+
+ Currently, g++ implements neither automatic model. The g++ team
+hopes to have a repository working for 2.7.0. In the mean time, you
+have three options for dealing with template instantiations:
+
+ 1. Do nothing. Pretend g++ does implement automatic instantiation
+ management. Code written for the Borland model will work fine, but
+ each translation unit will contain instances of each of the
+ templates it uses. In a large program, this can lead to an
+ unacceptable amount of code duplication.
+
+ 2. Add `#pragma interface' to all files containing template
+ definitions. For each of these files, add `#pragma implementation
+ "FILENAME"' to the top of some `.C' file which `#include's it.
+ Then compile everything with -fexternal-templates. The templates
+ will then only be expanded in the translation unit which
+ implements them (i.e. has a `#pragma implementation' line for the
+ file where they live); all other files will use external
+ references. If you're lucky, everything should work properly. If
+ you get undefined symbol errors, you need to make sure that each
+ template instance which is used in the program is used in the file
+ which implements that template. If you don't have any use for a
+ particular instance in that file, you can just instantiate it
+ explicitly, using the syntax from the latest C++ working paper:
+
+ template class A<int>;
+ template ostream& operator << (ostream&, const A<int>&);
+
+ This strategy will work with code written for either model. If
+ you are using code written for the Cfront model, the file
+ containing a class template and the file containing its member
+ templates should be implemented in the same translation unit.
+
+ A slight variation on this approach is to use the flag
+ -falt-external-templates instead; this flag causes template
+ instances to be emitted in the translation unit that implements
+ the header where they are first instantiated, rather than the one
+ which implements the file where the templates are defined. This
+ header must be the same in all translation units, or things are
+ likely to break.
+
+ *See Declarations and Definitions in One Header: C++ Interface,
+ for more discussion of these pragmas.
+
+ 3. Explicitly instantiate all the template instances you use, and
+ compile with -fno-implicit-templates. This is probably your best
+ bet; it may require more knowledge of exactly which templates you
+ are using, but it's less mysterious than the previous approach,
+ and it doesn't require any `#pragma's or other g++-specific code.
+ You can scatter the instantiations throughout your program, you
+ can create one big file to do all the instantiations, or you can
+ create tiny files like
+
+ #include "Foo.h"
+ #include "Foo.cc"
+
+ template class Foo<int>;
+
+ for each instance you need, and create a template instantiation
+ library from those. I'm partial to the last, but your mileage may
+ vary. If you are using Cfront-model code, you can probably get
+ away with not using -fno-implicit-templates when compiling files
+ that don't `#include' the member template definitions.
+
+4. Placing a function that looks like this near the top of a .C file
+ that uses any inline template member functions permits proper inlining:
+
+ // #ifdef __GNUG__
+ // This function works around the g++ problem with inline template member
+ // calls not being inlined ONLY in the first block (in a compilation
+ // unit) from which they are called.
+ // This function is inline and is never called, so it does not produce
+ // any executable code. The "if" statements avoid compiler warnings about
+ // unused variables.
+ inline
+ void
+ gcc_inline_template_member_function_instantiator()
+ {
+ if ( (List<FOO> *) 0 );
+ }
+ // #endif // __GNUG__
+
+ other prerequisites:
+ -- All inline template member functions should be defined in
+ the template class header. Otherwise, g++ will not inline
+ nested inline template member function calls.
+ -- Template .h and .C files should NOT include iostream.h
+ (and therefore debugging.h).
+ This is because iostream.h indirectly includes other
+ GNU headers that have unprotected #pragma interface,
+ which is incompatible with -fno-implicit-templates and optimal
+ space savings.
+ -- inline virtual destructors will not be inlined, unless necessary,
+ if you want to save every last byte
+ -- be sure that -Winline is enabled
+
+----------------------------------------
+19.
+
+> 1. when are dynamically loaded objects removed from the Service_Config.
+
+The Service Configurator calls dlclose() when a "remove Service_Name"
+directive is encountered in the svc.conf file (or programmatically
+when the Service_Config::remove() method is invoked). Check out the
+code in ./libsrc/Service_Config/Service_Repository.i and
+./libsrc/Service_Config/Service_Config.i to see exactly what happens.
+
+> 2. In the Service Configurator, when an item is entered in the svc.conf
+> how dow you know which items will be invoked as threads and
+> which items are forked. I know that static items are executed
+> internally.
+
+ No! It's totally up to the subclass of Service_Object to
+decide whetehr threading/forking/single-threading is used. Check out
+the ./apps/Logger/Service_Configurator_Logger for examples of
+single-threaded and multi-threaded configuration.
+----------------------------------------
+20.
+
+> I have been reading the Service Configurator Logger. I was wondering about
+> cleanup of new objects. In the handle_input method for the Acceptor a new
+> svc_handler is allocated for each new input request and deleted in the
+> handle_close. I was wondering how handle close was called when a client who
+> has created a socket terminates the connection (i.e., when is handle_close
+> called).
+
+handle_close() is automatically called by the Reactor when a
+handle_input()/handle_output()/etc. method returns -1. This is the
+"hook" that instructs the Reactor to call handle_**() and then remove
+the Event_Handler object from its internal tables.
+
+----------------------------------------
+21.
+
+> How does the Logger know to remove the client socket and the svc_handler object.
+> Does he recieve an exception.
+
+ No. when the client terminates the underlying TCP/IP
+implementation sends a RESET message to the logger host. This is
+delivered to the logger process as a 0-sized read(). It then knows to
+close down.
+
+> What I am worried about is a leak. Where by alot of clients connect and
+> disconnect and the server does not cleanup correctly. Such as a core dump
+> from the client where he cannot close correctly.
+
+ That's handled by the underlying TCP (assuming it is
+implemented correctly...).
+
+> What I am doing is attempting to convert the logger example into an alarm
+> manager for remote nodes. In this application a node may be powered down
+> there by terminating a Logger/Alarm server connection abnormally, this could
+> leave the Logger with many dangling sockets and allocated svc_handler objects.
+
+ If the TCP implementation doesn't handle this correctly then
+the standard way of dealing with it is to have an Event_Handler use a
+watchdog timer to periodically "poll" the client to make sure it is
+still connected. BTW, PCs tend to have more problems with this than
+UNIX boxes since when they are turned off the TCP implementation may
+not be able to send a RESET...
+----------------------------------------
+22.
+
+Using templates with Centerline.
+
+Centerline uses ptlink to process the C++ templates. ptlink expect the
+template declarations and definitions (app.h and app.C) to reside in
+the same directory. This works fine for the ACE hierarchy since
+everything is a link to the appropriate src directory (include/*.[hi]
+--> ../src/). When a users of the ACE distribution attempts to include
+the ACE classes in an existing application hierarchy this problem will
+arise if ptlink is used.
+
+The solution is to create a link to the declaration file from the
+definition file directory and use the "-I" to point to the definition
+directory.
+
+----------------------------------------
+
+23.
+
+> When I try to compile $ACE_ROOT/src/Message_Queue.C on a Solaris
+> 5.3 system using SUNPro CC 4.0, the compiler aborts with a Signal 10
+> (Bus Error). Our copy of CC 4.0 is over a year old and I do not
+> know if any patches or upgrades exist for it. If they do, then we
+> have not applied them to our compiler.
+
+ Several other people have run across this as well. It turns
+out that there is a bug in the Sun 4.0.0 C++ compiler that will get a
+bus error when -g is used. If you compilg Message_Queue.C *without*
+-g then it works fine. The later versions of SunC++ don't have this
+bug. I'd recommend that you upgrade as soon as possible.
+
+----------------------------------------
+
+24.
+
+> I have added a dynamic service to the Service Configurator. This new service
+> fails on the load because it uses application libraries that are not shared
+> object libraries (i.e., objects in libApp.a). I am assuming from the error
+> message that the problem is the mix match of shared and non-shared objects.
+
+ Right, exactly.
+
+> I was wondering if there is an easy way to add static services to the
+> Service Configurator. The example directory listing static service is
+> very tightly coupled with the Service_Config object. Is there another
+> way of adding static services.
+
+ Sure, that's easy. The best way to do this is to use the
+interfaces of the Service_Respository class to configure static
+services into the Service_Config. A good example of how to do this is
+in Service_Config.[Chi]:
+
+int
+Service_Config::load_defaults (void)
+{
+ for (Static_Svc_Descriptor *sl = Service_Config::service_list_; sl->name_ != 0; sl++)
+ {
+ Service_Type *stp = ace_create_service_type (sl->name_, sl->type_,
+ (const void *) (*sl->alloc_)(),
+ sl->flags_);
+ if (stp == 0)
+ continue;
+
+ const Service_Record *sr = new Service_Record (sl->name_, stp, 0, sl->active_);
+
+ if (Service_Config::svc_rep->insert (sr) == -1)
+ return -1;
+ }
+ return 0;
+}
+
+----------------------------------------
+25.
+
+> 8. Do you have examples of the SYNC/ASYNC pattern?
+
+ Yes. Check out the following:
+
+ 1. The latest version of ./apps/Gateway/Gateway has
+ an example of this when you compile with the USE_OUTPUT_MT
+ flag. In this case, the Reactor performs the "Async"
+ processing, which multiplexes all incoming messages from peers
+ arriving on Input_Channels. These messages are then queued
+ up at the appropriate Output_Channels. Each Output_Channel
+ runs in a separate thread, performing the "Sync"
+ processing.
+
+ 2. Also, the latest version of the OOCP-tutorial4.ps.gz
+ file available from wuarchive.wustl.edu in the
+ directory /languages/c++/ACE/ACE-documentation shows
+ an example of using the Half-Sync/Half-Async pattern
+ to build an Image Server. I'm using this as an
+ example in my tutorials these days.
+
+----------------------------------------
+26.
+
+> We had a discussion about something we saw in the new ACE code.
+> I thing there was a member function of a class that was doing a
+> "delete this". Is this safe?
+
+In general it is safe as long as (1) the object has been allocated
+dynamically off the heap and (2) you don't try to access the object
+after it has been deleted. You'll note that I tend to use this idiom
+in places where an object is registered with the Reactor, which must
+then must ensure the object cleans itself up when handle_close() is
+called. Note that to ensure (1) I try to declare the destructor
+"private" or "protected" so that the object must be allocated off the
+heap (some compilers have a problem with this, so I may not be as
+consistent as I ought to...).
+
+----------------------------------------
+27.
+
+> 5. What is the correct way for building a modified ACE library?
+> Changing in "libsrc" or in "include" directory?
+> When I make a complete new directory, how can I get introduced
+> the dependencies within my new makefile, can you give a short hint?
+
+Sure, no problem. For instance, here's what I did tonight when I
+added the new Thread_Specific.[hiC] files to ACE:
+
+ 1. Created three new files Thread_Specific.[hiC] in
+ ./libsrc/Threads.
+
+ 2. cd'd to ../../include/ace and did a
+
+ % ln -s ../../libsrc/Threads/Thread_Specific.[hi] .
+
+ 3. cd'd to ../../src and did a
+
+ % ln -s ../../libsrc/Threads/Thread_Specific.C .
+
+ 4. then I did
+
+ % make depend
+
+ on the ./src directory, which updated the dependencies.
+
+----------------------------------------
+28. The following is from Neil B. Cohen (nbc@metsci.com), who is
+ writing about how to work around problems he's found with HP/UX.
+
+I've been trying to compile the latest beta (3.2.9) on an HP running
+HPUX9.05 for the past week or so. I've had problems with templates up
+and down the line. I finally discovered (after some discussions with
+the HP support people) that they have made numerous changes to their
+C++ compiler recently to fix problems with templates and
+exceptions. If you are trying to compile ACE under HPUX with anything
+less than version 3.70 of the HP compiler, you may have serious
+problems (we were using v3.50 which came with the machine when we
+bought it a few months ago).
+
+Also, unlike earlier ACE versions, I was forced to add the following
+line to the rules.lib.GNU file to "close" the library - ie. force the
+various template files to be instantiated and linked to the ACE
+library itself. I don't know if this is necessary, or the only way to
+make things work, but it seems to do the job for my system.
+
+in rules.lib.GNU...
+
+$(VLIB): $(VOBJS)
+ - CC -pts -pth -ptb -ptv -I$(ACE_ROOT)/include $(VOBJS)
+ $(AR) $(ARFLAGS) $@ $? ./ptrepository/*.o
+ -$(RANLIB) $@
+ -chmod a+r $@
+
+I added the CC line, and added the "./ptrepository/*.o" to the $(AR)
+cmd. Sun has an -xar option, I believe that does something similar to
+this. Also - note that I'm not sure that the "-ptb" option is
+necessary. I added that before we upgraded the compiler, so it may not
+be needed now...
+
+----------------------------------------
+29.
+
+> I just ran my program with Purify, and it is telling me that there
+> is at least one large (~4k) memory leak in
+> ACE_Thread_Specific<ACE_Log_Msg>. This may or may not be serious,
+> but it is probably worth looking into.
+
+Right, that's ok. This is data that's allocated on a "per-thread"
+basis the first time a thread makes a call using the LM_ERROR or
+LM_DEBUG macros. The data isn't freed-up until the thread exits.
+
+----------------------------------------
+
+30.
+
+> In my trying to use the Reactor pattern for my application I
+> noticed that I had to couple my eventHandler derived objects with a
+> specific IPC_SAP mechanism. To use some of your own examples your
+> Client_Stream object contains a TLI_Stream object to use in data
+> transfer. My application calls for determining the communication
+> mechanism at run time. To do this my eventHandler must be able to
+> create the appropriate IPC_Stream object at run time and use its
+> methods through a super class casting. The problem is that there is no
+> super class with the virtual methods for send, recv, etc. To solve my
+> problem I will create that super class and have the TLI ( as well as
+> other wrapper objects) inherit from it instead of IPC_SAP. My question
+> is I am suspicious of why ACE wasn't designed with that in mind? Is my
+> application that unique ? or is there a better way to do this that I
+> am not aware of ? Your help in this matter will be much appreciated.
+
+ACE was developed using static binding for IPC_SAP in order to
+emphasize speed of execution over dynamic flexibility *in the core
+infrastructure*. To do otherwise would have penalized the performance
+of *all* applications in order to handle the relatively infrequent
+case where you want to be able to swap mechanisms at run-time.
+
+Since it is straightforward to create an abstract class like the one
+you describe above I decided to make this a "layered" service rather
+than use this mechanism in the core of ACE.
+
+BTW, I would not modify TLI_SAP and SOCK_SAP to inherit from a new
+class. Instead, I would use the Bridge and Adapter patterns from the
+"Gang of Four" patterns catalog and do something like this:
+
+----------------------------------------
+// Abstract base class
+class ACE_IPC_Stream
+{
+public:
+ virtual ssize_t recv (void *buf, size_t bytes) = 0;
+ virtual ssize_t send (const void *buf, size_t bytes) = 0;
+ virtual ACE_HANDLE get_handle (void) const = 0;
+ // ...
+};
+----------------------------------------
+
+and then create new classes like
+
+----------------------------------------
+template <class IPC>
+class ACE_IPC_Stream_T : public ACE_IPC_Stream
+{
+public:
+ virtual ssize_t recv (void *buf, size_t bytes)
+ {
+ return this->ipc_.recv (buf, bytes);
+ }
+
+ virtual ssize_t send (const void *buf, size_t bytes)
+ {
+ return this->ipc_.send (buf, bytes);
+ }
+
+ virtual ACE_HANDLE get_handle (void)
+ {
+ return this->ipc_.get_handle ();
+ }
+ // ...
+
+private:
+ IPC ipc_;
+ // Target of delegation
+ // (e.g., ACE_SOCK_Stream or ACE_TLI_Stream).
+}
+----------------------------------------
+
+Then you could write code that operated on ACE_SAP *'s to get a
+generic interface, but that reused existing code like SOCK_SAP and
+TLI_SAP, e.g.,
+
+----------------------------------------
+class My_Event_Handler : public ACE_Event_Handler
+{
+public:
+ My_Event_Handler (void) {
+ // Figure out which IPC mechanism to use somehow:
+
+ if (use_tli)
+ this->my_ipc_ = new ACE_SAP_IPC<ACE_TLI_Stream>;
+ else if (use_sockets)
+ this->my_ipc_ = new ACE_SAP_IPC<ACE_SOCK_Stream>;
+ else
+ ...
+ }
+
+private:
+ ACE_IPC_Stream *my_ipc_;
+};
+----------------------------------------
+
+There are obviously details left out here, but this is the general idea.
+
+----------------------------------------
+31.
+
+> I was trying to view your 'Writting example applications in CORBA' article
+> /tutorial using ghostview but the .ps file seems to be corrupted ( I tried to
+> ftp it more than once). Any help would be much appreciated.
+
+There are two solutions to this problem (which seems to be caused by a
+weird interaction between ghostview and the "psnup" program I use to
+generate the slides 4-up on a page):
+
+ 1. If you want to print them or view them 1-up on a page you
+ can edit the postscript file and remove the first 551
+ lines or so (which are generated by the psnup script).
+ This will cause the document to be printed 1-up rather than
+ 4-up.
+
+ 2. You can try to print the 4-up file on a postscript printer.
+ Believe it or not, this typically works, even though ghostview
+ can't handle it!
+
+----------------------------------------
+32.
+
+> We would like to use the Reactor class as a static member on some of
+> our classes (one per process) so that we can see and use the Reactor
+> witnin each process on a global level. We are using it to set
+> timers several levels down in our class trees and don't want to pass
+> a pointer to it through all of our constructors. My question is:
+> are there any static initialization dependencies that you know of
+> when using the default "do nothing" constructor of the Reactor that
+> could prevent use from using it as a static member variable? Thanks
+> for any advice on this issue.
+
+The only problems you'll have are the typical ones about "order of
+initialization" of statics in separate files. You'll also have to
+live with the default size of the I/O handler table, which probably
+isn't a problem since the max is something like 1024 or so.
+
+BTW, I solve this problem in ACE via the Service_Config::reactor,
+which is a static *pointer* to a Reactor. If you really wanted to
+make this work nicely, you could use the Singleton pattern from the
+"Gang of Four" patterns catalog. That should solve your problem even
+more elegantly!
+
+----------------------------------------
+33.
+> I just got the ACE-3.3 version and am trying it on the HP-UX.
+> I run into a small problem while cloning the directories that
+> might be worth fixing.
+>
+> I made a directory called ACE_WRAPPERS/HP-UXA.09.05-g1, cd to it
+> and run "make -f ../Makefile clone". when I look in src, I have:
+> Acceptor.C@ -> ../libsrc/Connection/Acceptor.C
+>
+> However, ../libsrc does not exist. It is not one of the CLONE
+> variables in ACE_WRAPPERS/Makefile. I don't think you'd want to
+> clone libsrc too, since its files don't change.
+
+I think you can solve this problem as follows:
+
+% cd ACE_WRAPPERS
+% setenv ACE_ROOT $cwd
+% cd HP-UXA.09.05-g1
+% make -f ../Makefile clone
+% setenv ACE_ROOT $cwd
+% make
+
+That should build the links correctly since they'll point to the
+absolute, rather than relative, pathnames!
+
+----------------------------------------
+34.
+
+> Our quality personal has asked me the following questions for which
+> I think you are the right guy for answering that:
+
+> o How long is ACE used in industrial products?
+
+It was first used at Ericsson starting in the fall of 1992, so that
+makes it about 3 years now.
+
+> o What are reference projects comparable to ours that use ACE?
+
+The ones I have directly worked with include:
+
+Motorola -- satellite communication control
+Kodak Health Imaging Systems -- enterprise medical imaging
+Siemens -- enterprise medical imaging
+Ericsson/GE Mobile Communications -- telecommunication switch management
+Bellcore -- ATM switch signal software
+
+In addition, there are probably about 100 or more other companies that
+have used ACE in commercial products. The current mailing list has
+about 300 people from about 230 different companies and universities.
+If you'd like additional info, please let me know.
+
+> o How many persons have contributed on testing and writing error
+> reports for ACE?
+
+Around 60 or so. All the contributors are listed by name and email
+address at the end of the README file distributed with the ACE release.
+
+> o How many bug fixes have been made since ACE was public domain?
+
+All information related to bug fixes is available in the ChangeLog
+file distributed with the ACE release (I could count these for you if
+you need that level of detail).
+
+> o How many literature is there on ACE?
+
+All articles published about ACE are referenced in the BIBLIOGRAPHY
+file in the top-level directory of ACE.
+
+----------------------------------------
+
+35.
+
+> We are currently evaluating ACE for use on a new telecom switch.
+> Many of us like ACE but are having trouble convincing some team
+> members that wrappers are better than using the direct Unix
+> system calls.
+
+> I have read your papers that came with ACE, but was wondering if there
+> are other papers that address the benefits (or problems) of wrappers?
+
+This topic has been discussed in other places, most notably the book
+by Erich Gamma and Richard Helm and Ralph Johnson and John Vlissides
+called "Design Patterns: Elements of Reusable Object-Oriented
+Software" (Addison-Wesley, 1994), where it is described in terms of
+the "Adapter" pattern.
+
+Very briefly, there are several key reasons why you should *not* use
+UNIX system calls directly (regardless of whether you use ACE or not).
+
+1. Portability --
+
+ Unless you plan to develop code on only 1 UNIX platform (and
+ you never plan to upgrade from that platform as it goes
+ through new releases of the OS) you'll run across many, many
+ non-portable features. It's beyond the scope of this
+ FAQ to name them all, but just take a look at ACE sometime
+ and you'll see all the #ifdefs I've had to add to deal with
+ non-compatible OSs and compilers. Most of these are centralized
+ in one place in ACE (in the ace/OS.*files), but it took a lot
+ of work to factor this out. By using wrappers, you can avoid
+ most of this problem in the bulk of your application code
+ and avoid revisiting all of these issues yourself.
+
+ In addition, ACE is now ported to other platforms (e.g.,
+ Windows NT and Windows 95). If you want to write code that
+ is portable across platforms, wrappers are a good way to
+ accomplish this.
+
+2. Ease of programming --
+
+ I'd go as far as to say that anyone who wants to program
+ applications using C-level APIs like sockets or TLI is not
+ serious about developing industrial strength, robust, and easy
+ to maintain software. Sockets and TLI are *incredibly*
+ error-prone and tedious to use, in addition to being
+ non-portable. I've got a paper that discusses this in detail
+ at URL http://www.cs.wustl.edu/~schmidt/PDF/COOTS-95.pdf
+
+3. Incorporation with higher-level patterns and programming methods --
+
+ Here's where the Adapter pattern stuff really pays
+ off. For example, by making all the UNIX network
+ programming interfaces and synchronization mechanisms
+ have the same API I can write very powerful higher-level
+ patterns (e.g., Connector and Acceptor) that generalize
+ over these mechanisms. For proof of this, take a look
+ at the ./tests/Connection/non_blocking directory
+ in the latest ACE-beta.tar.gz at wuarchive.wustl.edu
+ in the /languages/c++/ACE directory. It implements
+ the same exact program that can be parameterized
+ with sockets, TLI, and STREAM pipes *without*
+ modifying any application source code. It is
+ literally impossible to do this without wrappers.
+
+----------------------------------------
+36.
+
+> How can I use a kind of "Reactor" in such a way that a reading
+> thread can notice the arrival of new data on several shared memory
+> areas ?
+
+Ah, that is a tricky issue! The underlying problem is that UNIX is
+inconsistent with respect to the ability to "wait" on different
+sources of events. In this case, Windows NT is much more consistent
+(but it has its own set of problems...).
+
+> Poll, Select and Reactor (so far I read) assume that file
+> descriptors are present, which is not the case with shared memory.
+
+That's correct (though to be more precise, the Reactor can also deal
+with signals, as I discuss below).
+
+> Is there a common and efficient way to deal with that kind of
+> situation, or do I have to insert extra ipc mechanisms (based on
+> descriptors) ?
+
+There are several solutions:
+
+1. Use the Reactor's signal handling capability (see the
+ ./tests/Reactor/misc/signal_tester.C for an example)
+ and have the process/thread that writes to shared
+ data send a signal to the reader process(es). The
+ disadvantage of this is that your code needs to
+ be signal-safe now...
+
+2. Use a combination of SPIPE_Streams and the Reactor
+ to implement a simple "notification protocol," e.g.,
+ the receiver process has an Event_Handler with a
+ SPIPE_Stream in it that can be notified when the
+ sender process writes data to shared memory.
+ The disadvantage here is that there's an extra
+ trip through the kernel, though the overhead
+ is very small since you only need to send 1 byte.
+
+3. Use threads and either bypass the Reactor altogether
+ or integrate the threads with the Reactor using its
+ Reactor::notify() mechanism (see the
+ ./tests/Reactor/misc/notification.C file for an
+ example of how Reactor::notify() works). The
+ disadvantage of this approach is that it won't
+ work for platforms that lack threads.
+
+----------------------------------------
+37.
+
+> What do you think about wrapping communication methodologies in C++ streams?
+> What I mean is having defining a stream and extractor/insertor functions
+> which the underlying implementation reads/writes on comm mechanisms instead of
+> files. I would think this to be a very general interface for all comms
+> implementations. All user code would look the same, but the underlying stream
+> implementations would be different. Whether the stream functionality would
+> be defined by the stream itself (eg tcpstream) or with manipulators
+> (eg commstream cs; cs << tcp;) is up for grabs in my mind.
+>
+> Anyhow, I was wondering your input...
+
+That technique has been used for a long time. In fact, there are
+several freely available versions of iostreams that do this and
+RogueWave also sells a new product (Net.h++) that does this. I think
+this approach is fine for simple applications.
+
+However, it doesn't really work well if you need to write
+sophisticated distributed applications that must use features like
+non-blocking I/O, concurrency, or that must be highly robust against
+the types of errors that occur in a distributed system.
+
+For these kinds of systems you either need some type of ORB, or you
+need to write the apps with lower-level C++ wrappers like the ones
+provided by ACE.
+
+----------------------------------------
+
+38.
+
+> What is the difference between cont() and next() in an ACE_Message_Block?
+
+Ah, good question. cont() gives you a pointer to the next
+Message_Block in a chain of Message_Block fragments that all belong to
+the same logical message. In contrast, next() (and prev()) return
+pointers to the next (and previous) Message_Block in the doubly linked
+list of Message_Blocks on a Message_Queue.
+
+BTW, this is *exactly* the same structure as in System V Streams...
+
+> Which would I use if I wanted to add a header and a trailer, each stored in
+> ACE_Message_Blocks of their own, to another ACE_Message_Block?
+
+You should use cont() for that. Does that make sense?
+----------------------------------------
+
+39.
+
+> I think that your site is cool, but it's being a terrible tease in
+> that I really want to read the contents, but don't know anything
+> about x-gzip formatting. I'm running Netscape 2.0 under MS Windows
+> NT.
+
+To view PostScript files under Win32 you will need a PostScript
+viewer such as GSview. You can find GSview and Ghostscript (which is
+needed to run GSview) at http://www.cs.wisc.edu/~ghost/.
+
+It seems that both Netscape and Internet Explorer mangles the names
+of downloaded files to reflect their content type, so *.ps.gz files
+are saved as *_ps.ps instead. Fortunately, GSview as of version 2.2
+supports gzip compressed postscript. When set up as a viewer for
+Postscript files, files with mangled names can be viewed by GSview
+without any preprocessing.
+
+----------------------------------------
+
+40.
+
+> What I am doing is
+> 1. Making an ACE_SOCK_Dgram and let it choose the next available port number.
+> 2. Making a message that will be broadcasted to X number of servers. This
+> message has a port number which the server will use to send its reply.
+> 3. Broadcast the message to a fixed port number.
+> 4. Wait for replies from the servers.
+>
+>
+> It looks like I need "ACE::bind_port" to return the port number that
+> it picked and "ACE_SOCK_Dgram::shared_open" will need it store the
+> port number so I could call some function like
+> ACE_SOCK_Dgram::get_port_number or it would need to return the port
+> number instead of the handle(I could always call
+> ACE_SOCK_Dgram::get_handle if I needed the handle).
+>
+> Is there I way to get the port number that I have missed?
+
+Sure, can't you just do this:
+
+// Defaults to all "zeros", so bind will pick port.
+ACE_INET_Addr dg_addr;
+
+ACE_SOCK_Dgram dg;
+
+dg.open (dg_addr);
+
+dg.get_local_addr (dg_addr);
+
+dg_addr.get_port_number ();
+
+----------------------------------------
+
+41. How can you rename a core file?
+
+new_disposition.sa_handler = &Handle_Coredump_Signal;
+sigemptyset(&new_disposition.sa_mask);
+sigaddset(&new_disposition.sa_mask,SIGCHLD);
+new_disposition.sa_flags = 0;
+sigaction(SIGSEGV,&new_disposition,&old_disposition);
+
+*****************
+
+void
+Handle_Coredump_Signal(void)
+{
+ int status;
+ pid_t child;
+ char new_core_name[64];
+
+ if(0 == (child = fork()))
+ {
+ abort();
+ }
+ else
+ {
+ if(-1 == waitpid(child,&status,NULL))
+ {
+ exit(-1);
+ }
+ sprintf(new_core_name,"core_%d",getpid());
+ rename("core",new_core_name);
+ exit(0);
+ }
+}
+
+----------------------------------------
+
+42.
+
+> I have seen 2 different inlining policies in ACE
+>
+> 1) The .i file is included unconditionally by both the .h and .C file
+> and all functions in the .i file carry the "inline" keyword.
+
+Right. Those are for cases where I *always* want to inline those
+methods. I do this mostly for very short wrapper methods (e.g.,
+read() or write()) that are likely to be on the "fast path" of an
+application.
+
+> 2) The .i file is included by the .h file ONLY if __INLINE__ is defined
+> for the compile. This causes the functions in the .i file to be
+> compiled as inline functions (INLINE translates to inline in this case).
+> If __INLINE__ is not defined, the .i file is only included by the .C
+> file and the functions do NOT carry the "inline" keyword.
+
+I do this for cases where it's really not essential to have those
+methods inline, but some users might want to compile ACE that was if
+they want to eliminate all the wrapper function-call overhead. For
+instance, I'll typically do this when I'm running benchmarks.
+
+----------------------------------------
+
+43. Integrating ACE and CORBA
+
+> Our goal is to implement a CORBA-II compliant application. I am
+> trying to conceptually visualize the applicability to ACE to this
+> attempt (which we're pretty excited about), and I was hoping you'd
+> offer any opinions / observations that you might have.
+
+We've successfully integrated ACE with several implementations of
+CORBA (in particular Orbix 1.3 and 2.0) and used it in a number of
+commercial applications. In these systems, we use ACE for a number of
+tasks, including the following:
+
+1. Intra-application concurrency control, threading, and
+ synchronization via the ACE_Thread_Manager and Synch* classes.
+
+2. Dynamic linking of services via the ACE_Service_Config.
+
+3. Integration of event loops via the ACE_Reactor.
+
+4. Management of shared memory via ACE_Malloc.
+
+5. High-performance network I/O via the ACE_SOCK* wrappers.
+
+plus many more.
+
+You can find out more info about the ACE/CORBA integration and the
+performance issues associated with it in the following paper:
+
+http://www.cs.wustl.edu/~schmidt/PDF/COOTS-96.pdf
+
+----------------------------------------
+
+44.
+
+> Can the Reactor's event loop be called recursively?
+
+This is not advisable. The Reactor's dispatch() method is not
+reentrant (though it is thread-safe) since it maintains state about
+the active descriptors it is iterating over. Therefore, depending on
+the descriptors you're selecting on, you could end up with spurious
+handle_*() callbacks if you make nested calls to the
+Reactor::handle_events() method.
+
+> For example, if I have a program that sets up some event handlers
+> and then calls, in an infinite loop, ACE_Reactor::handle_events().
+> Can one of the event handlers call handle_events() again if it needs
+> to block, while allowing other event handlers a chance to run?
+
+I'm not sure if this is really a good idea, even if the Reactor were
+reentrant. In particular, what good does it do for one Event_Handler
+to "block" by calling handle_events() again? The event the handler is
+waiting for will likely be dispatched by the nested handle_events()
+call! So when you returned back from the nested call to
+handle_events() it will be tricky to know what state you were in and
+how to proceed.
+
+Here's how I design my single-threaded systems that have to deal with
+this:
+
+ 1. I use a single event loop based on the Reactor, which acts
+ a cooperative multi-tasking scheduler/dispatcher.
+
+ 2. I then program all Event_Handler's as non-blocking I/O
+ objects. This is straightforward to do for both input and
+ output using the ACE_Reactor::schedule_wakeup() and
+ ACE_Reactor::cancel_wakeup() methods (available with the
+ latest version of ACE).
+
+ 3. Then, whenever an Event_Handler must block on I/O, it
+ queues up its state on an ACE_Message_Queue, calls
+ ACE_Reactor::schedule_wakeup(), and returns to the
+ main event loop so that other Event_Handlers can be
+ dispatched. When the I/O is ready, the Reactor will
+ call back to the appropriate handle_* method, which
+ can pick up the state it left in the Message_Queue and
+ continue.
+
+There are a number of places to find more information on this sort of
+design:
+
+ 1. $ACE_ROOT/apps/Gateway/Gateway/Channel.cpp --
+ This Gateway application example shows the C++ code.
+
+ 2. http://www.cs.wustl.edu/~schmidt/PDF/TAPOS-00.pdf --
+ This paper describes the underlying patterns.
+
+ 3. http://www.cs.wustl.edu/~schmidt/PDF/OONP-tutorial4.pdf
+ -- This tutorial explains the source code and
+ the patterns.
+
+BTW, I'll be describing patterns for this type of design challenge in
+my tutorial at USENIX COOTS in June. Please check out
+http://www.cs.wustl.edu/~schmidt/COOTS-96.html for more info.
+
+----------------------------------------
+
+45.
+
+> In one of my programs, a process needs to receive input from
+> multiple input sources. One of the input sources is a file
+> descriptor while another is a message queue. Is there a clean way to
+> integrate this a message queue source into the Reactor class so that
+> both inputs are handled uniformly?
+
+Do you have multiple threads on your platform? If not, then life will
+be *very* tough and you'll basically have to use multiple processes to
+do what you're trying to do. There is *no* portable way to combine
+System V message queues and file descriptors on UNIX, unfortunately.
+
+If you do have threads, the easiest thing to do is to have a thread
+reading the message queue and redirecting the messages into the
+Reactor via its notify() method.
+
+Please take a look at the program called
+
+examples/Reactor/Misc/notification.cpp
+
+for an example.
+
+----------------------------------------
+
+46.
+
+> I'm writing a program to find out the address for a socket. The
+> idea is that we open an ACE_Acceptor (and will eventually perform
+> accept() on it.) Before we can do that we need to find out the
+> address of the ACE_Acceptor so that we can publish it (for others to
+> be able to connect to it.) The trouble is that the call
+> ACE_INET_Addr::get_host_name () prints "localhost" as the host name
+> while I would like to principal host name to be printed instead.
+
+All ACE_INET_Addr::get_host_name() is doing is calling
+ACE_OS::gethostbyaddr(), which in turn will call the socket
+gethostbyaddr() function. I suspect that what you should do is
+something like the following:
+
+ACE_Acceptor listener (ACE_Addr::sap_any);
+
+ACE_INET_Addr addr;
+
+listener.get_local_addr (addr);
+
+char *host = addr.get_host_name ();
+
+if (::strcmp (host, "localhost") == 0)
+{
+ char name[MAXHOSTNAMELEN];
+ ACE_OS::hostname (name, sizeof name);
+ cerr << name << endl;
+}
+else
+ cerr << host << endl;
+
+----------------------------------------
+
+47.
+
+> Could you please point me to stuff dealing with asynchronous cross
+> platform socket calls. I want to use non blocking socket calls on
+> both UNIX and NT.
+
+Sure, no problem. Take a look at the
+
+./examples/Connection/non_blocking/
+
+directory. There are a number of examples there. In addition, there
+are examples of non-blocking connections in
+
+./examples/IPC_SAP/SOCK_SAP/CPP-inclient.cpp
+
+The code that actually enables the non-blocking socket I/O is in
+ace/IPC_SAP.cpp
+
+----------------------------------------
+
+48.
+
+> Is ACE exception-safe? If I throw an exception out of event
+> handler, will the Reactor code clean itself?
+
+Yes, that should be ok. In general, the two things to watch out for
+with exceptions are:
+
+ 1. Memory leaks -- There shouldn't be any memory leaks internally
+ to the Reactor since it doesn't allocate any memory when
+ dispatching event handlers.
+
+ 2. Locks -- In the MT_SAFE version of ACE, the Reactor acquires
+ an internal lock before dispatching Event_Handler callbacks.
+ However, this lock is controlled by an ACE_Guard, whose
+ destructor will release the lock if exceptions are thrown
+ from an Event_Handler.
+
+----------------------------------------
+
+49.
+
+> I am building a Shared memory manager object using MMAP and MALLOC
+> basically as:
+>
+> typedef ACE_Malloc<ACE_MMAP_Memory_Pool, ACE_Process_Mutex> SHMALLOC;
+>
+> I noticed that the ACE_MMAP_Memory_Pool class provides for the users
+> to specify a Semaphore key. However, once I use it via the
+> ACE_Malloc<..>::ACE_Malloc(const char* poolname) constructor, I lose
+> this option.
+
+Yes, that is correct. That design decision was made to keep a clean
+interface that will work for all the various types of memory pools.
+
+> Is there any recommended way to specialize ACE classes to allow this
+> key to be overridden?
+
+Yes indeed, you just create a new subclass (e.g., class
+My_Memory_Pool) that inherits from ACE_MMAP_Memory_Pool and then you
+pass in the appropriate key to the constructor of ACE_MMAP_Memory_Pool
+in the constructor of My_Memory_Pool. Then you just say:
+
+typedef ACE_Malloc<My_Memory_Pool, ACE_Process_Mutex> SHMALLOC;
+
+Please check out the file:
+
+examples/Shared_Malloc/Malloc.cpp
+
+which illustrates more or less how to do this.
+
+----------------------------------------
+
+50.
+
+> What is the best way to turn on TRACE output in ACE. I commented
+> out the #define ACE_NTRACE 1 in config.h and rebuilt ACE and the
+> examples.
+
+The best way to do this is to say
+
+#define ACE_NTRACE 0
+
+in config.h.
+
+> When I run the CPP-inserver example in examples/IPC_SAP/SOCK_SAP, I
+> get some trace output but not everything I would expect to see.
+
+Can you please let me know what you'd expect to see that you're not
+seeing? Some of the ACE_TRACE macros for the lower-level ACE methods
+are commented out to avoid problems with infinite recursion (i.e.,
+tracing the ACE_Trace calls...). I haven't had a chance to go over
+all of these indepth, but I know that it should be possible to turn
+many of them back on.
+
+> It would be nice to have a runtime option for turning trace on and
+> off.
+
+There already is. In fact, there are two ways to do it.
+If you want to control tracing for the entire process, please check
+out ACE_Trace::start_tracing() and ACE_Trace::stop_tracing().
+
+If you want to control tracing on a per-thread basis please take a
+look at the ACE_Log_Msg class. There are methods called
+stop_tracing() and start_tracing() that do what you want.
+
+----------------------------------------
+
+51.
+
+> I've been using an acceptor and a connector in one (OS-) process.
+> What does happen, if a signal is sent to this process? Is the signal
+> processed by every ACE_Event_Handler (or its descendants) that is
+> around? The manual page simply states that handle signal is called
+> as soon as a signal is triggered by the OS.
+
+How this signal is handled depends on several factors:
+
+1. Whether your using ACE_Sig_Handler or ACE_Sig_Handlers to register
+ the signal handlers.
+
+2. If you're using ACE_Sig_Handler, then the ACE_Event_Handler * that
+ you've most recently registered to handle the signal will
+ have it's handle_signal() method called back by the Reactor.
+
+3. If you're using ACE_Sig_Handlers, then all of the ACE_Event_Handler *
+ that you've register will be called back.
+
+For examples of how this works, please check out
+
+$ACE_ROOT/examples/Reactor/Misc/test_signals.cpp
+
+This contains a long comment that explains precisely how everything
+works!