Thread-local contexts

View: New views
14 Messages — Rating Filter:   Alert me  

Thread-local contexts

by Chris Robinson-5 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

An idea I've been juggling around in my head. Unlike OpenGL, OpenAL only has
one current context per process. While this can help for things like sharing
sources between threads, it creates big problems when two subsystems may want
to independently use OpenAL.

For example, if something like DirectShow or GStreamer wants to use OpenAL to
stream out music/audio, separately from the app which uses OpenAL for game
sounds, it creates a problem where the background music player needs to set
its own context for its device, while the main game needs to set *its* context
for its device. There's no way for a background player to sanely work without
exposing specific controls and requiring specific interaction with the main
app, and this still wouldn't work for existing apps that may not expect their
background player to suddenly start using OpenAL.

If the background player could set a thread-specific context, it would prevent
unexpected side effects in the rest of the app. The app setting its own
(global) context wouldn't affect the current context for the background
player, and vice versa.


My idea would be to leave alcMakeContextCurrent set a process-wide context,
while a new function (alcMakeCurrent, alcMakeThreadCurrent, ..?) would set a
thread-local context. With a thread-local context set, the thread will ignore
the process-wode context. If a thread-local context is set to NULL, then the
process-wide context will be used for the thread. So basically, in psuedo-
code:

ALCboolean alcMakeThreadCurrent(ALCcontext *ctx)
{
    if(!ctx || IsContext(ctx))
    {
        tls_current_context = ctx;
        return ALC_TRUE;
    }
    ...
}

ALCcontext *alcGetCurrentContext()
{
    ALCcontext *ctx = tls_current_context;
    if(ctx == NULL)
        ctx = global_current_context;
    return ctx;
}

This allows alcMakeContextCurrent to behave the same for existing code, while
new code can affect just the thread's current context, within the same app.
_______________________________________________
Openal-devel mailing list
Openal-devel@...
http://opensource.creative.com/mailman/listinfo/openal-devel

Re: Thread-local contexts

by Jason Daly :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Chris Robinson wrote:
> This allows alcMakeContextCurrent to behave the same for existing code, while
> new code can affect just the thread's current context, within the same app.
>  

Makes a lot of sense to me.  Will this bring up any new concurrency issues?

--"J"

_______________________________________________
Openal-devel mailing list
Openal-devel@...
http://opensource.creative.com/mailman/listinfo/openal-devel

Re: Thread-local contexts

by Chris Robinson-5 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Wednesday 09 September 2009 8:26:02 am Jason Daly wrote:
> Chris Robinson wrote:
> > This allows alcMakeContextCurrent to behave the same for existing code,
> > while new code can affect just the thread's current context, within the
> > same app.
>
> Makes a lot of sense to me.  Will this bring up any new concurrency issues?

It shouldn't. OpenAL is still thread safe, so two threads calling AL functions
shouldn't trip over each other regardless if they're using the same context or
not.

My only question is if two threads can have the same context set locally.
OpenGL doesn't allow the same context to be set current on multiple threads at
once, but OpenAL is already designed to work with one context between threads,
so I'm not sure if the restriction is necessary.
_______________________________________________
Openal-devel mailing list
Openal-devel@...
http://opensource.creative.com/mailman/listinfo/openal-devel

Re: Thread-local contexts

by Chris Robinson-5 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

My current thinking is to have two new functions.

alcMakeThreadCurrent - Sets a thread-specific context, which overrides the
    process-wide context when set to a non-NULL value. If non-NULL,
    alcGetCurrentContext will return this context when called from the
    corresponding thread, otherwise it will return the process-wide context.

alcGetThreadContext - Returns the current thread-specific context, or NULL if
    one is not set. Unlike alcGetCurrentContext, this will not return the
    process-wide context if no thread-specific context is set.

The second function is needed in case some code wants to set, then later
restore, the proper context for a thread. Since alcGetCurrentContext will give
the context that currently affects the given thread, it won't say whether this
context is process-wide or thread-local. Eg, doing:

oldctx = alcGetCurrentContext();
alcMakeThreadCurrent(myctx);
...
alcMakeThreadCurrent(oldctx);

could make a process-wide context current for the thread (and subsequently
won't change if alcMakeContextCurrent is later called), while doing:

alcMakeThreadCurrent(myctx);
...
alcMakeThreadCurrent(NULL);

could undo a thread-specific context the app may have set. So to fix this, you
would do:

oldctx = alcGetThreadContext();
alcMakeThreadCurrent(myctx);
...
alcMakeThreadCurrent(oldctx);

which would properly restore the thread-specific context the app expects.
_______________________________________________
Openal-devel mailing list
Openal-devel@...
http://opensource.creative.com/mailman/listinfo/openal-devel

Re: Thread-local contexts

by Jason Daly :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Chris Robinson wrote:

> My current thinking is to have two new functions.
>
> alcMakeThreadCurrent - Sets a thread-specific context, which overrides the
>     process-wide context when set to a non-NULL value. If non-NULL,
>     alcGetCurrentContext will return this context when called from the
>     corresponding thread, otherwise it will return the process-wide context.
>
> alcGetThreadContext - Returns the current thread-specific context, or NULL if
>     one is not set. Unlike alcGetCurrentContext, this will not return the
>     process-wide context if no thread-specific context is set.
>  

Seems reasonable so far.  One question...

If you call (in the same thread):

ctx1 = alcCreateContext(...)
ctx2 = alcCreateContext(...)
ctx3 = alcCreateContext(...)

...

alcMakeCurrent(ctx1)
...
alcMakeThreadCurrent(ctx2)
...
alcMakeCurrent(ctx3)


Which context is current now?

--"J"


_______________________________________________
Openal-devel mailing list
Openal-devel@...
http://opensource.creative.com/mailman/listinfo/openal-devel

Re: Thread-local contexts

by Chris Robinson-5 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Wednesday 09 September 2009 4:06:25 pm Jason Daly wrote:

> Seems reasonable so far.  One question...
>
> If you call (in the same thread):
>
> ctx1 = alcCreateContext(...)
> ctx2 = alcCreateContext(...)
> ctx3 = alcCreateContext(...)
>
> ...
>
> alcMakeCurrent(ctx1)
> ...
> alcMakeThreadCurrent(ctx2)
> ...
> alcMakeCurrent(ctx3)
>
>
> Which context is current now?

ctx2 would be current for that thread (assuming you mean alcMakeContextCurrent
for alcMakeCurrent). Both alcGetCurrentContext and alcGetThreadContext would
return it.

For other threads that didn't have a thread-local context set, ctx3 would be
current. alcGetCurrentContext would return ctx3, and alcGetThreadContext would
return NULL.
_______________________________________________
Openal-devel mailing list
Openal-devel@...
http://opensource.creative.com/mailman/listinfo/openal-devel

Re: Thread-local contexts

by Jason Daly :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Chris Robinson wrote:

ctx2 would be current for that thread (assuming you mean alcMakeContextCurrent 
for alcMakeCurrent). Both alcGetCurrentContext and alcGetThreadContext would 
return it.
  

Yes, alcMakeContextCurrent() is what I meant.  That seems a bit counter-intuitive to me.  Would it be better (after an alcMakeThreadCurrent() call) for an alcMakeContextCurrent() call to set the specified context current for both the global and the thread context?

I guess no, because the whole point of this is to kind of "override" the current context in your own thread while some background thread that probably wasn't written with this extension hums along on its merry way.

It just seems odd that alcMakeContextCurrent() might not make the specified context current in some cases.  I can't think of an alternative at the moment, though.


--"J"

_______________________________________________
Openal-devel mailing list
Openal-devel@...
http://opensource.creative.com/mailman/listinfo/openal-devel

Re: Thread-local contexts

by Chris Robinson-5 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Wednesday 09 September 2009 6:01:55 pm Jason Daly wrote:
> Yes, alcMakeContextCurrent() is what I meant.  That seems a bit
> counter-intuitive to me.  Would it be better (after an
> alcMakeThreadCurrent() call) for an alcMakeContextCurrent() call to set
> the specified context current for both the global and the thread context?
>
> I guess no, because the whole point of this is to kind of "override" the
> current context in your own thread while some background thread that
> probably wasn't written with this extension hums along on its merry way.

Right. Existing code needs to work as it has, and new plugins or background
code that use this new extension need to be able to work with other code that
may or may not be aware of the extension.

alcMakeContextCurrent must not change the thread-local context if the thread-
local context is NULL. If the thread-local context is not NULL, then whether
it's changed or not doesn't matter too much since only the running thread will
affect it. If the app gets into code that wasn't aware of the previous call to
alcMakeThreadCurrent on the same thread, it's in trouble anyway.

It just seems more intuitive to me to make alcMakeContextCurrent not affect
thread-local contexts, as the function wasn't made with thread-local contexts
in mind. Plus it can't change it away from NULL, so changing it away from non-
NULL would be inconsistent, IMO.

> It just seems odd that alcMakeContextCurrent() might not make the
> specified context current in some cases.  I can't think of an
> alternative at the moment, though.

It does make it current, it just won't immediately affect threads that have a
thread-local context set. Something like this:

alcMakeThreadCurrent(ctx2);
...
alcMakeContextCurrent(ctx1);
...
alcMakeThreadCurrent(NULL);

would end up with ctx1 as the current context for the thread.
_______________________________________________
Openal-devel mailing list
Openal-devel@...
http://opensource.creative.com/mailman/listinfo/openal-devel

Re: Thread-local contexts

by Jason Daly :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Chris Robinson wrote:
> It does make it current, it just won't immediately affect threads that have a
> thread-local context set. Something like this:
>  

I'm thinking more from an API/terminology perspective.  What you're
essentially saying is that the specified context is now current, but the
thread-local context that you set earlier is "more current."  To me
"current" seems like an absolute term.  Either the context is current
(and you can manipulate it), or it isn't, so I would disagree
(conceptually) that a call to alcMakeContextCurrent() will make the
context current in all cases.  If there is a current thread-local
context, alcMakeContextCurrent() won't make the given context "current"
because you can't manipulate that context until you set the thread-local
context back to NULL.

If this extension is implemented, someone that is new to OpenAL may
expect that a call to alcMakeContextCurrent() will ensure that they will
be able to manipulate the specified context, and they may be confused
that it doesn't because they had previously set a thread-local context
and never set it back to NULL.  This would be easy to find in a simple
program, but as the programs gets larger (especially a multi-threaded
program, which is what this extension is targeting), it might get more
difficult to track down the problem.  (Keep in mind that I work at a
university research lab, where we routinely have inexperienced
programmers working on relatively complex software systems  :-) )

I still don't have a better idea, though.  The simple answer would be to
change the API terms to make them more intuitive.  Say, change
alcMakeContextCurrent() to alcSetDefaultContext(), which intuitively
suggests that the "default" context can be overridden by other
thread-local contexts.  However, I think everyone would agree that
changing alcMakeContextCurrent() isn't really an option.

--"J"

_______________________________________________
Openal-devel mailing list
Openal-devel@...
http://opensource.creative.com/mailman/listinfo/openal-devel

Re: Thread-local contexts

by Chris Robinson-5 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Thursday 10 September 2009 8:31:04 am Jason Daly wrote:

> If this extension is implemented, someone that is new to OpenAL may
> expect that a call to alcMakeContextCurrent() will ensure that they will
> be able to manipulate the specified context, and they may be confused
> that it doesn't because they had previously set a thread-local context
> and never set it back to NULL.  This would be easy to find in a simple
> program, but as the programs gets larger (especially a multi-threaded
> program, which is what this extension is targeting), it might get more
> difficult to track down the problem.  (Keep in mind that I work at a
> university research lab, where we routinely have inexperienced
> programmers working on relatively complex software systems  :-) )

Could make it so alcMakeContextCurrent resets the thread-local context back to
NULL, so whatever context is set will affect the current thread as well as
other threads that don't have a thread-local context.

Then there's three possible options:
1) alcMakeContextCurrent doesn't change the thread-local context, so the
current thread-local context will continue to be the 'active' context for the
thread if it's non-NULL.
2) alcMakeContextCurrent changes both the thread-local context (if non-NULL)
and global context to the specified value, so the active context will be
whatever is set, for the current thread and any others that don't have a
thread-local context.
3) alcMakeContextCurrent resets the thread-local context to NULL and the
global context to the specified value, so the active context will be whatever
is set.

All three should maintain current behavior for existing apps, but I still find
option 1 as the most intuitive (it affects thread-local contexts of all
threads the same; ie, doesn't touch them). However, option 3 could work, if
you think that's the best way to go. I'd just be cautious with option 2.

> I still don't have a better idea, though.  The simple answer would be to
> change the API terms to make them more intuitive.  Say, change
> alcMakeContextCurrent() to alcSetDefaultContext(), which intuitively
> suggests that the "default" context can be overridden by other
> thread-local contexts.  However, I think everyone would agree that
> changing alcMakeContextCurrent() isn't really an option.

I see alcMakeContextCurrent as setting the global, process-wide context, while
alcMakeThreadCurrent sets the thread-local context. When a thread-local
context is set, it overrides the the process-wide context for that thread. I
could add an alcMakeProcessCurrent that just aliases alcMakeContextCurrent,
but that doesn't seem too useful since the original function will still exist.
_______________________________________________
Openal-devel mailing list
Openal-devel@...
http://opensource.creative.com/mailman/listinfo/openal-devel

Re: Thread-local contexts

by Jason Daly :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Chris Robinson wrote:

> Then there's three possible options:
> 1) alcMakeContextCurrent doesn't change the thread-local context, so the
> current thread-local context will continue to be the 'active' context for the
> thread if it's non-NULL.
> 2) alcMakeContextCurrent changes both the thread-local context (if non-NULL)
> and global context to the specified value, so the active context will be
> whatever is set, for the current thread and any others that don't have a
> thread-local context.
> 3) alcMakeContextCurrent resets the thread-local context to NULL and the
> global context to the specified value, so the active context will be whatever
> is set.
>
> All three should maintain current behavior for existing apps, but I still find
> option 1 as the most intuitive (it affects thread-local contexts of all
> threads the same; ie, doesn't touch them). However, option 3 could work, if
> you think that's the best way to go. I'd just be cautious with option 2.
>  

I agree with you about option 2, I'd probably pick that one last.  3 is
interesting to me (see below)...


> I see alcMakeContextCurrent as setting the global, process-wide context, while
> alcMakeThreadCurrent sets the thread-local context. When a thread-local
> context is set, it overrides the the process-wide context for that thread. I
> could add an alcMakeProcessCurrent that just aliases alcMakeContextCurrent,
> but that doesn't seem too useful since the original function will still exist.
>  

How about alcMakeContextCurrent() following option 3 above, and
alcMakeProcessCurrent() following option 1?  Newer apps would probably
stop using alcMakeContextCurrent() in favor of the two new functions,
while older apps continue to work as before.

--"J"

_______________________________________________
Openal-devel mailing list
Openal-devel@...
http://opensource.creative.com/mailman/listinfo/openal-devel

Re: Thread-local contexts

by Chris Robinson-5 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Thursday 10 September 2009 12:06:51 pm Jason Daly wrote:
> How about alcMakeContextCurrent() following option 3 above, and
> alcMakeProcessCurrent() following option 1?  Newer apps would probably
> stop using alcMakeContextCurrent() in favor of the two new functions,
> while older apps continue to work as before.

Perhaps, but I'm not sure that an app totally aware of (and using) thread-
local contexts should also use process-wide contexts. It would be for
interaction with code possibly unaware of thread-local contexts. If you think
option 3 is the way to go for that, I don't really see a need to also have
option 1's behavior (and vice-versa).
_______________________________________________
Openal-devel mailing list
Openal-devel@...
http://opensource.creative.com/mailman/listinfo/openal-devel

Re: Thread-local contexts

by Jason Daly :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Chris Robinson wrote:
> Perhaps, but I'm not sure that an app totally aware of (and using) thread-
> local contexts should also use process-wide contexts. It would be for
> interaction with code possibly unaware of thread-local contexts. If you think
> option 3 is the way to go for that, I don't really see a need to also have
> option 1's behavior (and vice-versa).
>  

I see, that does make sense.

--"J"

_______________________________________________
Openal-devel mailing list
Openal-devel@...
http://opensource.creative.com/mailman/listinfo/openal-devel

Re: Thread-local contexts

by Chris Robinson-5 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Okay, here's a preliminary write up.

http://kcat.strangesoft.net/openal-extensions/EXT_thread_local_context.txt

I'm not too happy with some of the wording, so any improvements in that would
be welcome. But any further questions or comments are welcome.
_______________________________________________
Openal-devel mailing list
Openal-devel@...
http://opensource.creative.com/mailman/listinfo/openal-devel