Index: README.FIRST =================================================================== RCS file: /cvsroot/omni/README.FIRST,v retrieving revision 1.2.6.6 retrieving revision 1.2.6.7 diff -u -u -r1.2.6.6 -r1.2.6.7 --- README.FIRST 2000/10/02 16:35:39 1.2.6.6 +++ README.FIRST 2002/01/09 11:20:26 1.2.6.7 @@ -38,12 +38,15 @@ README.egcs - contains information on building omniORB3 with egcs-1.0. -README.ETSKernel - contains important information on building and using - omniORB3 with Phar Lap's ETS kernel. +README.ETSKernel - contains important information on building and using + omniORB3 with Phar Lap's ETS kernel. -README.SunC++5 - contains warnings on using omniORB3 with Sun C++ v5 +README.SunC++5 - contains warnings on using omniORB3 with Sun C++ v5 -PORTING - contains instructions on porting omniORB3. +README.bs2000 - contains information on building omniORB 3 for + Fujitsu Siemens BS2000. + +PORTING - contains instructions on porting omniORB3. CHANGES_280 - contains details of changes from 2.7.1 to 2.8.0. Index: README.unix =================================================================== RCS file: /cvsroot/omni/README.unix,v retrieving revision 1.1.8.7 retrieving revision 1.1.8.8 diff -u -u -r1.1.8.7 -r1.1.8.8 --- README.unix 2000/10/02 16:35:40 1.1.8.7 +++ README.unix 2002/02/14 14:10:36 1.1.8.8 @@ -136,9 +136,6 @@ 5. Configure the Naming service ------------------------------- - If you are upgrading from 2.2.0, please read the important information about - omniNames at the end of this note. - You also have to configure the omniORB3 runtime and the naming service, consult the user guides in ./doc for details. For a quick start, follow these steps: @@ -148,26 +145,24 @@ OMNINAMES_LOGDIR=/wib/wob; export OMNINAMES_LOGDIR o Start omniNames. The binary is in ./bin//. For example: - $ ./bin/sun4_sosV_5.5/omniNames -start 12345 & - Notice that you have to give as a parameter to the option -start - the TCP/IP port number omniNames will use to receive IIOP requests. - - o omniNames writes the stringified object reference for its root context - on standard error. You should copy this string into a file omniORB.cfg. - The format of the entry is the word NAMESERVICE followed by - space and the stringified IOR all on one line. For example: - - NAMESERVICE IOR:00fff71c0000002849444c3a6f6d672e6f72672f436f734e616d696e672f4e616d696e67436f6e746578743a312e300000000001000000000000002c0001000000000012776962626c652e776f62626c652e636f6d0004d20000000c34c35a8305a931a200000001 - - o Since 2.6.0, an alternative way set up omniORB.cfg is as follows: - If omniNames has been started on host wobble and port 1234, - add to omniORB.cfg the following lines: + $ ./bin/sun4_sosV_5.5/omniNames -start - ORBInitialHost wobble - ORBInitialPort 1234 + That starts omniNames on the default port of 2809. If you want + it to start on a different port, give the port number as an + argument to -start: - Any omniORB clients of release 2.6.0 or later is able to use this - information to locate the root context of the Naming Service. + $ ./bin/sun4_sosV_5.5/omniNames -start 12345 + + o You need to tell other omniORB programs where to find the Naming + service. With omniORB 3 and later, you use the interoperable + naming service. Create a file omniORB.cfg containing: + + ORBInitRef NameService=corbaname::my.host.name + + where my.host.name is the name of the machine running omniNames. + If you have specified a non-default port, use something like + + ORBInitRef NameService=corbaname::my.host.name:12345 o Set the environment variable OMNIORB_CONFIG to contain the full path name of the file omniORB.cfg. For example, Index: README.win32 =================================================================== RCS file: /cvsroot/omni/README.win32,v retrieving revision 1.2.6.5 retrieving revision 1.2.6.6 diff -u -u -r1.2.6.5 -r1.2.6.6 --- README.win32 2000/10/02 16:35:40 1.2.6.5 +++ README.win32 2002/02/14 14:10:36 1.2.6.6 @@ -89,9 +89,6 @@ Configure the naming service ============================= - If you are upgrading from 2.2.0, please read the important - information about omniNames at the end of this note. - You have to configure the omniORB runtime and the naming service, consult the user guides in ./doc for details. For a quick start, follow these steps: @@ -105,35 +102,26 @@ o Start omniNames. The binary is in \bin\win32_x86. For example: - omniNames -start 12345 - Notice that you have to give as a parameter to the option -start - the TCP/IP port number omniNames will use to receive IIOP requests. - o omniNames writes the stringified object reference for its root context - on standard error. - Copy the IOR. (including the IOR: prefix). + omniNames -start + That starts omniNames on the default port of 2809. If you want + it to start on a different port, give the port number as an + argument to -start: + + omniNames -start 12345 + o Start the tool REGEDT32.EXE (on NT) or REGEDIT.EXE (on Windows '95). Select the key HKEY_LOCAL_MACHINE\SOFTWARE\ORL\omniORB\2.0 (or create it if it doesn't exist). Add a string value (known as a REG_SZ data type - when using REGEDT32) called NAMESERVICE , and paste the IOR in to the - value field associated with it. - - o Since 2.6.0, an alternative way to set up the configuration data is - as follows: - - If omniNames has been started on host wobble and port 1234, - use REGEDT32.EXE to enter the following keys into + when using REGEDT32) called ORBInitRef , and give it the value - HKEY_LOCAL_MACHINE\SOFTWARE\ORL\omniORB\2.0 + NameService=corbaname::my.host.name - Name Value (REG_SZ) - ------------------------------------------ - ORBInitialHost wobble - ORBInitialPort 1234 + where my.host.name is the name of the machine running omniNames. + If you have specified a non-default port, use something like - Any omniORB clients of release 2.6.0 or later is able to use this - information to locate the root context of the Naming Service. + NameService=corbaname::my.host.name:12345 o The registry entries must be duplicated on all machines that will run omniORB programs. It is only necessary to run one Index: bugfixes.xml =================================================================== RCS file: /cvsroot/omni/bugfixes.xml,v retrieving revision 1.1.2.63 retrieving revision 1.1.2.74 diff -u -u -r1.1.2.63 -r1.1.2.74 --- bugfixes.xml 2001/06/15 13:27:24 1.1.2.63 +++ bugfixes.xml 2002/02/05 13:23:45 1.1.2.74 @@ -1,13 +1,129 @@ - + - + + Memory leak in string_to_object() + Jose Hernandez + + There was a memory leak in CORBA::ORB::string_to_object() under certain + circumstances. This was due to an base class lacking a virtual + destructor. + + + + + Memory leak in omniNames + Mathieu de Naurois + + + A silly memory leak was introduced when omniNames was POAfied. + Amazing it took this long before someone noticed :-) + + + + + Incorrect result when assigning unsigned long long + consts + Carl Thompson + + + A cut-and-paste error caused the value of some unsigned long long + consts to be damaged. + + + + + Deadlock when a worker thread can't be started + Gail Ollis + + + An attempt to re-lock a locked mutex lead to a deadlock when thread + creation failed. + + + + + Wrong _out type for fixed size structs/unions + Vibhu Rishi + + + + + Refcount not incremented in find_POA with + AdapterActivator. + Patrick Hubert + + + In the case that find_POA() activated the POA using an + AdapterActivator, it failed to increment the POA's reference count. + + + + + Incorrect omniidl output with repeated names in nested + scopes + Juan Bernabó + + + IDL like
+         module a {
+	   module b {
+	     interface Address {};
+	   };
+	   module c {
+	     module b {
+	       interface BAddress : a::b::Address { };
+	     };
+	   };
+	 };
+    
+ would result in invalid C++. +
+
+ + + + Incorrect behaviour with incarnate/etherealize + William H Jones + + + Multi-threaded access to servant activators could cause all sorts of + grief. + + + + + + HPUX 11.00 shared libraries are not build with -Wl,+s + David Tiller + + HPUX 11.00 shared libraries are not build with -Wl,+s which enable + SHLIB_PATH searching at runtime. + + + + + + nameclt fails when passed a nil BindingIterator + Tilman Skobowsky + + Some Naming services return a nil BindingIterator if a context is + empty. nameclt would blindly dereference the nil in this case. + +
Index: update.log =================================================================== RCS file: /cvsroot/omni/update.log,v retrieving revision 1.253.6.380 retrieving revision 1.253.6.412 diff -u -u -r1.253.6.380 -r1.253.6.412 --- update.log 2001/06/21 13:43:24 1.253.6.380 +++ update.log 2002/03/01 15:51:00 1.253.6.412 @@ -1,3 +1,337 @@ +Fri Mar 1 15:44:58 GMT 2002 dpg1 +================================= + +- Add -Wbe switch to C++ back-end for changing example impl suffix. + +src/lib/omniORB2/omniidl_be/cxx/__init__.py + + +Wed Feb 20 13:31:07 GMT 2002 dpg1 +================================= + +- C++ back-end old signatures option did not work. + +src/lib/omniORB2/omniidl_be/cxx/__init__.py + + +Thu Feb 14 14:07:50 GMT 2002 dpg1 +================================= + +- README files were way out of date about how to configure omniNames. + +external_merge/README.unix +external_merge/README.win32 + + +Tue Feb 5 17:50:25 GMT 2002 djr +================================ + +- Fixed memory leak in string_to_object(). + +src/lib/omniORB2/orbcore/uri.cc + + +Wed Jan 16 11:59:58 GMT 2002 dpg1 +================================= + +- Darwin patches for MacOS X 10.1. + +external_merge/mk/platforms/powerpc_darwin_1.3.mk +include/omniORB3/CORBA_sysdep.h +src/lib/omniORB2/dynamic/sharedlib/dir.mk +src/lib/omniORB2/orbcore/gatekeepers/tcpwrapper/sharedlib/dir.mk +src/lib/omniORB2/orbcore/sharedlib/dir.mk +src/lib/omnithread/sharedlib/dir.mk +src/tool/omniidl/cxx/dir.mk + + +Wed Jan 9 11:19:26 GMT 2002 dpg1 +================================= + +- Add BS2000 patch. + +external_merge/README.FIRST +external_merge/README.bs2000 -- new +external_merge/patches/BS2000.patch -- new +external_merge/patches/README + + +Tue Dec 11 16:49:16 GMT 2001 dpg1 +================================= + +- Bunch of new platforms, plus other minor tweaks. + +external_merge/config/config.mk +external_merge/mk/platforms/alpha_linux_2.0.mk +external_merge/mk/platforms/hppa_hpux_10.20.mk +external_merge/mk/platforms/hppa_linux_2.4.mk -- new +external_merge/mk/platforms/ia64_linux_2.4.mk -- new +external_merge/mk/platforms/powerpc_lynxos_3.1.mk -- new +external_merge/mk/platforms/x86_openbsd_3.0.mk -- new +external_merge/src/lib/omniORB2/orbcore/gatekeepers/alone/gatekeeper.cc +include/omnithread.h +include/omniORB3/.cvsignore -- new +include/omniORB3/CORBA_sysdep.h +src/lib/omniORB2/orbcore/tcpSocketMTfactory.cc +src/lib/omnithread/posix.cc +src/services/mklib/dir.mk +src/services/mklib/mkBOAlib/dir.mk +src/tool/omniidl/cxx/cccp/config-linux.h +src/tool/omniidl/cxx/cccp/config-lynxos.h -- new +src/tool/omniidl/cxx/cccp/config-openbsd.h -- new +src/tool/omniidl/cxx/cccp/config.h + + +Wed Nov 28 11:39:49 GMT 2001 dpg1 +================================= + +- Correct omnithread documentation, rearrange things. + +doc/tex/omniNames.tex -- new +doc/tex/omnithread.tex +doc/tex/utilities.tex -- new +external_merge/doc/omniNames.pdf +external_merge/doc/omniNames.ps +external_merge/doc/omniNames.tex -- deleted +external_merge/doc/omnithread.html +external_merge/doc/omnithread.pdf +external_merge/doc/omnithread.ps +external_merge/doc/omnithread.tex -- deleted +external_merge/doc/utilities.pdf +external_merge/doc/utilities.ps +external_merge/doc/utilities.tex -- deleted + + +Mon Nov 12 12:43:10 GMT 2001 dpg1 +================================= + +- _unchecked_narrow support. Thanks to Lars Immisch. + +include/omniORB3/CORBA.h +include/omniORB3/omniObjRef.h +src/lib/omniORB2/omniidl_be/cxx/header/template.py +src/lib/omniORB2/omniidl_be/cxx/skel/template.py +src/lib/omniORB2/orbcore/omniObjRef.cc + + +Mon Oct 29 17:20:21 GMT 2001 dpg1 +================================= + +- Back-port sll's cygwin fixes from omni4_0_develop. + +external_merge/bin/x86_win32/clwrapper.exe +external_merge/bin/x86_win32/libwrapper.exe +external_merge/bin/x86_win32/linkwrapper.exe +external_merge/bin/x86_win32/oidlwrapper.exe +external_merge/bin/x86_win32/omkdepend.exe +src/tool/omkdepend/gnuwin32.c +src/tool/win32/clwrapper.c +src/tool/win32/dir.mk +src/tool/win32/libwrapper.c +src/tool/win32/linkwrapper.c +src/tool/win32/oidlwrapper.c + + +Mon Oct 22 11:34:48 BST 2001 dpg1 +================================= + +- Cope with DOS line endings in all IDL situations. + +src/tool/omniidl/cxx/idl.ll +src/tool/omniidl/cxx/lex.yy.cc +src/tool/omniidl/cxx/y.tab.cc + + +Wed Oct 17 10:30:11 BST 2001 dpg1 +================================= + +- Use sys.prefix as well as sys.exec_prefix to find Python includes. + +src/tool/omniidl/cxx/dir.mk + + +Fri Oct 5 17:47:54 BST 2001 dpg1 +================================= + +- Silly memory leak in BindingIterator creation. + +src/appl/omniNames/BindingIterator_i.h + + +Fri Oct 5 15:27:13 BST 2001 dpg1 +================================= + +- Fix hard-coded Python path in AIX make rules. + +src/tool/omniidl/cxx/dir.mk + + +Wed Oct 3 15:14:47 BST 2001 dpg1 +================================= + +- Remove double "is" from error messages. + +src/appl/omniMapper/omniMapper.cc +src/appl/omniNames/omniNames.cc + + +Fri Sep 28 17:10:02 BST 2001 dpg1 +================================= + +- Support for Sun CC > 4.x in 4.x compatibility mode. + +include/omniORB3/CORBA_sysdep.h + + +Tue Sep 25 10:56:01 BST 2001 dpg1 +================================= + +- Obey omniORB::verifyObjectExistsAndType in DII. + +src/lib/omniORB2/dynamic/request.cc + + +Thu Aug 30 10:13:19 BST 2001 dpg1 +================================= + +- Cut-and-paste error in unsigned long long consts. + +src/tool/omniidl/cxx/idlexpr.cc + + +Tue Aug 28 12:02:05 BST 2001 dpg1 +================================= + +- Deadlock when a worker thread can't be started. + +src/lib/omniORB2/orbcore/tcpSocketMTfactory.cc + + +Fri Aug 24 12:37:25 BST 2001 dpg1 +================================= + +- Don't define NULL as (void*)0. + +include/omnithread.h + + +Wed Aug 22 11:07:12 BST 2001 sll +================================ + +- Fixed win32 shared library build rule to correctly include debug symbols in + debug dll. This only affects libraries that are built using mklib rules. + At the moment there is none! + +external_merge/mk/win32.mk + + +Mon Aug 20 14:44:28 BST 2001 dpg1 +================================= + +- Wrong _out type generated for fixed length structs/unions. + (Back-ported from omniORB 4.) + +include/omniORB3/templatedecls.h +src/lib/omniORB2/omniidl_be/cxx/header/defs.py +src/lib/omniORB2/omniidl_be/cxx/header/template.py + + +Thu Aug 16 09:58:02 BST 2001 dpg1 +================================= + +- Union discriminator not copied. + +src/lib/omniORB2/omniidl_be/cxx/header/template.py + + +Fri Aug 3 11:09:01 BST 2001 dpg1 +================================= + +- Refcount not incremented in find_POA with AdapterActivator. + +src/lib/omniORB2/orbcore/poa.cc + + +Fri Jul 27 17:55:52 BST 2001 dpg1 +================================= + +- Fix bug with relative scoped names in C++ back-end output. + +src/lib/omniORB2/omniidl_be/cxx/id.py + + +Wed Jul 25 11:41:15 BST 2001 dpg1 +================================= + +- Hack the showast.py back-end so it is clear that it's broken. + +src/lib/omniORB2/omniidl_be/dir.mk +src/lib/omniORB2/omniidl_be/showast.py + + +Tue Jul 24 15:53:44 BST 2001 dpg1 +================================= + +- Fix race conditions with servant activators. + +src/lib/omniORB2/orbcore/corbaBoa.cc +src/lib/omniORB2/orbcore/localIdentity.cc +src/lib/omniORB2/orbcore/localIdentity.h +src/lib/omniORB2/orbcore/objectAdapter.h +src/lib/omniORB2/orbcore/poa.cc +src/lib/omniORB2/orbcore/poaimpl.h +src/lib/omniORB2/orbcore/taskqueue.cc +src/lib/omniORB2/orbcore/taskqueue.h + + +Mon Jul 16 11:21:55 BST 2001 sll +================================ + +- Added the command line option -Wl,+s for HPUX when a shared library is built. + +external_merge/mk/platforms/hppa_hpux_11.00.mk +src/lib/omniORB2/dynamic/sharedlib/dir.mk +src/lib/omniORB2/orbcore/sharedlib/dir.mk +src/lib/omnithread/sharedlib/dir.mk + + +Fri Jul 6 14:30:35 BST 2001 dpg1 +================================= + +- nameclt did not cope with a nil BindingIterator + +src/appl/utils/nameclt/nameclt.cc + + +Wed Jul 4 10:53:06 BST 2001 dpg1 +================================= + +- README.os2 + +external_merge/README.os2 +include/omnithread.h + + +Fri Jun 29 15:14:28 BST 2001 dpg1 +================================= + +- Rename os2.h to os2_impl.h to avoid conflict with system header. + +include/omnithread.h +include/omnithread/os2.h -- DELETED +include/omnithread/os2_impl.h -- NEW + + +Tue Jun 26 10:45:03 BST 2001 dpg1 +================================= + +- Port of omnithread to OS/2 by David Schmidt. + +include/omnithread.h +include/omnithread/os2.h +src/lib/omnithread/os2.cc + + Thu Jun 21 14:42:32 BST 2001 dpg1 ================================= Index: bin/x86_win32/clwrapper.exe =================================================================== RCS file: /cvsroot/omni/bin/x86_win32/clwrapper.exe,v retrieving revision 1.1.8.2 retrieving revision 1.1.8.3 diff -u -u -r1.1.8.2 -r1.1.8.3 Binary files /tmp/cvs25437kaa and /tmp/cvs25437laa differ Index: bin/x86_win32/libwrapper.exe =================================================================== RCS file: /cvsroot/omni/bin/x86_win32/libwrapper.exe,v retrieving revision 1.1.8.2 retrieving revision 1.1.8.3 diff -u -u -r1.1.8.2 -r1.1.8.3 Binary files /tmp/cvs25437maa and /tmp/cvs25437naa differ Index: bin/x86_win32/linkwrapper.exe =================================================================== RCS file: /cvsroot/omni/bin/x86_win32/linkwrapper.exe,v retrieving revision 1.1.8.2 retrieving revision 1.1.8.3 diff -u -u -r1.1.8.2 -r1.1.8.3 Binary files /tmp/cvs25437oaa and /tmp/cvs25437paa differ Index: bin/x86_win32/oidlwrapper.exe =================================================================== RCS file: /cvsroot/omni/bin/x86_win32/oidlwrapper.exe,v retrieving revision 1.2.2.2 retrieving revision 1.2.2.3 diff -u -u -r1.2.2.2 -r1.2.2.3 Binary files /tmp/cvs25437qaa and /tmp/cvs25437raa differ Index: bin/x86_win32/omkdepend.exe =================================================================== RCS file: /cvsroot/omni/bin/x86_win32/omkdepend.exe,v retrieving revision 1.1.8.4 retrieving revision 1.1.8.5 diff -u -u -r1.1.8.4 -r1.1.8.5 Binary files /tmp/cvs25437saa and /tmp/cvs25437taa differ Index: config/config.mk =================================================================== RCS file: /cvsroot/omni/config/config.mk,v retrieving revision 1.2.6.12 retrieving revision 1.2.6.13 diff -u -u -r1.2.6.12 -r1.2.6.13 --- config/config.mk 2001/06/18 17:43:01 1.2.6.12 +++ config/config.mk 2001/12/11 16:52:58 1.2.6.13 @@ -23,6 +23,7 @@ # powerpc_aix_4.2_xlc5 IBM AIX 4.2, XLC 5.0 (a.k.a. Visual Age 5.0) # powerpc_aix_4.3_xlc5 IBM AIX 4.3, XLC 5.0 (a.k.a. Visual Age 5.0) # powerpc_linux_2.2_glibc PowerPC linux, Debian +# powerpc_lynxos_3.1 PowerPC LynxOS 3.1.0 # powerpc_darwin_1.3 PowerPC Darwin/Mac OS X # hppa_hpux_10.20 HPUX 10.20, aC++ B3910B A.01.04 # hppa_hpux_11.00 HPUX 11.00, aC++ B3910B A.01.04 @@ -40,6 +41,7 @@ # x86_uw7 SCO UnixWare 7 (7.1.0) # x86_freebsd_3.2 x86 FreeBSD 3.2, egcs 1.1.2 # x86_freebsd_4.0 x86 FreeBSD 4.0, gcc 2.95 +# x86_openbsd_3.0 x86 OpenBSD 3.0, gcc 2.95.3 # pc486_rtems_4.5.0 x86, RTEMS, gcc 2.95.2 # You should also look at /mk/platforms/$(platform).mk and if necessary @@ -63,6 +65,7 @@ #platform = powerpc_aix_4.2_xlc5 #platform = powerpc_aix_4.3_xlc5 #platform = powerpc_linux_2.2_glibc +#platform = powerpc_lynxos_3.1 #platform = powerpc_darwin_1.3 #platform = hppa_hpux_10.20 #platform = hppa_hpux_11.00 @@ -80,7 +83,9 @@ #platform = x86_uw7 #platform = x86_freebsd_3.2 #platform = x86_freebsd_4.0 +#platform = x86_openbsd_3.0 #platform = pc486_rtems_4.5.0 + # On Win32 platforms, uncomment the following line to build all the binaries # with debugging information. Useful if you want to debug the binaries under Index: doc/omnithread.html =================================================================== RCS file: /cvsroot/omni/doc/omnithread.html,v retrieving revision 1.1.2.2 retrieving revision 1.1.2.4 diff -u -u -r1.1.2.2 -r1.1.2.4 --- doc/omnithread.html 2000/07/13 11:13:09 1.1.2.2 +++ doc/omnithread.html 2001/11/28 11:48:00 1.1.2.4 @@ -15,32 +15,32 @@

The OMNI Thread Abstraction

-

Tristan Richardson
AT&T Laboratories Cambridge -

+

Tristan Richardson
AT&T Laboratories Cambridge

-

Revised 13 July 2000

+

Revised November 2001

1   Introduction

-The OMNI thread abstraction is designed to provide a common set of thread -operations for use in programs written in C++. Programs written using the -abstraction should be much easier to port between different architectures with -different underlying threads primitives.
-
-The programming interface is designed to be similar to the C language interface -to POSIX threads (IEEE draft standard 1003.1c - previously 1003.4a, often known -as ``pthreads'' [POSIX94]).
-
-Much of the abstraction consists of simple C++ object wrappers around pthread -calls. However for some features such as thread-specific data, a better -interface can be offered because of the use of C++.
-
-Some of the more complex features of pthreads are not supported because of the -difficulty of ensuring the same features can be offered on top of other thread -systems. Such features include thread cancellation and complex scheduling -control (though simple thread priorities are supported).
+The OMNI thread abstraction is designed to provide a common set of +thread operations for use in programs written in C++. Programs +written using the abstraction should be much easier to port between +different architectures with different underlying threads primitives.
+
+The programming interface is designed to be similar to the C language +interface to POSIX threads (IEEE draft standard 1003.1c --- previously +1003.4a, often known as ``pthreads'' [POSIX94]).
+
+Much of the abstraction consists of simple C++ object wrappers around +pthread calls. However for some features such as thread-specific +data, a better interface can be offered because of the use of C++.
+
+Some of the more complex features of pthreads are not supported +because of the difficulty of ensuring the same features can be offered +on top of other thread systems. Such features include thread +cancellation and complex scheduling control (though simple thread +priorities are supported).

-The abstraction layer is currently implemented for the following architectures -/ thread systems:
+The abstraction layer is currently implemented for the following +architectures / thread systems:

  • Solaris 2.x using pthreads draft 10 @@ -55,147 +55,153 @@
  • Linux 2.x using MIT pthreads (which is based on draft 8) -
  • ATMos using pthreads draft 6
See the omnithread.h header file for full details of the API. The -descriptions below assume you have some previous knowledge of threads, mutexes, -condition variables and semaphores. Also refer to other documentation -([Birrell89], [POSIX94]) for further explanation of these ideas -(particularly condition variables, the use of which may not be particularly -intuitive when first encountered).
+
  • ATMos using pthreads draft 6 (but not Virata ATMos)See the omnithread.h header file for full details of the API. +The descriptions below assume you have some previous knowledge of +threads, mutexes, condition variables and semaphores. Also refer to +other documentation ([Birrell89], [POSIX94]) for further +explanation of these ideas (particularly condition variables, the use +of which may not be particularly intuitive when first encountered).

    2   Synchronisation objects

    -Synchronisation objects are used to synchronise threads within the same -process. There is no inter-process synchronisation provided. The -synchronisation objects provided are mutexes, condition variables and counting -semaphores.
    +Synchronisation objects are used to synchronise threads within the +same process. There is no inter-process synchronisation provided. +The synchronisation objects provided are mutexes, condition variables +and counting semaphores.

    2.1   Mutex

    -An object of type omni_mutex is used for mutual exclusion. It provides -two operations, lock() and unlock(). The alternative names acquire() and release() can be used if preferred. Behaviour is -undefined when a thread attempts to lock the same mutex again or when a mutex -is locked by one thread and unlocked by a different thread.
    +An object of type omni_mutex is used for mutual exclusion. +It provides two operations, lock() and unlock(). +The alternative names acquire() and release() can be +used if preferred. Behaviour is undefined when a thread attempts to +lock the same mutex again or when a mutex is locked by one thread and +unlocked by a different thread.

    2.2   Condition Variable

    -A condition variable is represented by an omni_condition and is used for -signalling between threads. A call to wait() causes a thread to wait on -the condition variable. A call to signal() wakes up at least one thread -if any are waiting. A call to broadcast() wakes up all threads waiting -on the condition variable.
    -
    -When constructed, a pointer to an omni_mutex must be given. A condition -variable wait() has an implicit mutex unlock() and lock() -around it. The link between condition variable and mutex lasts for the -lifetime of the condition variable (unlike pthreads where the link is only for -the duration of the wait). The same mutex may be used with several condition +A condition variable is represented by an omni_condition and +is used for signalling between threads. A call to wait() +causes a thread to wait on the condition variable. A call to +signal() wakes up at least one thread if any are waiting. A +call to broadcast() wakes up all threads waiting on the +condition variable.
    +
    +When constructed, a pointer to an omni_mutex must be given. +A condition variable wait() has an implicit mutex +unlock() and lock() around it. The link between +condition variable and mutex lasts for the lifetime of the condition +variable (unlike pthreads where the link is only for the duration of +the wait). The same mutex may be used with several condition variables.

    -A wait with a timeout can be achieved by calling timed_wait(). This is -given an absolute time to wait until. The routine omni_thread::get_time() can be used to turn a relative time into an absolute -time. timed_wait() returns ETIMEDOUT if the time expires before -the condition variable is signalled.
    +A wait with a timeout can be achieved by calling +timed_wait(). This is given an absolute time to wait until. +The routine omni_thread::get_time() can be used to turn a +relative time into an absolute time. timed_wait() returns +true if the condition was signalled, false if the +time expired before the condition variable was signalled.

    2.3   Counting semaphores

    -An omni_semaphore is a counting semaphore. When created it is given an -initial unsigned integer value. When wait() is called, the value is -decremented if non-zero. If the value is zero then the thread blocks instead. -When post() is called, if any threads are blocked in wait(), -exactly one thread is woken. If no threads were blocked then the value of the -semaphore is incremented.
    +An omni_semaphore is a counting semaphore. When created it +is given an initial unsigned integer value. When wait() is +called, the value is decremented if non-zero. If the value is zero +then the thread blocks instead. When post() is called, if +any threads are blocked in wait(), exactly one thread is +woken. If no threads were blocked then the value of the semaphore is +incremented.

    -If a thread calls try_wait(), then the thread won't block if the -semaphore's value is 0, returning EAGAIN instead.
    +If a thread calls try_wait(), then the thread won't block if +the semaphore's value is 0, returning false instead.

    -At present there is no way of querying the value of the semaphore.
    +There is no way of querying the value of the semaphore.

    3   Thread object

    -A thread is represented by an omni_thread object. There are broadly two -different ways in which it can be used.
    +A thread is represented by an omni_thread object. There are +broadly two different ways in which it can be used.

    -The first way is simply to create an omni_thread object, giving a -particular function which the thread should execute. This is like the POSIX -(or any other) C language interface.
    -
    -The second method of use is to create a new class which inherits from omni_thread. In this case the thread will execute the run() member -function of the new class. One advantage of this scheme is that -thread-specific data can be implemented simply by having data members of the -new class.
    -
    -When constructed a thread is in the "new" state and has not actually started. -A call to start() causes the thread to begin executing. A static member -function create() is provided to construct and start a thread in a single -call. A thread exits by calling exit() or by returning from the thread -function.
    -
    -Threads can be either detached or undetached. Detached threads are threads for -which all state will be lost upon exit. Other threads cannot determine when a -detached thread will disappear, and therefore should not attempt to access the -thread object unless some explicit synchronisation with the detached thread -guarantees that it still exists.
    -
    -Undetached threads are threads for which storage is not reclaimed until another -thread waits for its termination by calling join(). An exit value can be -passed from an undetached thread to the thread which joins it.
    -
    - -Detached / undetached threads are distinguished on creation by the type of -function they execute. Undetached threads execute a function which has a void* return type, whereas detached threads execute a function which has a -void return type. Unfortunately C++ member functions are not allowed to -be distinguished simply by their return type. Thus in the case of a derived -class of omni_thread which needs an undetached thread, the member -function executed by the thread is called run_undetached() rather than -run(), and it is started by calling start_undetached() instead of -start(). -
    -
    -The abstraction currently supports three priorities of thread, but no guarantee -is made of how this will affect underlying thread scheduling. The three -priorities are PRIORITY_LOW, PRIORITY_NORMAL and PRIORITY_HIGH. By default all threads run at PRIORITY_NORMAL. A -different priority can be specified on thread creation, or while the thread is -running using set_priority(). A thread's current priority is returned -by priority().
    -
    - -Other functions provided are self() which returns the calling thread's -omni_thread object, yield() which requests that other threads be -allowed to run, id() which returns an integer id for the thread for use -in debugging, state(), sleep() and get_time(). +The first way is simply to create an omni_thread object, +giving a particular function which the thread should execute. This is +like the POSIX (or any other) C language interface.
    +
    +The second method of use is to create a new class which inherits from +omni_thread. In this case the thread will execute the +run() member function of the new class. One advantage of +this scheme is that thread-specific data can be implemented simply by +having data members of the new class.
    +
    +When constructed a thread is in the "new" state and has not actually +started. A call to start() causes the thread to begin +executing. A static member function create() is provided to +construct and start a thread in a single call. A thread exits by +calling exit() or by returning from the thread function.
    +
    +Threads can be either detached or undetached. Detached threads are +threads for which all state will be lost upon exit. Other threads +cannot determine when a detached thread will disappear, and therefore +should not attempt to access the thread object unless some explicit +synchronisation with the detached thread guarantees that it still +exists.
    +
    +Undetached threads are threads for which storage is not reclaimed +until another thread waits for its termination by calling +join(). An exit value can be passed from an undetached +thread to the thread which joins it.
    +
    +Detached / undetached threads are distinguished on creation by the +type of function they execute. Undetached threads execute a function +which has a void* return type, whereas detached threads +execute a function which has a void return type. +Unfortunately C++ member functions are not allowed to be distinguished +simply by their return type. Thus in the case of a derived class of +omni_thread which needs an undetached thread, the member +function executed by the thread is called run_undetached() +rather than run(), and it is started by calling +start_undetached() instead of start().
    +
    +The abstraction currently supports three priorities of thread, but no +guarantee is made of how this will affect underlying thread +scheduling. The three priorities are PRIORITY_LOW, +PRIORITY_NORMAL and PRIORITY_HIGH. By default all +threads run at PRIORITY_NORMAL. A different priority can be +specified on thread creation, or while the thread is running using +set_priority(). A thread's current priority is returned by +priority().
    +
    +Other functions provided are self() which returns the calling +thread's omni_thread object, yield() which +requests that other threads be allowed to run, id() which +returns an integer id for the thread for use in debugging, +state(), sleep() and get_time().

    -

    4   Using OMNI threads in your program

    -Obviously you need to include the omnithread.h header file in your source -code, and link in the omnithread library with your executable. Because there -is a single omnithread.h for all platforms, certain preprocessor defines -must be given as compiler options. The easiest way to do this is to study the -makefiles given in the examples provided with this distribution. If you are to -include OMNI threads in your own development environment, these are the -necessary preprocessor defines:
    +Obviously you need to include the omnithread.h header file in +your source code, and link in the omnithread library with your +executable. Because there is a single omnithread.h for all +platforms, certain preprocessor defines must be given as compiler +options. The easiest way to do this is to study the makefiles given +in the examples provided with this distribution. If you are to +include OMNI threads in your own development environment, these are +the necessary preprocessor defines:

    - + - - - - - - - + @@ -203,133 +209,150 @@ + + + + + +
    Platform Preprocessor Defines
    Sun Solaris 2.x-D__sunos__ -D__sparc__ -D__OSVERSION__=5 -DSVR4-D__sunos__ -D__sparc__ -D__OSVERSION__=5
     -DUsePthread -D_REENTRANT
    Digital Unix 3.2-D__osf1__ -D__alpha__ -D__OSVERSION__=3
     -D_REENTRANT-DSVR4 -DUsePthread -D_REENTRANT
    x86 Linux 2.0 -D__linux__ -D__i86__ -D__OSVERSION__=2
    with linuxthreads 0.5 -D_REENTRANT
    Digital Unix 3.2-D__osf1__ -D__alpha__ -D__OSVERSION__=3
     -D_REENTRANT
    Windows NT -D__NT__ -MD

    5   Threaded I/O shutdown for Unix

    -or, how one thread should tell another thread to shut down when it might -be doing a blocking call on a socket.
    +or, how one thread should tell another thread to shut down when it +might be doing a blocking call on a socket.

    -Unfortunately there doesn't seem to be a standard way of doing this which works -across all Unix systems. I have investigated the behaviour of our two main -Unix platforms, Solaris 2.5 and Digital Unix 3.2. On Digital Unix everything -is fine, as the obvious method using shutdown() seems to work OK. -Unfortunately on Solaris shutdown can only be used on a connected socket, so we -need devious means to get around this limitation. The details are summarised -below:
    +If you are using omniORB, you don't need to worry about all +this, since omniORB does it for you. This section is only relevant +if you are using omnithread in your own socket-based programming. It +is also seriously out of date.
    +
    +Unfortunately there doesn't seem to be a standard way of doing this +which works across all Unix systems. I have investigated the +behaviour of Solaris 2.5 and Digital Unix 3.2. On Digital Unix +everything is fine, as the obvious method using shutdown() seems to +work OK. Unfortunately on Solaris shutdown can only be used on a +connected socket, so we need devious means to get around this +limitation. The details are summarised below:

    5.1   read()

    -Thread A is in a loop, doing read(sock), processing the data, then going back -into the read.
    +Thread A is in a loop, doing read(sock), processing the data, +then going back into the read.

    -Thread B comes along and wants to shut it down - it can't cancel thread A since -(i) working out how to clean up according to where A is in its loop is a -nightmare, and (ii) this isn't available in omnithread anyway.
    +Thread B comes along and wants to shut it down --- it can't cancel +thread A since (i) working out how to clean up according to where A is +in its loop is a nightmare, and (ii) this isn't available in +omnithread anyway.

    On Solaris 2.5 and Digital Unix 3.2 the following strategy works:

    -Thread B does shutdown(sock,2).
    +Thread B does shutdown(sock,2).

    -At this point thread A is either blocked inside read(sock), or is elsewhere in -the loop. If the former then read will return 0, indicating that the socket is -closed. If the latter then eventually thread A will call read(sock) and then -this will return 0. Thread A should close(sock), do any other tidying up, and -exit.
    -
    -If there is another point in the loop that thread A can block then obviously -thread B needs to be aware of this and be able to wake it up in the appropriate -way from that point.
    +At this point thread A is either blocked inside read(sock), or +is elsewhere in the loop. If the former then read will return 0, +indicating that the socket is closed. If the latter then eventually +thread A will call read(sock) and then this will return 0. +Thread A should close(sock), do any other tidying up, and exit.
    +
    +If there is another point in the loop that thread A can block then +obviously thread B needs to be aware of this and be able to wake it up +in the appropriate way from that point.

    5.2   accept()

    -Again thread A is in a loop, this time doing an accept on listenSock, dealing -with a new connection and going back into accept. Thread B wants to cancel it.
    +Again thread A is in a loop, this time doing an accept on listenSock, +dealing with a new connection and going back into accept. Thread B +wants to cancel it.

    On Digital Unix 3.2 the strategy is identical to that for read:

    -Thread B does shutdown(listenSock,2). Wherever thread A is in the loop, -eventually it will return ECONNABORTED from the accept call. It should -close(listenSock), tidy up as necessary and exit.
    -
    -On Solaris 2.5 thread B can't do shutdown(listenSock,2) - this returns -ENOTCONN. Instead the following strategy can be used:
    -
    -First thread B sets some sort of "shutdown flag" associated with listenSock. -Then it does getsockaddr(listenSock) to find out which port listenSock is on -(or knows already), sets up a socket dummySock, does connect(dummySock, this -host, port) and finally does close(dummySock).
    -
    -Now wherever thread A is in the loop, eventually it will call -accept(listenSock). This will return successfully with a new socket, say -connSock. Thread A then checks to see if the "shutdown flag" is set. If not, -then it's a normal connection. If it is set, then thread A closes listenSock -and connSock, tidies up and exits.
    +Thread B does shutdown(listenSock,2). Wherever thread A is in +the loop, eventually it will return ECONNABORTED from the +accept call. It should close(listenSock), tidy up as necessary +and exit.
    +
    +On Solaris 2.5 thread B can't do shutdown(listenSock,2) --- +this returns ENOTCONN. Instead the following strategy can be +used:
    +
    +First thread B sets some sort of "shutdown flag" associated with +listenSock. Then it does getsockaddr(listenSock) to find out +which port listenSock is on (or knows already), sets up a socket +dummySock, does connect(dummySock, this host, port) and +finally does close(dummySock).
    +
    +Wherever thread A is in the loop, eventually it will call +accept(listenSock). This will return successfully with a new +socket, say connSock. Thread A then checks to see if the "shutdown +flag" is set. If not, then it's a normal connection. If it is set, +then thread A closes listenSock and connSock, tidies up and exits.

    5.3   write()

    -Thread A may be blocked in write, or about to go in to a potentially-blocking -write. Thread B wants to shut it down.
    +Thread A may be blocked in write, or about to go in to a +potentially-blocking write. Thread B wants to shut it down.

    On Solaris 2.5:

    -Thread B does shutdown(sock,2).
    +Thread B does shutdown(sock,2).

    -If thread A is already in write(sock) then it will return with ENXIO. If -thread A calls write after thread B calls shutdown this will return EIO.
    +If thread A is already in write(sock) then it will return with +ENXIO. If thread A calls write after thread B calls shutdown +this will return EIO.

    On Digital Unix 3.2:

    -Thread B does shutdown(sock,2).
    +Thread B does shutdown(sock,2).

    -If thread A is already in write(sock) then it will return the number of bytes -written before it became blocked. A subsequent call to write will then -generate SIGPIPE (or EPIPE will be returned if SIGPIPE is ignored by the -thread).
    +If thread A is already in write(sock) then it will return the +number of bytes written before it became blocked. A subsequent call +to write will then generate SIGPIPE (or EPIPE will be +returned if SIGPIPE is ignored by the thread).

    5.4   connect()

    -Thread A may be blocked in connect, or about to go in to a potentially-blocking -connect. Thread B wants to shut it down.
    +Thread A may be blocked in connect, or about to go in to a +potentially-blocking connect. Thread B wants to shut it down.

    On Digital Unix 3.2:

    -Thread B does shutdown(sock,2).
    +Thread B does shutdown(sock,2).

    -If thread A is already in connect(sock) then it will return a successful -connection. Subsequent reading or writing will show that the socket has been -shut down (i.e. read returns 0, write generates SIGPIPE or returns EPIPE). If -thread A calls connect after thread B calls shutdown this will return EINVAL.
    +If thread A is already in connect(sock) then it will return a +successful connection. Subsequent reading or writing will show that +the socket has been shut down (i.e. read returns 0, write generates +SIGPIPE or returns EPIPE). If thread A calls connect +after thread B calls shutdown this will return EINVAL.

    On Solaris 2.5:

    -There is no way to wake up a thread which is blocked in connect. Instead -Solaris forces us through a ridiculous procedure whichever way we try it. -One way is this:
    -
    -First thread A creates a pipe in addition to the socket. Instead of shutting -down the socket, thread B simply writes a byte to the pipe.
    -
    - -Thread A meanwhile sets the socket non-blocking using fcntl(sock, F_SETFL, -O_NONBLOCK). Then it calls connect on the socket - this will return -EINPROGRESS. Then it must call select, waiting for either sock to become -writable or for the pipe to become readable. If select returns that just sock -is writable then the connection has succeeded. It then needs to set the socket -back to blocking mode using fcntl(sock, F_SETFL, 0). If instead select -returns that the pipe is readable, thread A closes the socket, tidies up and -exits. -
    -
    -An alternative method is similar but to use polling instead of the pipe. -Thread B justs sets a flag and thread A calls select with a timeout, -periodically waking up to see if the flag has been set.
    +There is no way to wake up a thread which is blocked in connect. +Instead Solaris forces us through a ridiculous procedure whichever way +we try it. One way is this:
    +
    +First thread A creates a pipe in addition to the socket. Instead of +shutting down the socket, thread B simply writes a byte to the pipe.
    +
    +Thread A meanwhile sets the socket to non-blocking mode using +fcntl(sock, F_SETFL, O_NONBLOCK). Then it calls connect +on the socket --- this will return EINPROGRESS. Then it must +call select(), waiting for either sock to become writable or +for the pipe to become readable. If select returns that just sock is +writable then the connection has succeeded. It then needs to set the +socket back to blocking mode using fcntl(sock, F_SETFL, 0). If +instead select returns that the pipe is readable, thread A closes the +socket, tidies up and exits.
    +
    +An alternative method is similar but to use polling instead of the +pipe. Thread B justs sets a flag and thread A calls select with a +timeout, periodically waking up to see if the flag has been set.

    Index: doc/tex/omnithread.tex =================================================================== RCS file: /cvsroot/omni/doc/tex/omnithread.tex,v retrieving revision 1.7 retrieving revision 1.7.8.2 diff -u -u -r1.7 -r1.7.8.2 --- doc/tex/omnithread.tex 1997/03/16 13:25:40 1.7 +++ doc/tex/omnithread.tex 2001/11/28 11:48:00 1.7.8.2 @@ -1,20 +1,24 @@ -\documentclass[11pt,twoside,onecolumn]{article} -\usepackage[]{fontenc} +\documentclass[11pt,twoside,a4paper]{article} +\usepackage[T1]{fontenc} \usepackage{palatino} -\usepackage{a4} \addtolength{\oddsidemargin}{-0.2in} \addtolength{\evensidemargin}{-0.6in} \addtolength{\textwidth}{0.5in} \pagestyle{headings} +% Discretionary break used to split long function names cleanly +%BEGIN LATEX +\newcommand{\dsc}{\discretionary{}{}} +%END LATEX +%HEVEA\newcommand{\dsc}{} + \title{The OMNI Thread Abstraction} \author{Tristan Richardson\\ -Olivetti Research Laboratory \\ -Cambridge \\ +AT\&T Laboratories Cambridge \\ } -\date{{\it Revised} 13 March 1997} +\date{\textit{Revised} November 2001} \begin{document} @@ -22,26 +26,27 @@ \section{Introduction} -The OMNI thread abstraction is designed to provide a common set of thread -operations for use in programs written in C++. Programs written using the -abstraction should be much easier to port between different architectures with -different underlying threads primitives. - -The programming interface is designed to be similar to the C language interface -to POSIX threads (IEEE draft standard 1003.1c - previously 1003.4a, often known -as ``pthreads'' \cite{pthreads}). - -Much of the abstraction consists of simple C++ object wrappers around pthread -calls. However for some features such as thread-specific data, a better -interface can be offered because of the use of C++. - -Some of the more complex features of pthreads are not supported because of the -difficulty of ensuring the same features can be offered on top of other thread -systems. Such features include thread cancellation and complex scheduling -control (though simple thread priorities are supported). +The OMNI thread abstraction is designed to provide a common set of +thread operations for use in programs written in C++. Programs +written using the abstraction should be much easier to port between +different architectures with different underlying threads primitives. + +The programming interface is designed to be similar to the C language +interface to POSIX threads (IEEE draft standard 1003.1c --- previously +1003.4a, often known as ``pthreads'' \cite{pthreads}). + +Much of the abstraction consists of simple C++ object wrappers around +pthread calls. However for some features such as thread-specific +data, a better interface can be offered because of the use of C++. + +Some of the more complex features of pthreads are not supported +because of the difficulty of ensuring the same features can be offered +on top of other thread systems. Such features include thread +cancellation and complex scheduling control (though simple thread +priorities are supported). -The abstraction layer is currently implemented for the following architectures -/ thread systems: +The abstraction layer is currently implemented for the following +architectures / thread systems: \begin{itemize} @@ -51,298 +56,316 @@ \item Windows NT using NT threads \item Linux 2.x using Linuxthread 0.5 (which is based on pthreads draft 10) \item Linux 2.x using MIT pthreads (which is based on draft 8) -\item ATMos using pthreads draft 6 +\item ATMos using pthreads draft 6 (but not Virata ATMos) \end{itemize} -See the {\tt omnithread.h} header file for full details of the API. The -descriptions below assume you have some previous knowledge of threads, mutexes, -condition variables and semaphores. Also refer to other documentation -(\cite{birrell}, \cite{pthreads}) for further explanation of these ideas -(particularly condition variables, the use of which may not be particularly -intuitive when first encountered). +See the \texttt{omnithread.h} header file for full details of the API. +The descriptions below assume you have some previous knowledge of +threads, mutexes, condition variables and semaphores. Also refer to +other documentation (\cite{birrell}, \cite{pthreads}) for further +explanation of these ideas (particularly condition variables, the use +of which may not be particularly intuitive when first encountered). \section{Synchronisation objects} -Synchronisation objects are used to synchronise threads within the same -process. There is no inter-process synchronisation provided. The -synchronisation objects provided are mutexes, condition variables and counting -semaphores. +Synchronisation objects are used to synchronise threads within the +same process. There is no inter-process synchronisation provided. +The synchronisation objects provided are mutexes, condition variables +and counting semaphores. \subsection{Mutex} -An object of type {\tt omni\_mutex} is used for mutual exclusion. It provides -two operations, {\tt lock()} and {\tt unlock()}. The alternative names {\tt -acquire()} and {\tt release()} can be used if preferred. Behaviour is -undefined when a thread attempts to lock the same mutex again or when a mutex -is locked by one thread and unlocked by a different thread. +An object of type \texttt{omni\_mutex} is used for mutual exclusion. +It provides two operations, \texttt{lock()} and \texttt{unlock()}. +The alternative names \texttt{acquire()} and \texttt{release()} can be +used if preferred. Behaviour is undefined when a thread attempts to +lock the same mutex again or when a mutex is locked by one thread and +unlocked by a different thread. \subsection{Condition Variable} -A condition variable is represented by an {\tt omni\_condition} and is used for -signalling between threads. A call to {\tt wait()} causes a thread to wait on -the condition variable. A call to {\tt signal()} wakes up at least one thread -if any are waiting. A call to {\tt broadcast()} wakes up all threads waiting -on the condition variable. - -When constructed, a pointer to an {\tt omni\_mutex} must be given. A condition -variable {\tt wait()} has an implicit mutex {\tt unlock()} and {\tt lock()} -around it. The link between condition variable and mutex lasts for the -lifetime of the condition variable (unlike pthreads where the link is only for -the duration of the wait). The same mutex may be used with several condition +A condition variable is represented by an \texttt{omni\_condition} and +is used for signalling between threads. A call to \texttt{wait()} +causes a thread to wait on the condition variable. A call to +\texttt{signal()} wakes up at least one thread if any are waiting. A +call to \texttt{broadcast()} wakes up all threads waiting on the +condition variable. + +When constructed, a pointer to an \texttt{omni\_mutex} must be given. +A condition variable \texttt{wait()} has an implicit mutex +\texttt{unlock()} and \texttt{lock()} around it. The link between +condition variable and mutex lasts for the lifetime of the condition +variable (unlike pthreads where the link is only for the duration of +the wait). The same mutex may be used with several condition variables. -A wait with a timeout can be achieved by calling {\tt timed\_wait()}. This is -given an absolute time to wait until. The routine {\tt -omni\_thread::get\_time()} can be used to turn a relative time into an absolute -time. {\tt timed\_wait()} returns {\tt ETIMEDOUT} if the time expires before -the condition variable is signalled. +A wait with a timeout can be achieved by calling +\texttt{timed\_wait()}. This is given an absolute time to wait until. +The routine \texttt{omni\_thread::get\_time()} can be used to turn a +relative time into an absolute time. \texttt{timed\_wait()} returns +\texttt{true} if the condition was signalled, \texttt{false} if the +time expired before the condition variable was signalled. \subsection{Counting semaphores} -An {\tt omni\_semaphore} is a counting semaphore. When created it is given an -initial unsigned integer value. When {\tt wait()} is called, the value is -decremented if non-zero. If the value is zero then the thread blocks instead. -When {\tt post()} is called, if any threads are blocked in {\tt wait()}, -exactly one thread is woken. If no threads were blocked then the value of the -semaphore is incremented. +An \texttt{omni\_semaphore} is a counting semaphore. When created it +is given an initial unsigned integer value. When \texttt{wait()} is +called, the value is decremented if non-zero. If the value is zero +then the thread blocks instead. When \texttt{post()} is called, if +any threads are blocked in \texttt{wait()}, exactly one thread is +woken. If no threads were blocked then the value of the semaphore is +incremented. -If a thread calls {\tt try\_wait()}, then the thread won't block if the -semaphore's value is 0, returning {\tt EAGAIN} instead. +If a thread calls \texttt{try\_wait()}, then the thread won't block if +the semaphore's value is 0, returning \texttt{false} instead. -At present there is no way of querying the value of the semaphore. +There is no way of querying the value of the semaphore. \section{Thread object} - -A thread is represented by an {\tt omni\_thread} object. There are broadly two -different ways in which it can be used. - -The first way is simply to create an {\tt omni\_thread} object, giving a -particular function which the thread should execute. This is like the POSIX -(or any other) C language interface. - -The second method of use is to create a new class which inherits from {\tt -omni\_thread}. In this case the thread will execute the {\tt run()} member -function of the new class. One advantage of this scheme is that -thread-specific data can be implemented simply by having data members of the -new class. - -When constructed a thread is in the "new" state and has not actually started. -A call to {\tt start()} causes the thread to begin executing. A static member -function {\tt create()} is provided to construct and start a thread in a single -call. A thread exits by calling {\tt exit()} or by returning from the thread -function. - -Threads can be either detached or undetached. Detached threads are threads for -which all state will be lost upon exit. Other threads cannot determine when a -detached thread will disappear, and therefore should not attempt to access the -thread object unless some explicit synchronisation with the detached thread -guarantees that it still exists. - -Undetached threads are threads for which storage is not reclaimed until another -thread waits for its termination by calling {\tt join()}. An exit value can be -passed from an undetached thread to the thread which joins it. - -\sloppy{ -Detached / undetached threads are distinguished on creation by the type of -function they execute. Undetached threads execute a function which has a {\tt -void*} return type, whereas detached threads execute a function which has a -{\tt void} return type. Unfortunately C++ member functions are not allowed to -be distinguished simply by their return type. Thus in the case of a derived -class of {\tt omni\_thread} which needs an undetached thread, the member -function executed by the thread is called {\tt run\_undetached()} rather than -{\tt run()}, and it is started by calling {\tt start\_undetached()} instead of -{\tt start()}. -} - -The abstraction currently supports three priorities of thread, but no guarantee -is made of how this will affect underlying thread scheduling. The three -priorities are {\tt PRIORITY\_LOW}, {\tt PRIORITY\_NORMAL} and {\tt -PRIORITY\_HIGH}. By default all threads run at {\tt PRIORITY\_NORMAL}. A -different priority can be specified on thread creation, or while the thread is -running using {\tt set\_priority().} A thread's current priority is returned -by {\tt priority()}. - -\sloppy{ -Other functions provided are {\tt self()} which returns the calling thread's -{\tt omni\_thread} object, {\tt yield()} which requests that other threads be -allowed to run, {\tt id()} which returns an integer id for the thread for use -in debugging, {\tt state()}, {\tt sleep()} and {\tt get\_time()}. -} -\section{Using threads in OMNI programs} +A thread is represented by an \texttt{omni\_thread} object. There are +broadly two different ways in which it can be used. -All you need to do is include the {\tt omnithread.h} header file in your source -code, and then link in the omnithread library in to your executable. The -details of what you need to put in your dir.mk to make the header files and -library available is best explained by example. You just need something like -this: +The first way is simply to create an \texttt{omni\_thread} object, +giving a particular function which the thread should execute. This is +like the POSIX (or any other) C language interface. + +The second method of use is to create a new class which inherits from +\texttt{omni\_\dsc{}thread}. In this case the thread will execute the +\texttt{run()} member function of the new class. One advantage of +this scheme is that thread-specific data can be implemented simply by +having data members of the new class. + +When constructed a thread is in the "new" state and has not actually +started. A call to \texttt{start()} causes the thread to begin +executing. A static member function \texttt{create()} is provided to +construct and start a thread in a single call. A thread exits by +calling \texttt{exit()} or by returning from the thread function. + +Threads can be either detached or undetached. Detached threads are +threads for which all state will be lost upon exit. Other threads +cannot determine when a detached thread will disappear, and therefore +should not attempt to access the thread object unless some explicit +synchronisation with the detached thread guarantees that it still +exists. + +Undetached threads are threads for which storage is not reclaimed +until another thread waits for its termination by calling +\texttt{join()}. An exit value can be passed from an undetached +thread to the thread which joins it. + +Detached / undetached threads are distinguished on creation by the +type of function they execute. Undetached threads execute a function +which has a \texttt{void*} return type, whereas detached threads +execute a function which has a \texttt{void} return type. +Unfortunately C++ member functions are not allowed to be distinguished +simply by their return type. Thus in the case of a derived class of +\texttt{omni\_thread} which needs an undetached thread, the member +function executed by the thread is called \texttt{run\_undetached()} +rather than \texttt{run()}, and it is started by calling +\texttt{start\_\dsc{}undetached()} instead of \texttt{start()}. + +The abstraction currently supports three priorities of thread, but no +guarantee is made of how this will affect underlying thread +scheduling. The three priorities are \texttt{PRIORITY\_LOW}, +\texttt{PRIORITY\_NORMAL} and \texttt{PRIORITY\_HIGH}. By default all +threads run at \texttt{PRIORITY\_NORMAL}. A different priority can be +specified on thread creation, or while the thread is running using +\texttt{set\_priority().} A thread's current priority is returned by +\texttt{priority()}. + +Other functions provided are \texttt{self()} which returns the calling +thread's \texttt{omni\_\dsc{}thread} object, \texttt{yield()} which +requests that other threads be allowed to run, \texttt{id()} which +returns an integer id for the thread for use in debugging, +\texttt{state()}, \texttt{sleep()} and \texttt{get\_time()}. + +\section{Using OMNI threads in your program} + +Obviously you need to include the \texttt{omnithread.h} header file in +your source code, and link in the omnithread library with your +executable. Because there is a single \texttt{omnithread.h} for all +platforms, certain preprocessor defines must be given as compiler +options. The easiest way to do this is to study the makefiles given +in the examples provided with this distribution. If you are to +include OMNI threads in your own development environment, these are +the necessary preprocessor defines: + +\vspace{.5\baselineskip} + +\begin{tabular}{|l|l|} \hline +Platform & Preprocessor Defines \\ \hline \hline + +Sun Solaris 2.x & \verb|-D__sunos__ -D__sparc__ -D__OSVERSION__=5| \\ + & \verb|-DSVR4 -DUsePthread -D_REENTRANT| \\ \hline -\begin{verbatim} +x86 Linux 2.0 & \verb|-D__linux__ -D__i86__ -D__OSVERSION__=2| \\ +with linuxthreads 0.5 & \verb|-D_REENTRANT| \\ \hline -CXXSRCS = wob.cc +Digital Unix 3.2 & \verb|-D__osf1__ -D__alpha__ -D__OSVERSION__=3| \\ + & \verb|-D_REENTRANT| \\ \hline -CPPFLAGS = $(OMNITHREAD_CPPFLAGS) +Windows NT & \verb|-D__NT__ -MD| \\ \hline +\end{tabular} -wob = $(patsubst %,$(BinPattern),wob) -$(wob): wob.o $(OMNITHREAD_LIB_DEPEND) - @(libs="$(OMNITHREAD_LIB)"; $(CXXExecutable)) -\end{verbatim} - -Note that if you use CORBA then it is important that {\tt \$(CORBA\_LIB)} -appears before {\tt \$(OMNITHREAD\_LIB)} in the {\tt libs="..."} assignment. -This is because linking the Solaris thread library before the Orbix library -results in a binary which segmentation faults inside the Orbix library -initialisation. - - - \section{Threaded I/O shutdown for Unix} -or, how one thread should tell another thread to shut down when it might -be doing a blocking call on a socket. +or, how one thread should tell another thread to shut down when it +might be doing a blocking call on a socket. -Unfortunately there doesn't seem to be a standard way of doing this which works -across all Unix systems. I have investigated the behaviour of our two main -Unix platforms, Solaris 2.5 and Digital Unix 3.2. On Digital Unix everything -is fine, as the obvious method using shutdown() seems to work OK. -Unfortunately on Solaris shutdown can only be used on a connected socket, so we -need devious means to get around this limitation. The details are summarised -below: +\textbf{If you are using omniORB, you don't need to worry about all +this, since omniORB does it for you.} This section is only relevant +if you are using omnithread in your own socket-based programming. It +is also seriously out of date. + +Unfortunately there doesn't seem to be a standard way of doing this +which works across all Unix systems. I have investigated the +behaviour of Solaris 2.5 and Digital Unix 3.2. On Digital Unix +everything is fine, as the obvious method using shutdown() seems to +work OK. Unfortunately on Solaris shutdown can only be used on a +connected socket, so we need devious means to get around this +limitation. The details are summarised below: \subsection{read()} -Thread A is in a loop, doing read(sock), processing the data, then going back -into the read. +Thread A is in a loop, doing \verb|read(sock)|, processing the data, +then going back into the read. -Thread B comes along and wants to shut it down - it can't cancel thread A since -(i) working out how to clean up according to where A is in its loop is a -nightmare, and (ii) this isn't available in omnithread anyway. +Thread B comes along and wants to shut it down --- it can't cancel +thread A since (i) working out how to clean up according to where A is +in its loop is a nightmare, and (ii) this isn't available in +omnithread anyway. On Solaris 2.5 and Digital Unix 3.2 the following strategy works: -Thread B does shutdown(sock,2). +Thread B does \verb|shutdown(sock,2)|. -At this point thread A is either blocked inside read(sock), or is elsewhere in -the loop. If the former then read will return 0, indicating that the socket is -closed. If the latter then eventually thread A will call read(sock) and then -this will return 0. Thread A should close(sock), do any other tidying up, and -exit. - -If there is another point in the loop that thread A can block then obviously -thread B needs to be aware of this and be able to wake it up in the appropriate -way from that point. +At this point thread A is either blocked inside \verb|read(sock)|, or +is elsewhere in the loop. If the former then read will return 0, +indicating that the socket is closed. If the latter then eventually +thread A will call \verb|read(sock)| and then this will return 0. +Thread A should \verb|close(sock)|, do any other tidying up, and exit. + +If there is another point in the loop that thread A can block then +obviously thread B needs to be aware of this and be able to wake it up +in the appropriate way from that point. \subsection{accept()} -Again thread A is in a loop, this time doing an accept on listenSock, dealing -with a new connection and going back into accept. Thread B wants to cancel it. +Again thread A is in a loop, this time doing an accept on listenSock, +dealing with a new connection and going back into accept. Thread B +wants to cancel it. On Digital Unix 3.2 the strategy is identical to that for read: -Thread B does shutdown(listenSock,2). Wherever thread A is in the loop, -eventually it will return ECONNABORTED from the accept call. It should -close(listenSock), tidy up as necessary and exit. - -On Solaris 2.5 thread B can't do shutdown(listenSock,2) - this returns -ENOTCONN. Instead the following strategy can be used: - -First thread B sets some sort of "shutdown flag" associated with listenSock. -Then it does getsockaddr(listenSock) to find out which port listenSock is on -(or knows already), sets up a socket dummySock, does connect(dummySock, this -host, port) and finally does close(dummySock). - -Now wherever thread A is in the loop, eventually it will call -accept(listenSock). This will return successfully with a new socket, say -connSock. Thread A then checks to see if the "shutdown flag" is set. If not, -then it's a normal connection. If it is set, then thread A closes listenSock -and connSock, tidies up and exits. +Thread B does \verb|shutdown(listenSock,2)|. Wherever thread A is in +the loop, eventually it will return \verb|ECONNABORTED| from the +accept call. It should \verb|close(listenSock)|, tidy up as necessary +and exit. + +On Solaris 2.5 thread B can't do \verb|shutdown(listenSock,2)| --- +this returns \verb|ENOTCONN|. Instead the following strategy can be +used: + +First thread B sets some sort of "shutdown flag" associated with +listenSock. Then it does \verb|getsockaddr(listenSock)| to find out +which port listenSock is on (or knows already), sets up a socket +dummySock, does \verb|connect(dummySock,| \verb|this host, port)| and +finally does \verb|close(dummySock)|. + +Wherever thread A is in the loop, eventually it will call +\verb|accept(listenSock)|. This will return successfully with a new +socket, say connSock. Thread A then checks to see if the "shutdown +flag" is set. If not, then it's a normal connection. If it is set, +then thread A closes listenSock and connSock, tidies up and exits. \subsection{write()} -Thread A may be blocked in write, or about to go in to a potentially-blocking -write. Thread B wants to shut it down. +Thread A may be blocked in write, or about to go in to a +potentially-blocking write. Thread B wants to shut it down. On Solaris 2.5: -Thread B does shutdown(sock,2). +Thread B does \verb|shutdown(sock,2)|. -If thread A is already in write(sock) then it will return with ENXIO. If -thread A calls write after thread B calls shutdown this will return EIO. +If thread A is already in \verb|write(sock)| then it will return with +\verb|ENXIO|. If thread A calls write after thread B calls shutdown +this will return \verb|EIO|. On Digital Unix 3.2: -Thread B does shutdown(sock,2). +Thread B does \verb|shutdown(sock,2)|. -If thread A is already in write(sock) then it will return the number of bytes -written before it became blocked. A subsequent call to write will then -generate SIGPIPE (or EPIPE will be returned if SIGPIPE is ignored by the -thread). +If thread A is already in \verb|write(sock)| then it will return the +number of bytes written before it became blocked. A subsequent call +to write will then generate \verb|SIGPIPE| (or \verb|EPIPE| will be +returned if \verb|SIGPIPE| is ignored by the thread). \subsection{connect()} -Thread A may be blocked in connect, or about to go in to a potentially-blocking -connect. Thread B wants to shut it down. +Thread A may be blocked in connect, or about to go in to a +potentially-blocking connect. Thread B wants to shut it down. On Digital Unix 3.2: -Thread B does shutdown(sock,2). +Thread B does \verb|shutdown(sock,2)|. -If thread A is already in connect(sock) then it will return a successful -connection. Subsequent reading or writing will show that the socket has been -shut down (i.e. read returns 0, write generates SIGPIPE or returns EPIPE). If -thread A calls connect after thread B calls shutdown this will return EINVAL. +If thread A is already in \verb|connect(sock)| then it will return a +successful connection. Subsequent reading or writing will show that +the socket has been shut down (i.e. read returns 0, write generates +\verb|SIGPIPE| or returns \verb|EPIPE|). If thread A calls connect +after thread B calls shutdown this will return \verb|EINVAL|. On Solaris 2.5: - -There is no way to wake up a thread which is blocked in connect. Instead -Solaris forces us through a ridiculous procedure whichever way we try it. -One way is this: - -First thread A creates a pipe in addition to the socket. Instead of shutting -down the socket, thread B simply writes a byte to the pipe. - -\sloppy{ -Thread A meanwhile sets the socket non-blocking using fcntl(sock, F\_SETFL, -O\_NONBLOCK). Then it calls connect on the socket - this will return -EINPROGRESS. Then it must call select, waiting for either sock to become -writable or for the pipe to become readable. If select returns that just sock -is writable then the connection has succeeded. It then needs to set the socket -back to blocking mode using fcntl(sock, F\_SETFL, 0). If instead select -returns that the pipe is readable, thread A closes the socket, tidies up and -exits. -} -An alternative method is similar but to use polling instead of the pipe. -Thread B justs sets a flag and thread A calls select with a timeout, -periodically waking up to see if the flag has been set. +There is no way to wake up a thread which is blocked in connect. +Instead Solaris forces us through a ridiculous procedure whichever way +we try it. One way is this: + +First thread A creates a pipe in addition to the socket. Instead of +shutting down the socket, thread B simply writes a byte to the pipe. + +Thread A meanwhile sets the socket to non-blocking mode using +\verb|fcntl(sock,| \verb|F_SETFL, O_NONBLOCK)|. Then it calls connect +on the socket --- this will return \verb|EINPROGRESS|. Then it must +call \verb|select()|, waiting for either sock to become writable or +for the pipe to become readable. If select returns that just sock is +writable then the connection has succeeded. It then needs to set the +socket back to blocking mode using \verb|fcntl(sock, F_SETFL, 0)|. If +instead select returns that the pipe is readable, thread A closes the +socket, tidies up and exits. + +An alternative method is similar but to use polling instead of the +pipe. Thread B justs sets a flag and thread A calls select with a +timeout, periodically waking up to see if the flag has been set. \begin{thebibliography}{lo} \bibitem[POSIX94]{pthreads} -{\em Portable Operating System Interface (POSIX) Threads Extension}, +\emph{Portable Operating System Interface (POSIX) Threads Extension}, P1003.1c Draft 10, IEEE, September 1994. \bibitem[Birrell89]{birrell} -{\em An Introduction to Programming with Threads}, +\emph{An Introduction to Programming with Threads}, Research Report 35, DEC Systems Research Center, Palo Alto, CA, Index: include/omnithread.h =================================================================== RCS file: /cvsroot/omni/include/omnithread.h,v retrieving revision 1.17.6.4 retrieving revision 1.17.6.9 diff -u -u -r1.17.6.4 -r1.17.6.9 --- include/omnithread.h 2001/06/18 17:43:01 1.17.6.4 +++ include/omnithread.h 2001/12/11 16:53:00 1.17.6.9 @@ -36,7 +36,7 @@ #define __omnithread_h_ #ifndef NULL -#define NULL (void*)0 +#define NULL 0 #endif class omni_mutex; @@ -150,11 +150,20 @@ #elif defined(__freebsd__) #include +#elif defined(__openbsd__) +#include + #elif defined(__rtems__) #include #include #elif defined(__darwin__) +#include + +#elif defined(__OS2__) +#include + +#elif defined(__lynxos__) #include #else Index: include/omniORB3/CORBA.h =================================================================== RCS file: /cvsroot/omni/include/omniORB3/CORBA.h,v retrieving revision 1.1.2.15 retrieving revision 1.1.2.16 diff -u -u -r1.1.2.15 -r1.1.2.16 --- include/omniORB3/CORBA.h 2001/06/01 13:56:57 1.1.2.15 +++ include/omniORB3/CORBA.h 2001/11/12 13:15:07 1.1.2.16 @@ -29,6 +29,9 @@ /* $Log: CORBA.h,v $ + Revision 1.1.2.16 2001/11/12 13:15:07 dpg1 + _unchecked_narrow support. Thanks to Lars Immisch. + Revision 1.1.2.15 2001/06/01 13:56:57 sll Long long define for HPUX. External CPP define guard for IR.h @@ -1500,6 +1503,9 @@ static _ptr_type _duplicate(_ptr_type); static inline _ptr_type _narrow(Object_ptr o) { return _duplicate(o); } + static inline _ptr_type _unchecked_narrow(Object_ptr o) { + return _duplicate(o); + } static _ptr_type _nil(); ////////////////////// Index: include/omniORB3/CORBA_sysdep.h =================================================================== RCS file: /cvsroot/omni/include/omniORB3/CORBA_sysdep.h,v retrieving revision 1.1.2.23 retrieving revision 1.1.2.26 diff -u -u -r1.1.2.23 -r1.1.2.26 --- include/omniORB3/CORBA_sysdep.h 2001/06/01 13:56:57 1.1.2.23 +++ include/omniORB3/CORBA_sysdep.h 2002/01/16 12:01:46 1.1.2.26 @@ -32,6 +32,15 @@ /* $Log: CORBA_sysdep.h,v $ + Revision 1.1.2.26 2002/01/16 12:01:46 dpg1 + Darwin patches for MacOS X 10.1. + + Revision 1.1.2.25 2001/12/11 16:53:00 dpg1 + Bunch of new platforms, plus other minor tweaks. + + Revision 1.1.2.24 2001/09/28 16:16:43 dpg1 + Support for Sun CC > 4.x in 4.x compatibility mode. + Revision 1.1.2.23 2001/06/01 13:56:57 sll Long long define for HPUX. External CPP define guard for IR.h @@ -228,6 +237,10 @@ # define SIZEOF_LONG 8 # define SIZEOF_INT 4 # define SIZEOF_PTR 8 +# elif defined(__ia64__) +# define SIZEOF_LONG 8 +# define SIZEOF_INT 4 +# define SIZEOF_PTR 8 # endif # if __GNUG__ == 2 && __GNUC_MINOR__ == 7 @@ -311,8 +324,10 @@ # if __SUNPRO_CC < 0x420 # define NEED_DUMMY_RETURN # elif __SUNPRO_CC >= 0x500 -# define HAS_Cplusplus_Namespace -# define HAS_Std_Namespace +# if __SUNPRO_CC_COMPAT >= 5 +# define HAS_Cplusplus_Namespace +# define HAS_Std_Namespace +# endif # endif # define HAS_LongLong @@ -459,6 +474,11 @@ # if !defined(__WIN32__) # define _HAS_SIGNAL 1 # endif +#elif defined(__ia64__) +# define _OMNIORB_HOST_BYTE_ORDER_ 1 +# if !defined(__WIN32__) +# define _HAS_SIGNAL 1 +# endif #elif defined(__sunos__) && defined(__sparc__) # define _OMNIORB_HOST_BYTE_ORDER_ 0 # define _HAS_SIGNAL 1 @@ -479,22 +499,24 @@ # define _OMNIORB_HOST_BYTE_ORDER_ 0 # define _HAS_SIGNAL 1 # define OMNI_REQUIRES_FQ_BASE_CTOR 1 -#elif defined(__hpux__) && defined(__hppa__) +#elif defined(__hppa__) # define _OMNIORB_HOST_BYTE_ORDER_ 0 # define _HAS_SIGNAL 1 -#if __OSVERSION__ < 11 +# if defined(__hpux__) && __OSVERSION__ < 11 // Do we really need to include this here? -SLL // - not for HPUX 11.0 // need someone to check this for HPUX 10.20 -#include -#undef __ptr -#endif +# include +# undef __ptr +# endif #elif defined(__m68k__) && defined(__nextstep__) # define _OMNIORB_HOST_BYTE_ORDER_ 0 # define _HAS_SIGNAL 1 # define _USE_MACH_SIGNAL 1 # define _NO_STRDUP 1 # define _USE_GETHOSTNAME 1 +#elif defined(__darwin__) +# define _HAS_SIGNAL 1 #elif defined(__VMS) # define _OMNIORB_HOST_BYTE_ORDER_ 1 # if __VMS_VER >= 70000000 Index: include/omniORB3/omniObjRef.h =================================================================== RCS file: /cvsroot/omni/include/omniORB3/omniObjRef.h,v retrieving revision 1.1.2.4 retrieving revision 1.1.2.5 diff -u -u -r1.1.2.4 -r1.1.2.5 --- include/omniORB3/omniObjRef.h 2000/03/01 17:57:42 1.1.2.4 +++ include/omniORB3/omniObjRef.h 2001/11/12 13:15:08 1.1.2.5 @@ -29,6 +29,9 @@ /* $Log: omniObjRef.h,v $ + Revision 1.1.2.5 2001/11/12 13:15:08 dpg1 + _unchecked_narrow support. Thanks to Lars Immisch. + Revision 1.1.2.4 2000/03/01 17:57:42 dpg1 New omniObjRef::_compatibleServant() function to support object references and servants written for languages other than C++. @@ -120,9 +123,20 @@ // interface type identified by the IR repository ID , return // a valid object reference. Otherwise, return 0. The return value is // of type void* and can be casted to the T_ptr type of the interface - // T directly. If necassary we contact the object itself to check the + // T directly. If necessary we contact the object itself to check the // inheritance relation. must be a type for which there exists // a proxy object factory. + // This function is thread-safe. + // Does not throw any exceptions. + + void* _uncheckedNarrow(const char* repoId); + // Return a valid object reference to the interface type identified + // by . We do not contact the object itself to check the + // inheritance relation, so subsequent operations on this object may + // fail because it actually does not implement the interface. This + // function _always_ succeeds, no matter what interface we ask for. + // must be a type for which there exists a proxy object + // factory. // This function is thread-safe. // Does not throw any exceptions. Index: include/omniORB3/templatedecls.h =================================================================== RCS file: /cvsroot/omni/include/omniORB3/templatedecls.h,v retrieving revision 1.1.2.3 retrieving revision 1.1.2.4 diff -u -u -r1.1.2.3 -r1.1.2.4 --- include/omniORB3/templatedecls.h 2001/03/07 12:29:57 1.1.2.3 +++ include/omniORB3/templatedecls.h 2001/08/20 13:48:00 1.1.2.4 @@ -831,6 +831,10 @@ ///////////////// _CORBA_ConstrType_Fix_OUT_arg ///////////////// ////////////////////////////////////////////////////////////////////// +// This is incorrect, and is no longer used by omniidl output. It's +// kept here for compatibility with stubs generated by earlier +// versions of omniidl. + template class _CORBA_ConstrType_Fix_OUT_arg { public: Index: mk/win32.mk =================================================================== RCS file: /cvsroot/omni/mk/win32.mk,v retrieving revision 1.2.6.14 retrieving revision 1.2.6.15 diff -u -u -r1.2.6.14 -r1.2.6.15 --- mk/win32.mk 2001/06/15 13:27:26 1.2.6.14 +++ mk/win32.mk 2001/08/22 10:08:43 1.2.6.15 @@ -262,7 +262,8 @@ # template: # ... ........ SECT.. notype External | ?[^?].............. # -# Default destructors generated by the compiler are excluded. +# Default destructors generated by the compiler and the symbols +# inside an anonymous namespace are excluded. # # It looks like class variable and function symbols start with two ?? # and class static variable and static function symbols start with one ?. @@ -279,6 +280,7 @@ DUMPBIN.EXE /SYMBOLS $$symreflib | \ egrep '^[^ ]+ +[^ ]+ +SECT[^ ]+ +[^ ]+ +\(\) +External +\| +\?[^ ]*|^[^ ]+ +[^ ]+ +SECT[^ ]+ +[^ ]+ +External +\| +\?[^?][^ ]*'|\ egrep -v 'deleting destructor[^(]+\(unsigned int\)' | \ +egrep -v 'anonymous namespace' | \ cut -d'|' -f2 | \ cut -d' ' -f2 | $(SORT) -u >> $$defname; \ set +x; @@ -302,13 +304,18 @@ dllname=$$targetdir/$$libname.dll; \ defname=$$targetdir/$(SharedLibraryExportSymbolFileNameTemplate); \ version=$(SharedLibraryVersionStringTemplate); \ +if [ -n "$$debug" ]; then \ +extralinkoption="$(MSVC_DLL_CXXLINKDEBUGOPTIONS)"; \ +else \ +extralinkoption="$(MSVC_DLL_CXXLINKNODEBUGOPTIONS)"; \ +fi; \ if [ -z "$$nodeffile" ]; then \ $(MakeCXXExportSymbolDefinitionFile) \ defflag="-def:$$defname"; \ fi; \ set -x; \ $(RM) $@; \ -$(CXXLINK) -out:$$dllname -DLL $(MSVC_DLL_CXXLINKNODEBUGOPTIONS) \ +$(CXXLINK) -out:$$dllname -DLL $$extralinkoption \ $$defflag -IMPLIB:$@ $(IMPORT_LIBRARY_FLAGS) \ $^ $$extralibs; endef Index: mk/platforms/alpha_linux_2.0.mk =================================================================== RCS file: /cvsroot/omni/mk/platforms/alpha_linux_2.0.mk,v retrieving revision 1.2.6.3 retrieving revision 1.2.6.4 diff -u -u -r1.2.6.3 -r1.2.6.4 --- mk/platforms/alpha_linux_2.0.mk 2000/08/09 16:07:27 1.2.6.3 +++ mk/platforms/alpha_linux_2.0.mk 2001/12/11 16:52:59 1.2.6.4 @@ -2,6 +2,12 @@ # alpha_linux_2.0.mk - make variables and rules specific to Linux 2.0. # +# WARNING! +# +# omniORB does not work properly on Alpha Linux. gcc does not generate +# thread-safe exception handling code. + + Linux = 1 AlphaProcessor = 1 @@ -38,11 +44,6 @@ $(patsubst %,-Wl$(comma)-rpath$(comma)%,$(IMPORT_LIBRARY_DIRS)) CXXOPTIONS = -Wall -Wno-unused - -# Notice that this platform will be supported when egcs-1.1 is released. -# The binary compiled with egcs-1.0.x and egcs development snapshots, up to -# 980824, do not work!!!! -# EgcsMajorVersion = 1 EgcsMinorVersion = 1 @@ -87,3 +88,13 @@ # Default directory for the omniNames log files. OMNINAMES_LOG_DEFAULT_LOCATION = /var/omninames + +# +# Shared Library support. +# +BuildSharedLibrary = 1 # Enable +SHAREDLIB_CPPFLAGS = -fPIC # compiler flag + +ifeq ($(notdir $(CC)),KCC) +SharedLibraryPlatformLinkFlagsTemplate = --thread_safe --soname $$soname +endif Index: mk/platforms/hppa_hpux_10.20.mk =================================================================== RCS file: /cvsroot/omni/mk/platforms/hppa_hpux_10.20.mk,v retrieving revision 1.2.6.6 retrieving revision 1.2.6.7 diff -u -u -r1.2.6.6 -r1.2.6.7 --- mk/platforms/hppa_hpux_10.20.mk 2000/08/16 11:25:37 1.2.6.6 +++ mk/platforms/hppa_hpux_10.20.mk 2001/12/11 16:52:59 1.2.6.7 @@ -109,7 +109,7 @@ #CC = gcc #CMAKEDEPEND += __GNUC__ #CDEBUGFLAGS = -O -#COPTIONS = $(CDEBUGFLAGS) $(COPTIONS) \ +#COPTIONS = $(CDEBUGFLAGS) \ # $(patsubst %,-Wl$(comma)-rpath$(comma)%,$(IMPORT_LIBRARY_DIRS)) #CLINKOPTIONS = #CLINK = $(CC) Index: mk/platforms/hppa_hpux_11.00.mk =================================================================== RCS file: /cvsroot/omni/mk/platforms/hppa_hpux_11.00.mk,v retrieving revision 1.1.6.11 retrieving revision 1.1.6.12 diff -u -u -r1.1.6.11 -r1.1.6.12 --- mk/platforms/hppa_hpux_11.00.mk 2000/11/23 13:05:04 1.1.6.11 +++ mk/platforms/hppa_hpux_11.00.mk 2001/07/16 10:24:58 1.1.6.12 @@ -193,9 +193,11 @@ SHAREDLIB_CPPFLAGS += +Z -SharedLibraryPlatformLinkFlagsTemplate = -b -Wl,+h$$soname +SharedLibraryPlatformLinkFlagsTemplate = -b -Wl,+h$$soname -Wl,+s # May need $(patsubst %,-L %,$(IMPORT_LIBRARY_DIRS)) +endif + ifeq ($(notdir $(CC)),gcc) SHAREDLIB_CFLAGS = -fPIC endif @@ -206,4 +208,3 @@ SharedLibraryPlatformLinkFlagsTemplate = --thread_safe --soname $$soname endif -endif Index: mk/platforms/powerpc_darwin_1.3.mk =================================================================== RCS file: /cvsroot/omni/mk/platforms/powerpc_darwin_1.3.mk,v retrieving revision 1.1.2.2 retrieving revision 1.1.2.3 diff -u -u -r1.1.2.2 -r1.1.2.3 --- mk/platforms/powerpc_darwin_1.3.mk 2001/06/21 13:38:59 1.1.2.2 +++ mk/platforms/powerpc_darwin_1.3.mk 2002/01/16 12:01:45 1.1.2.3 @@ -83,7 +83,7 @@ SharedLibraryFullNameTemplate = lib$$1$$2.$$3.$$4.$(SHAREDLIB_SUFFIX) SharedLibrarySoNameTemplate = lib$$1$$2.$$3.$(SHAREDLIB_SUFFIX) SharedLibraryLibNameTemplate = lib$$1$$2.$(SHAREDLIB_SUFFIX) -SharedLibraryPlatformLinkFlagsTemplate = -dynamiclib -undefined suppress +SharedLibraryPlatformLinkFlagsTemplate = -dynamiclib -flat_namespace -undefined suppress # Re-define 'ExportLibrary' to run 'ranlib' after the file is copied, # for static libraries as otherwise the linker complains: "table of Index: patches/README =================================================================== RCS file: /cvsroot/omni/patches/README,v retrieving revision 1.1.6.1 retrieving revision 1.1.6.2 diff -u -u -r1.1.6.1 -r1.1.6.2 --- patches/README 2000/07/10 10:47:02 1.1.6.1 +++ patches/README 2002/01/09 11:20:27 1.1.6.2 @@ -1,7 +1,9 @@ -This directory contains patches to the source to work around bugs in some -old compilers. +This directory contains patches to the source to work around bugs in +some old compilers, and to support platforms for which the patches are +too obtrusive to be included in the main distribution. The patches are: dec_CXX_5.6.patch - patch to apply to work around bugs in Dec C++ 5.6. aix_xlC_5.0.patch - patch to work around problems with VisualAge C++ 5.0. + BS2000.patch - patch to support Fujitsu Siemens BS2000 Index: src/appl/omniMapper/omniMapper.cc =================================================================== RCS file: /cvsroot/omni/src/appl/omniMapper/omniMapper.cc,v retrieving revision 1.1.2.3 retrieving revision 1.1.2.4 diff -u -u -r1.1.2.3 -r1.1.2.4 --- src/appl/omniMapper/omniMapper.cc 2001/01/16 12:54:46 1.1.2.3 +++ src/appl/omniMapper/omniMapper.cc 2001/10/03 14:16:27 1.1.2.4 @@ -21,8 +21,11 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // 02111-1307, USA. -// $Id: omniMapper.cc,v 1.1.2.3 2001/01/16 12:54:46 dpg1 Exp $ +// $Id: omniMapper.cc,v 1.1.2.4 2001/10/03 14:16:27 dpg1 Exp $ // $Log: omniMapper.cc,v $ +// Revision 1.1.2.4 2001/10/03 14:16:27 dpg1 +// Remove double "is" from error messages. +// // Revision 1.1.2.3 2001/01/16 12:54:46 dpg1 // omniNames and omniMapper now complain if they cannot open the // requested port, rather than dying with an uncaught exception. @@ -270,7 +273,7 @@ } catch (CORBA::INITIALIZE& ex) { cerr << "Failed to initialise the POA. " - << "Is omniMapper is already running?" << endl; + << "Is omniMapper already running?" << endl; return 1; } Index: src/appl/omniNames/BindingIterator_i.h =================================================================== RCS file: /cvsroot/omni/src/appl/omniNames/BindingIterator_i.h,v retrieving revision 1.5.8.3 retrieving revision 1.5.8.4 diff -u -u -r1.5.8.3 -r1.5.8.4 --- src/appl/omniNames/BindingIterator_i.h 2000/02/22 18:38:24 1.5.8.3 +++ src/appl/omniNames/BindingIterator_i.h 2001/10/05 16:52:19 1.5.8.4 @@ -44,7 +44,7 @@ BindingIterator_i(PortableServer::POA_ptr poa, CosNaming::BindingList* l) : list(l) { - poa->activate_object(this); + PortableServer::ObjectId_var id = poa->activate_object(this); } CORBA::Boolean next_one(CosNaming::Binding_out b) { Index: src/appl/omniNames/omniNames.cc =================================================================== RCS file: /cvsroot/omni/src/appl/omniNames/omniNames.cc,v retrieving revision 1.8.6.4 retrieving revision 1.8.6.5 diff -u -u -r1.8.6.4 -r1.8.6.5 --- src/appl/omniNames/omniNames.cc 2001/01/16 12:54:46 1.8.6.4 +++ src/appl/omniNames/omniNames.cc 2001/10/03 14:16:27 1.8.6.5 @@ -206,7 +206,7 @@ } catch (CORBA::INITIALIZE& ex) { cerr << "Failed to initialise the POAs. " - << "Is omniNames is already running?" << endl; + << "Is omniNames already running?" << endl; return 1; } Index: src/appl/utils/nameclt/nameclt.cc =================================================================== RCS file: /cvsroot/omni/src/appl/utils/nameclt/nameclt.cc,v retrieving revision 1.18.6.3 retrieving revision 1.18.6.4 diff -u -u -r1.18.6.3 -r1.18.6.4 --- src/appl/utils/nameclt/nameclt.cc 2000/06/19 15:25:57 1.18.6.3 +++ src/appl/utils/nameclt/nameclt.cc 2001/07/06 14:24:44 1.18.6.4 @@ -209,6 +209,9 @@ context->list(0, bl, bi); + if (CORBA::is_nil(bi)) + goto done; + while (bi->next_one(b)) { CORBA::String_var sname = omniURI::nameToString(b->binding_name); Index: src/lib/omniORB2/dynamic/request.cc =================================================================== RCS file: /cvsroot/omni/src/lib/omniORB2/dynamic/request.cc,v retrieving revision 1.8.6.4 retrieving revision 1.8.6.5 diff -u -u -r1.8.6.4 -r1.8.6.5 --- src/lib/omniORB2/dynamic/request.cc 2000/06/22 10:37:50 1.8.6.4 +++ src/lib/omniORB2/dynamic/request.cc 2001/09/25 09:59:26 1.8.6.5 @@ -341,7 +341,8 @@ #else while(1) { #endif - o->_assertExistsAndTypeVerified(); + if (omniORB::verifyObjectExistsAndType) + o->_assertExistsAndTypeVerified(); try{ @@ -548,7 +549,8 @@ #else while(1) { #endif - o->_assertExistsAndTypeVerified(); + if (omniORB::verifyObjectExistsAndType) + o->_assertExistsAndTypeVerified(); try{ Index: src/lib/omniORB2/dynamic/sharedlib/dir.mk =================================================================== RCS file: /cvsroot/omni/src/lib/omniORB2/dynamic/sharedlib/dir.mk,v retrieving revision 1.13.6.8 retrieving revision 1.13.6.10 diff -u -u -r1.13.6.8 -r1.13.6.10 --- src/lib/omniORB2/dynamic/sharedlib/dir.mk 2001/06/18 17:43:01 1.13.6.8 +++ src/lib/omniORB2/dynamic/sharedlib/dir.mk 2002/01/16 12:01:46 1.13.6.10 @@ -514,7 +514,7 @@ $(dynlib): $(DYN_OBJS) (set -x; \ $(RM) $@; \ - aCC -b -Wl,+h$(dynsoname) -o $@ $(IMPORT_LIBRARY_FLAGS) \ + aCC -b -Wl,+h$(dynsoname) -Wl,+s -o $@ $(IMPORT_LIBRARY_FLAGS) \ $(patsubst %,-L %,$(IMPORT_LIBRARY_DIRS)) \ $(filter-out $(LibSuffixPattern),$^) $(OMNITHREAD_LIB) \ -lomniORB$(major_version) \ @@ -740,7 +740,7 @@ $(dynlib): $(DYN_OBJS) (set -x; \ $(RM) $@; \ - $(CXX) -dynamiclib -undefined suppress -o $@ \ + $(CXX) -dynamiclib -flat_namespace -undefined suppress -o $@ \ $(IMPORT_LIBRARY_FLAGS) \ $(filter-out $(LibSuffixPattern),$^) $(OMNITHREAD_LIB); \ ) Index: src/lib/omniORB2/omniidl_be/dir.mk =================================================================== RCS file: /cvsroot/omni/src/lib/omniORB2/omniidl_be/dir.mk,v retrieving revision 1.4.2.3 retrieving revision 1.4.2.4 diff -u -u -r1.4.2.3 -r1.4.2.4 --- src/lib/omniORB2/omniidl_be/dir.mk 2000/02/18 16:17:16 1.4.2.3 +++ src/lib/omniORB2/omniidl_be/dir.mk 2001/07/25 10:52:19 1.4.2.4 @@ -19,5 +19,5 @@ export:: __init__.py @(file="__init__.py"; dir="$(PYLIBDIR)"; $(ExportFileToDir)) -export:: showast.py - @(file="showast.py"; dir="$(PYLIBDIR)"; $(ExportFileToDir)) +# export:: showast.py +# @(file="showast.py"; dir="$(PYLIBDIR)"; $(ExportFileToDir)) Index: src/lib/omniORB2/omniidl_be/showast.py =================================================================== RCS file: /cvsroot/omni/src/lib/omniORB2/omniidl_be/showast.py,v retrieving revision 1.2.2.1 retrieving revision 1.2.2.2 diff -u -u -r1.2.2.1 -r1.2.2.2 --- src/lib/omniORB2/omniidl_be/showast.py 2000/02/14 18:34:57 1.2.2.1 +++ src/lib/omniORB2/omniidl_be/showast.py 2001/07/25 10:45:18 1.2.2.2 @@ -27,8 +27,23 @@ # Simple AST dumping module for testing utility functions etc # (derived from dpg1's dump.py) -# $Id: showast.py,v 1.2.2.1 2000/02/14 18:34:57 dpg1 Exp $ + +# ************************* +# +# THIS IS BROKEN +# +# Don't try to use this -- it does not work. It is only left here in +# case someone wishes to fix it. + +assert 0, "The showast backend is not in a working state. Do not try to use it." + + + +# $Id: showast.py,v 1.2.2.2 2001/07/25 10:45:18 dpg1 Exp $ # $Log: showast.py,v $ +# Revision 1.2.2.2 2001/07/25 10:45:18 dpg1 +# Hack the showast.py back-end so it is clear that it's broken. +# # Revision 1.2.2.1 2000/02/14 18:34:57 dpg1 # New omniidl merged in. # Index: src/lib/omniORB2/omniidl_be/cxx/__init__.py =================================================================== RCS file: /cvsroot/omni/src/lib/omniORB2/omniidl_be/cxx/__init__.py,v retrieving revision 1.18.2.12 retrieving revision 1.18.2.14 diff -u -u -r1.18.2.12 -r1.18.2.14 --- src/lib/omniORB2/omniidl_be/cxx/__init__.py 2001/04/25 17:07:21 1.18.2.12 +++ src/lib/omniORB2/omniidl_be/cxx/__init__.py 2002/03/01 15:51:02 1.18.2.14 @@ -26,8 +26,14 @@ # # Entrypoint to the C++ backend -# $Id: __init__.py,v 1.18.2.12 2001/04/25 17:07:21 dpg1 Exp $ +# $Id: __init__.py,v 1.18.2.14 2002/03/01 15:51:02 dpg1 Exp $ # $Log: __init__.py,v $ +# Revision 1.18.2.14 2002/03/01 15:51:02 dpg1 +# Add -Wbe switch to C++ back-end for changing example impl suffix. +# +# Revision 1.18.2.13 2002/02/20 13:33:46 dpg1 +# C++ back-end old signatures option did not work. +# # Revision 1.18.2.12 2001/04/25 17:07:21 dpg1 # Properly handle files #included at non-file scope. # @@ -193,7 +199,7 @@ elif arg == "BOA": config.state['BOA Skeletons'] = 1 elif arg == "old": - config.state['Old Signatures'] = 0 + config.state['Old Signatures'] = 1 elif arg == "old_prefix": config.state['Reserved Prefix'] = "_" elif arg == "keep_inc_path": @@ -210,6 +216,8 @@ config.state['SK Suffix'] = arg[2:] elif arg[:2] == "d=": config.state['DYNSK Suffix'] = arg[2:] + elif arg[:2] == "e=": + config.state['IMPL Suffix'] = arg[2:] elif arg == "inline": config.state['Inline Includes'] = 1 else: Index: src/lib/omniORB2/omniidl_be/cxx/id.py =================================================================== RCS file: /cvsroot/omni/src/lib/omniORB2/omniidl_be/cxx/id.py,v retrieving revision 1.1.2.2 retrieving revision 1.1.2.3 diff -u -u -r1.1.2.2 -r1.1.2.3 --- src/lib/omniORB2/omniidl_be/cxx/id.py 2000/06/26 16:23:10 1.1.2.2 +++ src/lib/omniORB2/omniidl_be/cxx/id.py 2001/07/27 17:08:24 1.1.2.3 @@ -26,7 +26,7 @@ # # Environment handling, identifier scoping, naming -from omniidl import idlvisitor +from omniidl import idlvisitor, idlutil import id, config, util @@ -132,27 +132,36 @@ """relName(id.Name, id.Environment): string list Returns a list of the name components essential to making the name unambiguous""" - # first try to progressively add scopes - sn = self.__scopedName[:] - sn.reverse() - relName = [ sn[0] ] - del sn[0] - - name = None - while 1: - name = environment.lookup(relName) - # case name of None => nothing was found at all - # | self => lookup was successful - # | other => too ambiguous still - if name != None and (name.__scopedName == self.__scopedName): - return relName - if sn == []: - # the fully scoped (not from root) name is - # not unambiguous- must go from root - return None - # add more scope and continue - relName = [ sn[0] ] + relName - del sn[0] + rscope = idlutil.relativeScope(environment._Environment__scope, + self.__scopedName) + if rscope and rscope[0] is None: + return None + else: + return rscope + + # Old broken implementation follows... + +# # first try to progressively add scopes +# sn = self.__scopedName[:] +# sn.reverse() +# relName = [ sn[0] ] +# del sn[0] + +# name = None +# while 1: +# name = environment.lookup(relName) +# # case name of None => nothing was found at all +# # | self => lookup was successful +# # | other => too ambiguous still +# if name != None and (name.__scopedName == self.__scopedName): +# return relName +# if sn == []: +# # the fully scoped (not from root) name is +# # not unambiguous- must go from root +# return None +# # add more scope and continue +# relName = [ sn[0] ] + relName +# del sn[0] def unambiguous(self, environment, cxx = 1): """unambiguous(id.Name, id.Environment option, cxx boolean): string Index: src/lib/omniORB2/omniidl_be/cxx/header/defs.py =================================================================== RCS file: /cvsroot/omni/src/lib/omniORB2/omniidl_be/cxx/header/defs.py,v retrieving revision 1.31.2.21 retrieving revision 1.31.2.22 diff -u -u -r1.31.2.21 -r1.31.2.22 --- src/lib/omniORB2/omniidl_be/cxx/header/defs.py 2001/04/25 16:55:09 1.31.2.21 +++ src/lib/omniORB2/omniidl_be/cxx/header/defs.py 2001/08/20 13:48:00 1.31.2.22 @@ -26,8 +26,12 @@ # # Produce the main header definitions for the C++ backend -# $Id: defs.py,v 1.31.2.21 2001/04/25 16:55:09 dpg1 Exp $ +# $Id: defs.py,v 1.31.2.22 2001/08/20 13:48:00 dpg1 Exp $ # $Log: defs.py,v $ +# Revision 1.31.2.22 2001/08/20 13:48:00 dpg1 +# Wrong _out type generated for fixed length structs/unions. +# (Back-ported from omniORB 4.) +# # Revision 1.31.2.21 2001/04/25 16:55:09 dpg1 # Properly handle files #included at non-file scope. # @@ -856,10 +860,17 @@ dup_loop = dup_loop, copy_loop = copy_loop) # output the _copyHelper class - stream.out(template.typedef_array_copyHelper, - name = derivedName) - - + if types.variableDecl(node): + stream.out(template.typedef_array_copyHelper, + name = derivedName) + stream.out(template.typedef_array_variable_out_type, + name = derivedName) + else: + stream.out(template.typedef_array_copyHelper, + name = derivedName) + stream.out(template.typedef_array_fix_out_type, + name = derivedName) + def visitMember(node): memberType = node.memberType() @@ -918,11 +929,22 @@ dims = tyutil.dimsToString(decl_dims)) # Output the structure itself - stream.out(template.struct, - name = cxx_name, - type = type, - Other_IDL = Other_IDL, - members = members) + if types.variableDecl(node): + stream.out(template.struct, + name = cxx_name, + type = "Variable", + Other_IDL = Other_IDL, + members = members) + stream.out(template.struct_variable_out_type, + name = cxx_name) + else: + stream.out(template.struct, + name = cxx_name, + type = "Fix", + Other_IDL = Other_IDL, + members = members) + stream.out(template.struct_fix_out_type, + name = cxx_name) self.__insideClass = insideClass @@ -1602,7 +1624,13 @@ tcParser_unionHelper = tcParser_unionHelper, union = str(inside), outsideUnion = str(outside)) - + + if types.variableDecl(node): + stream.out(template.union_variable_out_type, + unionname = cxx_id) + else: + stream.out(template.union_fix_out_type, + unionname = cxx_id) self.__insideClass = insideClass Index: src/lib/omniORB2/omniidl_be/cxx/header/template.py =================================================================== RCS file: /cvsroot/omni/src/lib/omniORB2/omniidl_be/cxx/header/template.py,v retrieving revision 1.3.2.17 retrieving revision 1.3.2.20 diff -u -u -r1.3.2.17 -r1.3.2.20 --- src/lib/omniORB2/omniidl_be/cxx/header/template.py 2000/09/25 11:03:28 1.3.2.17 +++ src/lib/omniORB2/omniidl_be/cxx/header/template.py 2001/11/12 13:15:08 1.3.2.20 @@ -26,8 +26,18 @@ # # C++ templates for the .hh file -# $Id: template.py,v 1.3.2.17 2000/09/25 11:03:28 dpg1 Exp $ +# $Id: template.py,v 1.3.2.20 2001/11/12 13:15:08 dpg1 Exp $ # $Log: template.py,v $ +# Revision 1.3.2.20 2001/11/12 13:15:08 dpg1 +# _unchecked_narrow support. Thanks to Lars Immisch. +# +# Revision 1.3.2.19 2001/08/20 13:48:01 dpg1 +# Wrong _out type generated for fixed length structs/unions. +# (Back-ported from omniORB 4.) +# +# Revision 1.3.2.18 2001/08/16 09:11:35 dpg1 +# Union discriminator not copied. +# # Revision 1.3.2.17 2000/09/25 11:03:28 dpg1 # Remove use of _T as a template class name # @@ -294,6 +304,7 @@ static _ptr_type _duplicate(_ptr_type); static _ptr_type _narrow(CORBA::Object_ptr); + static _ptr_type _unchecked_narrow(CORBA::Object_ptr); static _ptr_type _nil(); static inline size_t _alignedSize(_ptr_type, size_t); @@ -530,10 +541,17 @@ }; typedef _CORBA_Array_Var<@name@_copyHelper,@name@_slice> @name@_var; -typedef _CORBA_Array_OUT_arg<@name@_slice,@name@_var > @name@_out; typedef _CORBA_Array_Forany<@name@_copyHelper,@name@_slice> @name@_forany; """ +typedef_array_fix_out_type = """\ +typedef @name@_slice* @name@_out; +""" + +typedef_array_variable_out_type = """\ +typedef _CORBA_Array_OUT_arg<@name@_slice,@name@_var > @name@_out; +""" + ## ## Sequences ## @@ -700,10 +718,16 @@ }; typedef @name@::_var_type @name@_var; +""" -typedef _CORBA_ConstrType_@type@_OUT_arg< @name@,@name@_var > @name@_out; +struct_fix_out_type = """\ +typedef @name@& @name@_out; """ +struct_variable_out_type = """\ +typedef _CORBA_ConstrType_Variable_OUT_arg< @name@,@name@_var > @name@_out; +""" + struct_nonarray_sequence = """\ typedef @memtype@ _@cxx_id@_seq; _@cxx_id@_seq @cxx_id@; @@ -779,19 +803,20 @@ union_ctor_nonexhaustive = """\ if ((_pd__default = _value._pd__default)) { - _pd__d = _value._pd__d; @default@ } else { switch(_value._pd__d) { @cases@ } -}""" +} +_pd__d = _value._pd__d;""" union_ctor_exhaustive = """\ switch(_value._pd__d) { @cases@ -}""" +} +_pd__d = _value._pd__d;""" union_ctor_case = """\ case @discrimvalue@: @name@(_value._pd_@name@); break; @@ -859,8 +884,16 @@ }; typedef @unionname@::_var_type @unionname@_var; -typedef _CORBA_ConstrType_@fixed@_OUT_arg< @unionname@,@unionname@_var > @unionname@_out; """ + +union_fix_out_type = """\ +typedef @unionname@& @unionname@_out; +""" + +union_variable_out_type = """\ +typedef _CORBA_ConstrType_Variable_OUT_arg< @unionname@,@unionname@_var > @unionname@_out; +""" + union_union = """\ union { @members@ Index: src/lib/omniORB2/omniidl_be/cxx/skel/template.py =================================================================== RCS file: /cvsroot/omni/src/lib/omniORB2/omniidl_be/cxx/skel/template.py,v retrieving revision 1.1.2.11 retrieving revision 1.1.2.12 diff -u -u -r1.1.2.11 -r1.1.2.12 --- src/lib/omniORB2/omniidl_be/cxx/skel/template.py 2001/04/27 11:03:56 1.1.2.11 +++ src/lib/omniORB2/omniidl_be/cxx/skel/template.py 2001/11/12 13:15:08 1.1.2.12 @@ -26,8 +26,11 @@ # # C++ templates for the SK.cc file -# $Id: template.py,v 1.1.2.11 2001/04/27 11:03:56 dpg1 Exp $ +# $Id: template.py,v 1.1.2.12 2001/11/12 13:15:08 dpg1 Exp $ # $Log: template.py,v $ +# Revision 1.1.2.12 2001/11/12 13:15:08 dpg1 +# _unchecked_narrow support. Thanks to Lars Immisch. +# # Revision 1.1.2.11 2001/04/27 11:03:56 dpg1 # Fix scoping bug in MSVC work-around for external constant linkage. # @@ -138,7 +141,6 @@ return obj; } - @name@_ptr @name@::_narrow(CORBA::Object_ptr obj) { @@ -147,6 +149,13 @@ return e ? e : _nil(); } +@name@_ptr +@name@::_unchecked_narrow(CORBA::Object_ptr obj) +{ + if( !obj || obj->_NP_is_nil() || obj->_NP_is_pseudo() ) return _nil(); + _ptr_type e = (_ptr_type) obj->_PR_getobj()->_uncheckedNarrow(_PD_repoId); + return e ? e : _nil(); +} @name@_ptr @name@::_nil() Index: src/lib/omniORB2/orbcore/corbaBoa.cc =================================================================== RCS file: /cvsroot/omni/src/lib/omniORB2/orbcore/corbaBoa.cc,v retrieving revision 1.13.6.16 retrieving revision 1.13.6.17 diff -u -u -r1.13.6.16 -r1.13.6.17 --- src/lib/omniORB2/orbcore/corbaBoa.cc 2001/04/23 14:49:58 1.13.6.16 +++ src/lib/omniORB2/orbcore/corbaBoa.cc 2001/07/24 14:58:53 1.13.6.17 @@ -29,6 +29,9 @@ /* $Log: corbaBoa.cc,v $ + Revision 1.13.6.17 2001/07/24 14:58:53 dpg1 + Fix race conditions with servant activators. + Revision 1.13.6.16 2001/04/23 14:49:58 dpg1 Null pointer dereference in BOA_init() @@ -700,7 +703,13 @@ void omniOrbBOA::lastInvocationHasCompleted(omniLocalIdentity* id) { - ASSERT_OMNI_TRACEDMUTEX_HELD(*omni::internalLock, 0); + ASSERT_OMNI_TRACEDMUTEX_HELD(*omni::internalLock, 1); + + // Make sure the object is gone from the object table + omniLocalIdentity* did = omni::deactivateObject(id->key(), + id->keysize()); + OMNIORB_ASSERT(did == id || did == 0); + omni::internalLock->unlock(); if( omniORB::trace(15) ) { omniORB::logger l; @@ -747,8 +756,11 @@ return; } - omniLocalIdentity* id = omni::deactivateObject(lid->key(), lid->keysize()); - if( !id ) { + CORBA::ULong hash = omni::hash(lid->key(), lid->keysize()); + + omniLocalIdentity* id = omni::locateIdentity(lid->key(), + lid->keysize(), hash); + if( !id || !id->servant() ) { omni::internalLock->unlock(); boa_lock.unlock(); return; @@ -759,6 +771,11 @@ id->removeFromOAObjList(); if( id->is_idle() ) { + // TODO: this should use lastInvocationHasCompleted() + + omniLocalIdentity* did = omni::deactivateObject(id->key(), id->keysize()); + OMNIORB_ASSERT(did == id); + omni::internalLock->unlock(); boa_lock.unlock(); Index: src/lib/omniORB2/orbcore/localIdentity.cc =================================================================== RCS file: /cvsroot/omni/src/lib/omniORB2/orbcore/localIdentity.cc,v retrieving revision 1.1.2.5 retrieving revision 1.1.2.6 diff -u -u -r1.1.2.5 -r1.1.2.6 --- src/lib/omniORB2/orbcore/localIdentity.cc 2000/06/22 10:40:15 1.1.2.5 +++ src/lib/omniORB2/orbcore/localIdentity.cc 2001/07/24 14:58:53 1.1.2.6 @@ -28,6 +28,9 @@ /* $Log: localIdentity.cc,v $ + Revision 1.1.2.6 2001/07/24 14:58:53 dpg1 + Fix race conditions with servant activators. + Revision 1.1.2.5 2000/06/22 10:40:15 dpg1 exception.h renamed to exceptiondefs.h to avoid name clash on some platforms. @@ -75,15 +78,17 @@ omni::internalLock->lock(); pd_id->pd_nInvocations--; pd_id->pd_adapter->leaveAdapter(); - int done = pd_id->pd_nInvocations > 0; - omni::internalLock->unlock(); - if( done ) return; + if (pd_id->pd_nInvocations > 0) { + omni::internalLock->unlock(); + return; + } // Object has been deactivated, and the last invocation // has completed. Pass the object back to the adapter // so it can be etherealised. pd_id->adapter()->lastInvocationHasCompleted(pd_id); - } + // lastInvocationHasCompleted() has released . + } private: omniLocalIdentity* pd_id; }; Index: src/lib/omniORB2/orbcore/localIdentity.h =================================================================== RCS file: /cvsroot/omni/src/lib/omniORB2/orbcore/localIdentity.h,v retrieving revision 1.1.2.3 retrieving revision 1.1.2.4 diff -u -u -r1.1.2.3 -r1.1.2.4 --- src/lib/omniORB2/orbcore/localIdentity.h 2000/06/02 16:09:59 1.1.2.3 +++ src/lib/omniORB2/orbcore/localIdentity.h 2001/07/24 14:58:53 1.1.2.4 @@ -29,6 +29,9 @@ /* $Log: localIdentity.h,v $ + Revision 1.1.2.4 2001/07/24 14:58:53 dpg1 + Fix race conditions with servant activators. + Revision 1.1.2.3 2000/06/02 16:09:59 dpg1 If an object is deactivated while its POA is in the HOLDING state, clients which were held now receive a TRANSIENT exception when the POA @@ -110,7 +113,6 @@ OMNIORB_ASSERT(pd_nInvocations > 0); --pd_nInvocations; } - // This should only be called after doing omni::deactivateObject(). // Must hold . void die(); @@ -203,6 +205,7 @@ // that it never goes to zero. The initial value is 1 for // this reason. deactivate() decrements this value, so that // the adapter will be told when there are no invocations. + // Protected by . omniServant* pd_servant; // Nil if this object is not yet incarnated, but once set Index: src/lib/omniORB2/orbcore/objectAdapter.h =================================================================== RCS file: /cvsroot/omni/src/lib/omniORB2/orbcore/objectAdapter.h,v retrieving revision 1.1.2.4 retrieving revision 1.1.2.5 diff -u -u -r1.1.2.4 -r1.1.2.5 --- src/lib/omniORB2/orbcore/objectAdapter.h 2000/08/08 15:01:44 1.1.2.4 +++ src/lib/omniORB2/orbcore/objectAdapter.h 2001/07/24 14:58:53 1.1.2.5 @@ -28,6 +28,9 @@ /* $Log: objectAdapter.h,v $ + Revision 1.1.2.5 2001/07/24 14:58:53 dpg1 + Fix race conditions with servant activators. + Revision 1.1.2.4 2000/08/08 15:01:44 dpg1 -ORBpoa_iiop_port no longer overrides OMNIORB_USEHOSTNAME. @@ -180,7 +183,8 @@ // case the object adapter calls this), or when any outstanding // method invocations complete (in which case the // omniLocalIdentity calls this). - // The caller must not hold any locks. + // The caller must hold on entry. It is + // released on exit. //////////////////// Index: src/lib/omniORB2/orbcore/omniObjRef.cc =================================================================== RCS file: /cvsroot/omni/src/lib/omniORB2/orbcore/omniObjRef.cc,v retrieving revision 1.1.2.7 retrieving revision 1.1.2.8 diff -u -u -r1.1.2.7 -r1.1.2.8 --- src/lib/omniORB2/orbcore/omniObjRef.cc 2001/05/04 16:53:08 1.1.2.7 +++ src/lib/omniORB2/orbcore/omniObjRef.cc 2001/11/12 13:15:08 1.1.2.8 @@ -28,6 +28,9 @@ /* $Log: omniObjRef.cc,v $ + Revision 1.1.2.8 2001/11/12 13:15:08 dpg1 + _unchecked_narrow support. Thanks to Lars Immisch. + Revision 1.1.2.7 2001/05/04 16:53:08 dpg1 Work-around for Compaq C++ optimiser bug. @@ -195,6 +198,38 @@ return target; } +void* +omniObjRef::_uncheckedNarrow(const char* repoId) +{ + ASSERT_OMNI_TRACEDMUTEX_HELD(*omni::internalLock, 0); + OMNIORB_ASSERT(repoId && *repoId); + + // Attempt to narrow the reference using static type info. + void* target = _ptrToObjRef(repoId); + + if( target ) { + omni::duplicateObjRef(this); + } + else { + omniObjRef* objref; + + omni::internalLock->lock(); + + if( _localId() ) + objref = omni::createObjRef(pd_mostDerivedRepoId, repoId, _localId()); + else + objref = omni::createObjRef(pd_mostDerivedRepoId, repoId, + pd_iopprofiles, 0, 1); + + omni::internalLock->unlock(); + + if( objref ) { + target = objref->_ptrToObjRef(repoId); + OMNIORB_ASSERT(target); + } + } + return target; +} void omniObjRef::_assertExistsAndTypeVerified() Index: src/lib/omniORB2/orbcore/poa.cc =================================================================== RCS file: /cvsroot/omni/src/lib/omniORB2/orbcore/poa.cc,v retrieving revision 1.1.2.24 retrieving revision 1.1.2.26 diff -u -u -r1.1.2.24 -r1.1.2.26 --- src/lib/omniORB2/orbcore/poa.cc 2000/12/05 12:10:30 1.1.2.24 +++ src/lib/omniORB2/orbcore/poa.cc 2001/08/03 10:32:02 1.1.2.26 @@ -29,6 +29,12 @@ /* $Log: poa.cc,v $ + Revision 1.1.2.26 2001/08/03 10:32:02 dpg1 + Refcount not incremented in find_POA with AdapterActivator. + + Revision 1.1.2.25 2001/07/24 14:58:54 dpg1 + Fix race conditions with servant activators. + Revision 1.1.2.24 2000/12/05 12:10:30 dpg1 Fix bug with ServantLocator postinvoke() when operation name is >32 characters. @@ -374,11 +380,6 @@ static omni_tracedmutex poa_lock; -static omni_tracedmutex servant_activator_lock; -// Used to serealise invocations on ServantActivator's. It -// comes before all other locks in the partial order -- since -// it is held whilst making an upcall into application code. - static omni_tracedcondition adapteractivator_signal(&poa_lock); // Used to signal between threads when using an AdapterActivator // to create a child POA. @@ -478,9 +479,13 @@ poa = attempt_to_activate_adapter(adapter_name); - if( !poa ) throw AdapterNonExistent(); + if( poa && !poa->pd_dying ) { + poa->incrRefCount(); + return poa; + } - return poa; + throw AdapterNonExistent(); + return 0; // For dumb compilers } @@ -758,11 +763,12 @@ int idsize; create_new_key(key, &oid, &idsize); - ret->length(idsize); - memcpy(ret->NP_data(), oid, idsize); - - id = omni::activateObject(p_servant, this, key); + if (!operationPending(key.key(), key.size())) { + ret->length(idsize); + memcpy(ret->NP_data(), oid, idsize); + id = omni::activateObject(p_servant, this, key); + } } while( !id ); p_servant->_add_ref(); @@ -782,8 +788,21 @@ !pd_policy.user_assigned_id && oid.length() != SYS_ASSIGNED_ID_SIZE ) OMNIORB_THROW(BAD_PARAM,0, CORBA::COMPLETED_NO); + omniObjKey key; + create_key(key, oid.NP_data(), oid.length()); + omni_tracedmutex_lock sync(pd_lock); CHECK_NOT_DYING(); + + { + PendingOperation* po; + while ((po = operationPending(key.key(), key.size()))) { + omniORB::logs(15, "activate_object_with_id() races with another " + "thread doing activate / deactivate. Waiting\n"); + po->wait(); + } + } + omniLocalIdentity* id = 0; { omni_tracedmutex_lock sync2(*omni::internalLock); @@ -799,12 +818,9 @@ if( id ) throw ServantAlreadyActive(); } - omniObjKey key; - create_key(key, oid.NP_data(), oid.length()); id = omni::activateObject(p_servant, this, key); if( !id ) throw ObjectAlreadyActive(); } - p_servant->_add_ref(); id->insertIntoOAObjList(&pd_activeObjList); } @@ -813,28 +829,41 @@ void omniOrbPOA::deactivate_object(const PortableServer::ObjectId& oid) { - // Arghh! Things are supposed to happen in this order: - // o stop new requests being admitted + // Things happen in this order: // o wait for requests to complete + // -- note that new requests can arrive in the mean time, so we + // may never actually complete! This is necessary to prevent + // deadlocks in objects which do re-entrant calls to + // themselves. // o remove from active object map // o etherealise - // Should not be possible to reactivate same object until - // the etherealisation stage has happened. This is probably - // tricky -- we may be forced to put a placeholder into the - // active object map. Ignore for now ... + // + // It is not possible to reactivate the same object until the + // etherealisation stage has happened. Attempts to do so are blocked + // until it is safe to continue. CHECK_NOT_NIL(); if( !pd_policy.retain_servants ) throw WrongPolicy(); omniObjKey key; create_key(key, oid.NP_data(), oid.length()); + CORBA::ULong hash = omni::hash(key.key(), key.size()); pd_lock.lock(); CHECK_NOT_DESTROYED(); + + if (operationPending(key.key(), key.size(), hash)) { + pd_lock.unlock(); + omniORB::logs(10, "deactivate_object() races with another thread doing " + "activate / deactivate. ObjectNotActive is thrown."); + + throw ObjectNotActive(); + } + omni::internalLock->lock(); - omniLocalIdentity* id = omni::deactivateObject(key.key(), key.size()); - if( !id ) { + omniLocalIdentity* id = omni::locateIdentity(key.key(), key.size(), hash); + if( !id || !id->servant() ) { omni::internalLock->unlock(); pd_lock.unlock(); throw ObjectNotActive(); @@ -844,29 +873,53 @@ id->removeFromOAObjList(); if( id->is_idle() ) { + // TODO: this should use lastInvocationHasCompleted() + // If the last method invocation has already completed on // this object, and it doesn't need etherealising, we // can just get rid of it now. + + omniLocalIdentity* did = omni::deactivateObject(key.key(), key.size()); + OMNIORB_ASSERT(did == id); + omni::internalLock->unlock(); PortableServer::ServantActivator_ptr sa = pd_servantActivator; - pd_lock.unlock(); - omniORB::logs(15, "Object is idle -- etherealise now."); + if (sa) { + PendingOperation* pending = + new PendingOperation(this, id->key(), id->keysize(), hash); + pd_lock.unlock(); - PortableServer::Servant servant = DOWNCAST(id->servant()); + omniORB::logs(15, "Object is idle -- etherealise now."); - if( sa ) + PortableServer::Servant servant = DOWNCAST(id->servant()); + add_object_to_etherealisation_queue(servant, sa, id->key(), - id->keysize(), 0); - else + id->keysize(), 0, 0, pending); + id->die(); + } + else { + PendingOperation pending(this, id->key(), id->keysize(), hash); + pd_lock.unlock(); + + omniORB::logs(15, "Object is idle -- _remove_ref now."); + + PortableServer::Servant servant = DOWNCAST(id->servant()); + servant->_remove_ref(); - id->die(); + id->die(); + } } else { // When outstanding requests have completed the object // will be etherealised. omni::internalLock->unlock(); detached_object(); + + // Create a PendingOperation on the heap. The object will remove + // it when all ourstanding requests have completed. + new PendingOperation(this, id->key(), id->keysize(), hash); + pd_lock.unlock(); omniORB::logs(15, "Object is still busy -- etherealise later."); @@ -888,7 +941,11 @@ pd_lock.lock(); omni::internalLock->lock(); - // We need to be sure we use a new id ... + // We need to be sure we use a new id. We _don't_ bother to see if + // there is an operation pending for the new key, since that race + // condition is indistinguishable from the case that this + // create_reference() call happened before whatever operation is + // pending. do { create_new_key(key); @@ -988,11 +1045,12 @@ int idsize; create_new_key(key, &oid, &idsize); - ret->length(idsize); - memcpy(ret->NP_data(), oid, idsize); - - id = omni::activateObject(p_servant, this, key); + if (!operationPending(key.key(), key.size())) { + ret->length(idsize); + memcpy(ret->NP_data(), oid, idsize); + id = omni::activateObject(p_servant, this, key); + } } while( !id ); p_servant->_add_ref(); @@ -1057,8 +1115,9 @@ int idsize; create_new_key(key, &oid, &idsize); - id = omni::activateObject(p_servant, this, key); - + if (!operationPending(key.key(), key.size())) { + id = omni::activateObject(p_servant, this, key); + } } while( !id ); p_servant->_add_ref(); @@ -1412,7 +1471,13 @@ void omniOrbPOA::lastInvocationHasCompleted(omniLocalIdentity* id) { - ASSERT_OMNI_TRACEDMUTEX_HELD(*omni::internalLock, 0); + ASSERT_OMNI_TRACEDMUTEX_HELD(*omni::internalLock, 1); + + // Make sure the object is gone from the object table + omniLocalIdentity* did = omni::deactivateObject(id->key(), + id->keysize()); + OMNIORB_ASSERT(did == id || did == 0); + omni::internalLock->unlock(); if( omniORB::trace(15) ) { omniORB::logger l; @@ -1445,6 +1510,8 @@ } } + PendingOperation* pending = operationPending(id->key(), id->keysize()); + pd_lock.unlock(); PortableServer::Servant servant = DOWNCAST(id->servant()); @@ -1452,13 +1519,15 @@ if( sa ) { // Delegate etherealisation to a separate thread. add_object_to_etherealisation_queue(servant, sa, id->key(), - id->keysize(), 0, 1); + id->keysize(), 0, 1, pending); } else { servant->_remove_ref(); + if (pending) { + delete pending; + } met_detached_object(); } - id->die(); } @@ -1486,7 +1555,8 @@ pd_call_lock(0), pd_deathSignal(&pd_lock), pd_oidIndex(0), - pd_activeObjList(0) + pd_activeObjList(0), + pd_pendingOperations(0) { OMNIORB_ASSERT(name); OMNIORB_ASSERT(manager); @@ -1561,7 +1631,8 @@ pd_poaIdSize(0), pd_deathSignal(&pd_lock), pd_oidIndex(0), - pd_activeObjList(0) + pd_activeObjList(0), + pd_pendingOperations(0) { } @@ -1791,9 +1862,10 @@ const CORBA::Octet* oid; int idsize; create_new_key(key, &oid, &idsize); - - id = omni::activateObject(p_servant, this, key); + if (!operationPending(key.key(), key.size())) { + id = omni::activateObject(p_servant, this, key); + } } while( !id ); p_servant->_add_ref(); @@ -1888,25 +1960,6 @@ } -void -omniOrbPOA::shutdown() -{ - poa_lock.lock(); - omniOrbPOA* rp = theRootPOA; - if( rp ) rp->incrRefCount(); - poa_lock.unlock(); - - try { - if( rp ) rp->destroy(1, 1); - } - catch(CORBA::OBJECT_NOT_EXIST&) { - // That's okay -- someone else got there first. - } - - if( rp ) CORBA::release(rp); -} - - omniOrbPOA* omniOrbPOA::getAdapter(const _CORBA_Octet* key, int keysize) { @@ -2286,28 +2339,316 @@ } -static omniTaskQueue* etherealisation_queue = 0; +////////////////////////////////////////////////////////////////////// +////////////////////// Servant Activator queue /////////////////////// +////////////////////////////////////////////////////////////////////// + +// Calls to incarnate() and etherealize() must be serialised. The easy +// way to do this would be to maintain a