Discussion:
[omniORB] thread policy per interface function
black hole
2007-08-17 18:12:53 UTC
Permalink
Hi,

I am trying to solve this situation. I have an IDL interface.
I want part of its functions to be executed single-threaded
or multi-threaded (ORB_CTRL_MODEL). But I always want
the other part to be executed multi-threaded. Now, this is not
an issue with omniORB, since it spawns new thread for a new
request if the previous request is not handled yet. But, I don't
know how to solve it in general (not to depend on a particular
CORBA implementation).

Note1: It is a design decision not to have the interface split
into two. The interface has to be available as a single IOR
and not two.

Note2: As another part of the design, I can not start a new
thread inside an interface function. The interface function
has to be already executing in a new thread.

Tomas Klacko
Thomas Lockhart
2007-08-17 20:51:42 UTC
Permalink
Post by black hole
I want part of its functions to be executed single-threaded
or multi-threaded (ORB_CTRL_MODEL). But I always want
the other part to be executed multi-threaded.
Given your constraints, I would think that protecting some execution
paths with a mutex held within your server code would give you the
single-threaded behavior you need. Leave the mutex out for those methods
which can be executed in parallel.

The downside is that you will be tying up ORB threads while they wait
for the mutex to become free.

hth

- Tom
black hole
2007-08-17 21:20:06 UTC
Permalink
Hi,
Post by Thomas Lockhart
Post by black hole
I want part of its functions to be executed single-threaded
or multi-threaded (ORB_CTRL_MODEL). But I always want
the other part to be executed multi-threaded.
Given your constraints, I would think that protecting some execution
paths with a mutex held within your server code would give you the
single-threaded behavior you need. Leave the mutex out for those methods
which can be executed in parallel.
The downside is that you will be tying up ORB threads while they wait
for the mutex to become free.
Yes, it is a downside. And there is more to it. Imagine a CORBA
implementation that is not multi-threaded in ORB_CTRL_MODEL[*].
Then I would have to create new threads for the several functions I need.
And this thread-creation would depend on the underlying CORBA
implementation in use.

I understand CORBA specification that there is way to force
a single-threaded POA, but not a multi-threaded one.

Tomas Klacko
Thomas Lockhart
2007-08-17 21:38:40 UTC
Permalink
Post by black hole
Yes, it is a downside. And there is more to it. Imagine a CORBA
implementation that is not multi-threaded in ORB_CTRL_MODEL[*].
Then I would have to create new threads for the several functions I need.
That was prohibited by your "Note2" constraint. And wouldn't this still
restrict you to serial servicing of requests? You might be able to use
multiple threads to service a single request, but the ORB will not let
another request through until that is finished.
Post by black hole
I understand CORBA specification that there is way to force
a single-threaded POA, but not a multi-threaded one.
Forced or not, you know you can get either single- or multi-threaded POAs.

afaicr a POA will handle the entire interface, so having two POAs with
two servicing models doesn't help. Unless you do something clever with
having some methods in the multi-threaded POA sending back a forwarding
request to the client which will redirect the request to the
single-threaded POA (or vica versa single- to multi-). I haven't done
that myself so, even if you would accept the overhead of a forwarded
transaction, having only some methods get forwarded might not be easily
supported.

hth

- Tom
black hole
2007-08-17 22:32:04 UTC
Permalink
Post by Thomas Lockhart
Post by black hole
Yes, it is a downside. And there is more to it. Imagine a CORBA
implementation that is not multi-threaded in ORB_CTRL_MODEL[*].
Then I would have to create new threads for the several functions I need.
That was prohibited by your "Note2" constraint. And wouldn't this still
restrict you to serial servicing of requests? You might be able to use
multiple threads to service a single request, but the ORB will not let
another request through until that is finished.
Well, not prohibited (next time, I'll use the word 'constraint'
instead of 'note').
I'll explain.

First, the (simplified) idl:
module M
{
typedef sequence<octet> ByteString;
typedef sequence<ByteString> ByteStringSeq;

interface I
{
// Download component to repository.
// Can be multi-threaded or single-threaded.
void download_component(in ByteString component);

// Instantiate component, return instance Id.
// Must be always multi-threaded.
ByteString instantiate_component(in ByteString component,
in ByteStringSeq arguments);
};
};

On the server side, I now have one servant
that implements the interface M::I.
The server runs a simplified cycle:
for(;;){
while(orb->work_pending())
orb->perform_work();
// do some other work;
// sleep;
}

The client issues a request, calls download_component().
Regarding this function, I do not care about thread policy.
That means requests to this function can be processed
sequentially or parallel.

The client issues another request, calls instantiate_component().
The catch with this one is that a component, that is being instantiated,
can instantiate other components. This can lead to another
instantiate_component() request on the same servant. If requests
for this function are handled sequentially, than this results in a deadlock.

If the CORBA implementation is multi-threaded in ORB_CTRL_MODEL,
such as omniORB, then there is no issue.

Regarding the instantiate_component() function. This function looks like this:
M::ByteString* instantiate_component(const M::ByteString& component,
const M::ByteStringSeq& arguments)
{
// instantiate a component in an OS-specific way.
return __instantiate_component(component, arguments);
}

It makes no sense to spawn a thread inside instantiate_component()
and have it call __instantiate_component() since the return value is needed.
The return value identifies a newly created component instance,
and it is what client should receive after the instance is created.

But it is perferctly OK, if something else (ORB for example) does this:
1) read a request from a socket descriptor
2) is it a request for instantiate_component()?
if yes, then create a new thread and let it execute this function
if not, then proceed as with ORB_CTRL_MODEL.

I did not find a way to hide the above two steps into these two calls:
if(orb->work_pending()) orb->perform_work();

I took a look at interceptors, default servants and related stuff,
but yet without any clue.
Post by Thomas Lockhart
Post by black hole
I understand CORBA specification that there is way to force
a single-threaded POA, but not a multi-threaded one.
Forced or not, you know you can get either single- or multi-threaded POAs.
Actually, I don't know :)


Tomas Klacko
Duncan Grisby
2007-08-17 23:30:51 UTC
Permalink
Post by Thomas Lockhart
Post by black hole
I want part of its functions to be executed single-threaded
or multi-threaded (ORB_CTRL_MODEL). But I always want
the other part to be executed multi-threaded.
Given your constraints, I would think that protecting some execution
paths with a mutex held within your server code would give you the
single-threaded behavior you need. Leave the mutex out for those
methods which can be executed in parallel.
The downside is that you will be tying up ORB threads while they wait
for the mutex to become free.
That doesn't make any difference. omniORB implements the single thread
model with a recursive mutex, so using a mutex in application code is no
different.

Cheers,

Duncan.
--
-- Duncan Grisby --
-- ***@grisby.org --
-- http://www.grisby.org --
Thomas Lockhart
2007-08-17 23:57:44 UTC
Permalink
Post by Duncan Grisby
Post by Thomas Lockhart
The downside is that you will be tying up ORB threads while they wait
for the mutex to become free.
That doesn't make any difference. omniORB implements the single thread
model with a recursive mutex, so using a mutex in application code is no
different.
I was assuming a multi-threaded model with individual methods forcing
single-thread behavior by holding application-level mutexes. Is there a
fatal flaw in that configuration?

- Tom
black hole
2007-08-18 00:15:07 UTC
Permalink
Post by Thomas Lockhart
Post by Duncan Grisby
Post by Thomas Lockhart
The downside is that you will be tying up ORB threads while they wait
for the mutex to become free.
That doesn't make any difference. omniORB implements the single thread
model with a recursive mutex, so using a mutex in application code is no
different.
I was assuming a multi-threaded model with individual methods forcing
single-thread behavior by holding application-level mutexes. Is there a
fatal flaw in that configuration?
There is nothing wrong with this configuration. But it is not
what I am looking for. ORB_CTRL_MODEL is not necessarily
a multi-threaded model (it is a choice of every CORBA implementation).
There is SINGLE_THREAD_MODEL POA policy, to specify that I want
single-threaded POA. But there doesn't seem to be any such policy as
"MULTI_THREAD_MODEL" policy, to specify that I want multi-threaded POA.

Tomas Klacko
Thomas Lockhart
2007-08-18 00:35:10 UTC
Permalink
Post by black hole
There is nothing wrong with this configuration. But it is not
what I am looking for. ORB_CTRL_MODEL is not necessarily
a multi-threaded model (it is a choice of every CORBA implementation).
There is SINGLE_THREAD_MODEL POA policy, to specify that I want
single-threaded POA. But there doesn't seem to be any such policy as
"MULTI_THREAD_MODEL" policy, to specify that I want multi-threaded POA.
Well, that is what I was alluding to earlier. You get a multi-threaded
POA (at least with the ORBs I've used) if you use the default policies.
So no worries, right?

- Tom
black hole
2007-08-18 02:42:09 UTC
Permalink
Post by Thomas Lockhart
Post by black hole
There is nothing wrong with this configuration. But it is not
what I am looking for. ORB_CTRL_MODEL is not necessarily
a multi-threaded model (it is a choice of every CORBA implementation).
There is SINGLE_THREAD_MODEL POA policy, to specify that I want
single-threaded POA. But there doesn't seem to be any such policy as
"MULTI_THREAD_MODEL" policy, to specify that I want multi-threaded POA.
Well, that is what I was alluding to earlier. You get a multi-threaded
POA (at least with the ORBs I've used) if you use the default policies.
So no worries, right?
Right :)

Tomas Klacko

Duncan Grisby
2007-08-18 00:05:29 UTC
Permalink
Post by Thomas Lockhart
Post by Duncan Grisby
Post by Thomas Lockhart
The downside is that you will be tying up ORB threads while they wait
for the mutex to become free.
That doesn't make any difference. omniORB implements the single thread
model with a recursive mutex, so using a mutex in application code is no
different.
I was assuming a multi-threaded model with individual methods forcing
single-thread behavior by holding application-level mutexes. Is there
a fatal flaw in that configuration?
Not at all. I think that's the right thing to do. My point was that
omniORB's single thread model does exactly the same thing, so ORB
threads are tied up waiting for the lock regardless of whether it's the
mutex in the ORB or a mutex in the application.

There's nothing particularly special about a single thread policy POA --
it just has a lock around method calls.

Cheers,

Duncan.
--
-- Duncan Grisby --
-- ***@grisby.org --
-- http://www.grisby.org --
Loading...