ORBit-mt: a multi-threaded ORB built on top of ORBit

ORBit-mt is dead. Long live ORBit2!

Use ORBit2. It is much more mature and does everything, you would possibly (and impossibly) want.

So this page will only stay around for historical reasons.

Table of Contents

Why would you want this

  • it is a good solution for servers, which need themself to call other servers (be they CORBA servers or e.g. databases) and still want to be reactive during that call.
  • also it helps for multithreaded programs, where you just want to call CORBA methods from different threads.
  • its fully buzzword compliant.
  • simply everybody wants to have it.

Download

Download the latest version ORBit-mt-0.5.15.tar.gz (447 KiB). See below for older versions and the differences between them.

News

2003-07-02:

  • I think, it's time now to begin phasing out ORBit-mt. ORBit2 is thanks to the work of Michael Meeks and Mark McLoughlin now in such an advanced state with regard to multi-threading that all further work will go there. You are urged to check out ORBit2, whether it already can meet your requirements better than ORBit-mt. I still won't have time in the near future to work on ORBit2 or ORBit-mt though.

2002-06-28:  ORBit-mt-0.5.15.tar.gz (447 KiB)

  • Incorporated all applying changes from upstream ORBit-0.5.15.
  • Now works with newer glibc versions, which don't like getaddrinfo for unix domain sockets too much. Thanks for most of the patch goes to Mike Kohne.
  • Fixed some other small bugs. Again kudos to Mike Kohne.
  • Updated and extended the multithread test programs.

2002-01-30:

  • New design.
  • Now hosted at Sourceforge.
  • I hope to roll out a port of ORBit-mt to ORBit2 soon.

2001-02-20:

  • There is a bug in src/orb/orbit.h.in. Please add extern to the line 195, such that it reads
    extern CORBA_Principal ORBit_default_principal;
    
    and rerun ./configure after that.

2001-02-05:  ORBit-mt-0.5.7.tar.gz (376 KiB)

  • Now compiles on Solaris 2.6 and later. Make sure, however, that you configured glib --with-threads=posix. DynAny is working again. I introduced a stupid bug, that should be fixed now.

2001-01-03:  ORBit-mt-0.5.5.tar.gz (331 KiB)

  • Now the header files can be included from C++-programs as well. Another bug for very large transmissions has been fixed. Thanks to Sam Counter now ORBit-mt.m4 is included for your autoconf pleasure.

2000-09-21:  ORBit-mt-0.5.3a.tar.gz (324 KiB)

  • Now also working for very large sequences on Linux, which seemed to be too long for the writev of linux.

2000-09-07:  ORBit-mt-0.5.3.tar.gz (327 KiB)

  • A bug for the PortableServer_THREAD_PER_REQUEST policy, that would result in an serialized execution of all request has been fixed.
  • Another news it, that ORBit-mt now can live peacefully beside standard ORBit. They no longer try to install the same headers, libs and binaries. You have to use orbit-idl-mt and orbit-config-mt instead of orbit-idl and orbit-config resp. in order to compile ORBit-mt programs now.
  • To make this seperation possible, I had to remove popt and libIDL from the tarball. The easiest way to get libIDL is to simply install the last ORBit.
  • Also the bug in the compilation process, resulting in errors about unknown references to allow_severity and deny_severity has been solved. It took me sometime to find the bug and to fix it I had to remove the TCP wrappers support. Not that this feature would work in upstream ORBit.

2000-04-20:  ORBit-mt-0.5.1.tar.gz (1100 KiB)

  • Distributed as a tarball this time.
  • This version has a completly rewritten libIIOP, which will hopefully be part of upstream ORBit soon. Furthermore I've written GAsyncQueue and GThreadPool, both of which will be part of the upcoming GLib-1.4 release. The thread support was also improved along the lines of GLib. Some memory leaks were fixed and the thing run quite stable again.

1999-10-08:

  • new version 0.5.0: This time distributed as a patch.

1999-07-23:  ORBit-mt-0.4.92.tar.gz (1069 KiB)

  • CVS version no longer up to date.

1999-06-01:

  • now you can download a tarball of ORBit-mt.

1999-01-19:

  • new version, that doesn't require the gthread library.
  • implemented several different threading strategies and now the whole thing is actually working.
  • now again only working with the gthread library. That provides us with very fast spinlocks and a good and fast thread abstraction.
  • now working without gthread with vanilla posix threads.

Installation

You must have libIDL and popt installed on your machine in order to compile ORBit-mt. Both should be available, if you simply install ORBit-0.5.15 or newer (not ORBit2 however).

        gunzip ORBit-mt-0.5.15.tar.gz
	tar -xvf ORBit-mt-0.5.15.tar
	cd ORBit-mt-0.5.15
	./configure
	make
	make install

Usage

To compile a program, that will use a multithreaded ORB, you can simply provide the --multithread flag to orbit-config-mt, when fetching the link flags i.e.:

	gcc -o mt-server mt-server.o `orbit-config-mt --multithread --libs server`

For an example, how to use it, look at the ORBit/test/multithread/server.c file. The initialization of the policy list is far from nice, but I do not know, how to do it better yet.

In a nutshell it works like this, first you have to init the ORB as a multithread aware ORB. That happens through:

 	orb = CORBA_ORB_init(&argc, argv, "orbit-local-mt-orb", &ev);

This can also be done at startup via a command line parameter, i.e.:

	server -ORBid=orbit-local-mt-orb

You will however then get an error, if you have not linked your program against the necessary libraries (see above). So there is no need for two versions of ORBit-mt libs. It is done magically in the backgorund. That does however only work on systems with weak external symbols. On other systems there is no MT support for ORBit-mt (but ORBit-mt should work singlethreaded).

If you want to use a gtk program (or gnome, for that matter) with ORBit-mt, then you have to be aware, that ORBit-mt uses the glib main loop, which ORBit does not (yet) do. So take a look at gnome-libs/libgnorba/orbitgtk.c, how this is can be done with the macro ORBIT_USES_GLIB_MAIN_LOOP, that is defined for ORBit-mt, but not (yet) for ORBit. In short, you don't need to (aka must not :) set the IIOPAddConnectionHandler and IIOPRemoveConnectionHandler function pointers for ORBit-mt.

You have to get yourself a POA with the requested properties, this goes like that:

  PortableServer_POA poa;
  PortableServer_POA root_poa = ...;
  /* you have to have a parant poa, doesn't need to be the root poa */;

  CORBA_PolicyList policies;
  char *poa_name="new poa"; /* the name of the new poa */

  /* thread_policy should be one of:        
	
     - PortableServer_THREAD_PER_OBJECT: 
           all requests to the same  object will be serialized. It is not
           garanteed though, that there is a 1-to-1 relation between object 
           and thread. 
           This is the default: (i.e. it equals PortableServer_ORB_CTRL_MODEL)
     - PortableServer_SINGLE_THREAD_MODEL:
           all requests will be serialized. you can however use the orb 
           from multiple threads.
     - PortableServer_THREAD_PER_REQUEST:
           every incoming request will be dispatched to a new thread.
     - PortableServer_THREAD_PER_POA:
           all requests to the same POA will be serialized.
     - PortableServer_THREAD_PER_CONNECTION
           all requests from the same connection will be serialized. */

  PortableServer_ThreadPolicyValue thread_policy = 
	PortableServer_THREAD_PER_REQUEST;

  policies._length = 1;
  policies._buffer = g_new0 (CORBA_Policy, 1);
  policies._buffer[0] = (CORBA_Policy)
    PortableServer_POA_create_thread_policy (root_poa, thread_policy, &ev);
  
  poa = PortableServer_POA_create_POA (root_poa, poa_name, NULL, 
				       &policies, &ev);

  /* FIXME: some problems here: an endless stack killing recursion
  CORBA_Object_release (policies._buffer[0], &ev);
  g_free (policies._buffer); */
  
  PortableServer_POAManager_activate (PortableServer_POA__get_the_POAManager (poa, &ev), &ev);

Implementation

The glib main loop is only running in one thread, the input thread. If a request is received, the corresponding POA is determined and the POA decides which threading strategy should be used. Then the request is queued to the thread, it is scheduled for. The request is processed there. The input thread returns immediately to the glib main loop. If a reply or a locate reply is received, then the input thread looks up, which thread sent the corresponding request and queues the reply to that thread.

FAQ

How can I use the name service from ORBit-mt?

You can use the normal ORBit name service, as the name service will hardly profit from being multithreaded. To link to the stubs, you can't use orbit-config-mt --use-service=name ..., because I deleted all services and the like from the distribution. What you should do is:

  orbit-idl-mt --noskels `orbit-config --prefix`/include/ORBitservices/CosNaming.idl

Then you can simply compile and link the resulting files CosNaming-common.c and CosNaming-stubs.c into your binary and you should be able to use the name service. Be sure to include the local CosNaming.h and not ORBitservices/CosNaming.h.

Why did you choose to take the route of having a "main thread" as opposed to having all threads share the work equally?

Take two threads and one object, that both are using. Now both threads issue a request to that object, so both would have to go to select on that connection. I would have the same need for signaling as in the 'main-thread does scheduling' solution. So I chose it right away. So the main thread is almost all the time in the select. This insures, that at every time the server is ready to take requests. (We will on the other hand have to make a decision on a maximum number of threads, otherwise the server might be exposed to a overload lock)

TODO

  • Port it to ORBit2, which is much cleaner, more modular and all in all easier to build upon.
  • not all global data structures are checked to be reentrant. But it runs amazingly stable here on my computer.
  • clean up properly (removing all threads) after CORBA_ORB_shutdown call.
  • we might want to have mutexes on a all writev-calls. I don't know, if they are garanteed to be atomic, especially when flow control makes them wait.
  • make same address space calls respect the thread policy, i.e. if a same address space call is encountered now, it will be executed, but actually there had to be a check first, if the POA-policy forbids running this request (because it isn't serialized properly).