Alternate thread based model for jack proposal

classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|

Alternate thread based model for jack proposal

Stéphane Letz
Hi All,

Some months ago Fons Adriaensen proposed an alternative way to  
implement audio process in a jack application by adding a new function  
called "jack_thread_wait" in the API. This function allows the RT  
callback to "wait" for the next cycle and in some way control "return  
to libjack", thus signaling the next clients in the graph. It allows  
to implement applications that need to get frames from several  
callback before starting their process without having to explicitly  
maintain a state outside of the audio callback. It appears that this  
new function also simplify multi-threaded application programming by  
allowing again precise control of  "return to libjack".

After some discussion with Dave Robillard and Juuso Alasuutari, it  
appeared that this function is somewhat difficult to understand and  
use and it would be even more flexible to give access to two different  
functions "jack_cycle_wait" and "jack_cycle_signal". So an new  
proposal would be the following:


1) Current callback based model:
---------------------------------------------

int process (jack_nframes_t nframes)
{
        // process audio
        return 0;
}

jack_client_t * client = jack_client_open (client_name, options,  
&status, NULL);
jack_set_process_callback (client, process, client);
jack_activate (client):

/// client running

jack_deactivate (client);
jack_client_close(client);

2) Alternate thread based model:
---------------------------------------------

int process (jack_nframes_t nframes)
{
        // process audio
        return 0;
}

void* jack_thread(void *arg)
{
        jack_client_t* client = (jack_client_t*) arg;

        // possibly calling an "init" callback
       
        while (1) {
                jack_nframes_t frames = jack_cycle_wait (client);
                int status = process(frames);
                jack_cycle_signal (client, status);
        }
       
        return 0;
}


jack_client_t * client = jack_client_open (client_name, options,  
&status, NULL);
jack_client_create_thread(client, &thread, 90, 1, jack_thread, client);
jack_acquire_real_time_scheduling (thread, 90);
jack_activate (client):

/// client running

jack_deactivate (client);
jack_client_close(client);

Basically the 2) model would give the application complete access to  
the RT audio thread: creation and control. As we see the 1) model can  
be written using the 2) model. Internally it would be implemented like  
this: if the application uses "jack_set_process_callback", then  
libjack know that the 1) model is used and the internal RT thread is  
started in "jack_activate" as before, otherwise (no RT cb ), libjack  
know the 2) model will be used and does not start it's internal RT  
thread: everything concerning audio RT creation would be then the  
responsability of the application.

This model can be implemented in jackdmp with it's "two thread  
model" (one for notifications coming from the server and one audio RT  
thread). It may be more complicated in jackd codebase. But it would be  
interesting to get some feedback before starting any development.

Stephane

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Alternate thread based model for jack proposal

Fons Adriaensen-2
On Wed, Feb 20, 2008 at 11:35:44AM +0100, Stéphane Letz wrote:

> After some discussion with Dave Robillard and Juuso Alasuutari, it  
> appeared that this function is somewhat difficult to understand and  
> use and it would be even more flexible to give access to two different  
> functions "jack_cycle_wait" and "jack_cycle_signal". So an new  
> proposal would be the following:

I will provide a more detailed reply once I've had
the time to understand this proposal and it's
consequences. But pleas note:

- The call as it is now is not at all difficult to
  understand or use. What you need to understand is
  that, since it's equivalent (from jackd's POV) to
  returning from the callback:
 
  - The callback's return value becomes a function parameter
  - The callback's nframes parameter becomes the return value
  - When it returns you have to refresh your jack-buffer
    pointers, as you would at the start of a callback.
   
  It is so simple to use that I have some clients that
  (just for the fun of testing it) switch randomly between
  the two methods while running.

  It also introduces nothing new in jackd's code. The
  waiting function is just a refactoring of what was
  already there, in order to expose it as a function.
  The internal logic remains exactly the same as before.
     
- I explicitly ruled out the option that the client would
  create it's own thread. This is an ortoghonal issue, and
  one that opens up a can of possible nasty worms.

Ciao,

--
FA

Laboratorio di Acustica ed Elettroacustica
Parma, Italia

Lascia la spina, cogli la rosa.


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Alternate thread based model for jack proposal

Stéphane Letz

Le 20 févr. 08 à 19:01, Fons Adriaensen a écrit :

> On Wed, Feb 20, 2008 at 11:35:44AM +0100, Stéphane Letz wrote:
>
>> After some discussion with Dave Robillard and Juuso Alasuutari, it
>> appeared that this function is somewhat difficult to understand and
>> use and it would be even more flexible to give access to two  
>> different
>> functions "jack_cycle_wait" and "jack_cycle_signal". So an new
>> proposal would be the following:
>
> I will provide a more detailed reply once I've had
> the time to understand this proposal and it's
> consequences. But pleas note:
>
> - The call as it is now is not at all difficult to
>   understand or use. What you need to understand is
>   that, since it's equivalent (from jackd's POV) to
>   returning from the callback:
>
>   - The callback's return value becomes a function parameter
>   - The callback's nframes parameter becomes the return value
>   - When it returns you have to refresh your jack-buffer
>     pointers, as you would at the start of a callback.
>
>   It is so simple to use that I have some clients that
>   (just for the fun of testing it) switch randomly between
>   the two methods while running.

It would possibly help the discussion to see this code...
>
>   It also introduces nothing new in jackd's code. The
>   waiting function is just a refactoring of what was
>   already there, in order to expose it as a function.
>   The internal logic remains exactly the same as before.

Right, but jack_cycle_wait and jack_cycle_signal would also be  
exposure of "already there" code..  Basically:

jack_thread_wait(..) ==  jack_cycle_signal(..); jack_cycle_wait(..);

One of the idea here is to separate "waiting" and "signaling" as two  
different functions. I hope Dave can provide some example of their use.

>
> - I explicitly ruled out the option that the client would
>   create it's own thread. This is an ortoghonal issue, and
>   one that opens up a can of possible nasty worms.
>
> Ciao,
>
>
Yes this is a valid point, but having  jack_cycle_signal(..);  
jack_cycle_wait(..) *and* keeping the callack model seems event more  
nasty.

Hope we will see more feedback on the subject.

Stephane
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Alternate thread based model for jack proposal

Fons Adriaensen-2
On Wed, Feb 20, 2008 at 07:45:51PM +0100, Stéphane Letz wrote:

> jack_thread_wait(..) ==  jack_cycle_signal(..); jack_cycle_wait(..);

If this is indeed true (and that's what I will want
to verify), then it's an interesting idea.

It would allow a client to say, "OK, as far as JACK
is concerned I'm ready but please let me continue with
my own stuff for a while". For example send messages
to other threads or check if they have sent any. This
actually happens in almost all of my apps, and indeed
there is no reason to keep JACK waiting for it.

On a single-CPU system nothing special would happen.
Some other client will be scheduled but it will not
run until the first one calls jack_cycle_wait(), since
RT threads are not pre-empted by their peers of same
priority. On an SMP system the two would be allowed
to run at the same time.

For jackdmp this is nothing new - it already handles
this situation. But I suspect that for jackd you will
have to impose the rule that between the two calls the
client must not call any jacklib code. If jackd can
handle this it would be more by accident than by design.
And since apps may want to be portable between the
two servers they should in fact always obey that rule.

Independent of this, you will have to exclude any
access to jackd(mp) buffers after the signal call.

More later,

--
FA

Laboratorio di Acustica ed Elettroacustica
Parma, Italia

Lascia la spina, cogli la rosa.


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Alternate thread based model for jack proposal

Stéphane Letz

Le 20 févr. 08 à 20:36, Fons Adriaensen a écrit :

> On Wed, Feb 20, 2008 at 07:45:51PM +0100, Stéphane Letz wrote:
>
>> jack_thread_wait(..) ==  jack_cycle_signal(..); jack_cycle_wait(..);
>
> If this is indeed true (and that's what I will want
> to verify), then it's an interesting idea.
>
> It would allow a client to say, "OK, as far as JACK
> is concerned I'm ready but please let me continue with
> my own stuff for a while".

I understand you mean the RT thread uses  jack_cycle_signal to signal  
next clients... and possibly still does some stuff after that, before  
calling jack_cycle_wait  to suspend itself again...
Yes this is a possibility.. but jack_cycle_wait has to be called  
before next cycle begins...


> For example send messages
> to other threads or check if they have sent any. This
> actually happens in almost all of my apps, and indeed
> there is no reason to keep JACK waiting for it.
>
> On a single-CPU system nothing special would happen.
> Some other client will be scheduled but it will not
> run until the first one calls jack_cycle_wait(), since
> RT threads are not pre-empted by their peers of same
> priority. On an SMP system the two would be allowed
> to run at the same time.
>
> For jackdmp this is nothing new - it already handles
> this situation. But I suspect that for jackd you will
> have to impose the rule that between the two calls the
> client must not call any jacklib code. If jackd can
> handle this it would be more by accident than by design.
> And since apps may want to be portable between the
> two servers they should in fact always obey that rule.
>
> Independent of this, you will have to exclude any
> access to jackd(mp) buffers after the signal call.

Yes sure. Audio processing related code is supposed to be done  
between jack_cycle_wait and jack_cycle_signal.

Stephane
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Alternate thread based model for jack proposal

Fons Adriaensen-2
On Wed, Feb 20, 2008 at 09:09:35PM +0100, Stéphane Letz wrote:

> I understand you mean the RT thread uses  jack_cycle_signal to signal  
> next clients... and possibly still does some stuff after that, before  
> calling jack_cycle_wait  to suspend itself again...
> Yes this is a possibility.. but jack_cycle_wait has to be called  
> before next cycle begins...

You seem to be surprised by my idea of having some client
code in between the signal and wait calls. If this is not
the intention, why separate them ???

Ciao,

--
FA

Laboratorio di Acustica ed Elettroacustica
Parma, Italia

Lascia la spina, cogli la rosa.


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Alternate thread based model for jack proposal

Stéphane Letz

Le 20 févr. 08 à 21:09, Fons Adriaensen a écrit :

> On Wed, Feb 20, 2008 at 09:09:35PM +0100, Stéphane Letz wrote:
>
>> I understand you mean the RT thread uses  jack_cycle_signal to signal
>> next clients... and possibly still does some stuff after that, before
>> calling jack_cycle_wait  to suspend itself again...
>> Yes this is a possibility.. but jack_cycle_wait has to be called
>> before next cycle begins...
>
> You seem to be surprised by my idea of having some client
> code in between the signal and wait calls. If this is not
> the intention, why separate them ???
>
> Ciao,
>
>

Dave Robillard first argument was "to be able to use them in different  
functions or context", but what you explained is actually a much  
better one.

Stephane
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Alternate thread based model for jack proposal

Stéphane Letz
In reply to this post by Fons Adriaensen-2
>
> - I explicitly ruled out the option that the client would
>  create it's own thread. This is an ortoghonal issue, and
>  one that opens up a can of possible nasty worms.
>

So we could possibly introduce this couple of function  
jack_cycle_signal  and jack_cycle_wait (with the property : old  
jack_thread_wait(); = jack_cycle_signal(); jack_cycle_wait();  ) and  
keep the callback model, that is *not* having the client creates its  
own thread. Would this be a reasonable solution?

Stephane

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Alternate thread based model for jack proposal

David Robillard-3
In reply to this post by Stéphane Letz
On Thu, 2008-02-21 at 13:33 +0100, Stéphane Letz wrote:

> Le 20 févr. 08 à 21:09, Fons Adriaensen a écrit :
>
> > On Wed, Feb 20, 2008 at 09:09:35PM +0100, Stéphane Letz wrote:
> >
> >> I understand you mean the RT thread uses  jack_cycle_signal to signal
> >> next clients... and possibly still does some stuff after that, before
> >> calling jack_cycle_wait  to suspend itself again...
> >> Yes this is a possibility.. but jack_cycle_wait has to be called
> >> before next cycle begins...
> >
> > You seem to be surprised by my idea of having some client
> > code in between the signal and wait calls. If this is not
> > the intention, why separate them ???
> >
> > Ciao,
> >
> >
>
> Dave Robillard first argument was "to be able to use them in different  
> functions or context", but what you explained is actually a much  
> better one.

I suggested this for larger clients, since it works out much nicer in
some cases.  In e.g. Ardour and Ingen, the actual 'finishing' part
usually takes place (or will take place, anyway) out in other bits of
code, and which (possibly parallel) 'worker' finishes first isn't set in
stone (inherent in the parallelism usually).

Separating them like this means you can do things like this:

jack_process_callback() {
        jack_cycle_wait();
        read_inputs();
        do_other_non_parallel_stuff();
        call_workers();
}

/* several of these */
worker() {
        if (work_left)  /* atomic */
                do_stuff();
        else
                jack_cycle_finished();
}

Point of the separation: if they aren't separate, the app has to deal
with signalling back to the driver that things are ready, and it can
return.  This can be quite a nuisance in more complex clients.

Being able to run some code after the last finished() and before the
next wait() is also handy for performance reasons.  Best example is
event based stuff, the jack cycle can look something like this:

jack_process_callback() {
        jack_cycle_wait();
        do_jack_stuff();
        write_outputs();
        jack_cycle_finished();
       
        /* now jack is done with us, and other clients
         * aren't waiting on this callback */

        deliver_notifications_to_ui(); /* (realtime, of course) */
}

(Ingen does this, where the notifications result in OSC messages being
fired back to the client in another thread, though the same is true of
pretty much anything that sends events to a UI/client/whatever).

Without the separation, jack ends up waiting on the notifications (ie
pumping stuff into a ringbuffer so another thread can deal with it), but
that's not necessary since it has no effect on Jack output.  This way,
Jack waits on exactly what it /needs/ to wait on (and it's extremely
likely the in-between bit of code finished before the next wait could
return anyway).

Basically the same as Fons' original proposal, but the split wait and
finish calls make several things much nicer (less annoying code in the
clients), and have a potential performance benefit too (esp. for
parallel clients).

Cheers,

-DR-



-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel

Reply | Threaded
Open this post in threaded view
|

Re: Alternate thread based model for jack proposal

Fons Adriaensen-2
Hello Dave and Stephane,

> I suggested this for larger clients, since it works out much nicer in
> some cases. In e.g. Ardour and Ingen, the actual 'finishing' part
> usually takes place (or will take place, anyway) out in other bits of
> code, and which (possibly parallel) 'worker' finishes first isn't set in
> stone (inherent in the parallelism usually).

The second example you give corresponds to the use
case I mentioned before. It happens in almost all
my apps and (surprise ! surprise !) also in yours...
I see no problems with this use.

Now I'm trying to grok the first example...

> Separating them like this means you can do things like this:
>
> jack_process_callback() {
> jack_cycle_wait();
> read_inputs();
> do_other_non_parallel_stuff();
> call_workers();
> }
>
> /* several of these */
> worker() {
> if (work_left)  /* atomic */
> do_stuff();
> else
> jack_cycle_finished();
> }
>
> Point of the separation: if they aren't separate, the app has to deal
> with signalling back to the driver that things are ready, and it can
> return.  This can be quite a nuisance in more complex clients.
> event based stuff, the jack cycle can look something like this:

I'm moderately confused now :-) In Stephane's message
we had

jack_cycle_signal()  // Tell jack we are ready with the audio
                     // processing. Output buffers are valid,
                     // inputs are no longer needed.

jack_cycle_wait()    // Wait until jack wakes us up.

and these two indeed add up to the current jack_thread_wait(),
but allow you to do some things in between them. This again
corresponds to the second example you give, but the semantics
seem to be different.

In order to understand your examples, I must assume that
your jack_cycle_wait() is not the one mentioned above.
What it seems to do is tell jack

- to ignore a return from the process callback as a signal
  that we are ready,

- and to use the first jack_cycle_finished() instead,
  regardless of if the callback has returned (as in
  your first example, quoted above) or not (as in the
  second example).

Is this correct ?

This allows me to interpret your code as follows:

The call_workers() triggers a number of worker threads
but does not block, so the callback returns, but this is
ignored by jack because of the previous jack_cycle_wait().

But then I don't understand the structure of the workers.
I assume there is a loop around the code you show, with
a wait() for whatever is signalled by call_workers().
The workers take whatever work there is and have a
method to obtain a job atomically. If there is no more
work they call jack_cycle_finished().

- This doesn't seem t work correctly. The first call
to jack_cycle_finished() is done by the first worker
that discovers that there is no more work. But this
doesn't mean the others have finished their work.
Jack should wait until *all* are ready, and I don't
see this happen with this code (assuming I read it
correctly).

- There will be multiple calls to jack_cycle_finished().
Also they will originate from threads that are not
known to jackd. Both could complicate the solution.

A simple solution for both problems would be something
like jackd waiting on a counting semaphore, with the
initial state supplied by jack_cycle_wait(int N), and
signalled by jack_cycle_finished (). But this assumes
that jackd *has* a trhead to do this.

I have another consideration. The code needed to
distribute the work and to atomically test and get it
would probably be a lot more complex that what you
need to signal back to the callback that all workers
are ready. All _that_ takes is a counting semaphore.
So why replace that simple method with something that
could be quite invasive to jackd ? Re-using your code:


jack_process_callback() {
        read_inputs();
        do_other_non_parallel_stuff();
        set_sema_state (number_of_workers - 1);
        call_workers();
        wait_for_sema();
}

/* several of these */
while (true) {
        wait_for_trigger() // from call_workers()
        while (get_some_work ()) do_stuff();
        signal_the_sema();
}

which requires no extra jack_* calls, and also
allows the callback thread to do some work (not
shown) after all workers are ready.

--
FA

Laboratorio di Acustica ed Elettroacustica
Parma, Italia

Lascia la spina, cogli la rosa.


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel

Reply | Threaded
Open this post in threaded view
|

Re: Alternate thread based model for jack proposal

Stéphane Letz

Le 24 févr. 08 à 20:10, Fons Adriaensen a écrit :

> Hello Dave and Stephane,
>
>> I suggested this for larger clients, since it works out much nicer in
>> some cases. In e.g. Ardour and Ingen, the actual 'finishing' part
>> usually takes place (or will take place, anyway) out in other bits of
>> code, and which (possibly parallel) 'worker' finishes first isn't  
>> set in
>> stone (inherent in the parallelism usually).
>
> The second example you give corresponds to the use
> case I mentioned before. It happens in almost all
> my apps and (surprise ! surprise !) also in yours...
> I see no problems with this use.
>
> Now I'm trying to grok the first example...
>
>> Separating them like this means you can do things like this:
>>
>> jack_process_callback() {
>> jack_cycle_wait();
>> read_inputs();
>> do_other_non_parallel_stuff();
>> call_workers();
>> }
>>
>> /* several of these */
>> worker() {
>> if (work_left)  /* atomic */
>> do_stuff();
>> else
>> jack_cycle_finished();
>> }
>>
>> Point of the separation: if they aren't separate, the app has to deal
>> with signalling back to the driver that things are ready, and it can
>> return.  This can be quite a nuisance in more complex clients.
>> event based stuff, the jack cycle can look something like this:
>
> I'm moderately confused now :-) In Stephane's message
> we had
>
> jack_cycle_signal()  // Tell jack we are ready with the audio
>                     // processing. Output buffers are valid,
>                     // inputs are no longer needed.
>
> jack_cycle_wait()    // Wait until jack wakes us up.
>
> and these two indeed add up to the current jack_thread_wait(),
> but allow you to do some things in between them. This again
> corresponds to the second example you give, but the semantics
> seem to be different.
>
> In order to understand your examples, I must assume that
> your jack_cycle_wait() is not the one mentioned above.
> What it seems to do is tell jack
>
> - to ignore a return from the process callback as a signal
>  that we are ready,
>
> - and to use the first jack_cycle_finished() instead,
>  regardless of if the callback has returned (as in
>  your first example, quoted above) or not (as in the
>  second example).
>
> Is this correct ?
>
> This allows me to interpret your code as follows:
>
> The call_workers() triggers a number of worker threads
> but does not block, so the callback returns, but this is
> ignored by jack because of the previous jack_cycle_wait().
>
> But then I don't understand the structure of the workers.
> I assume there is a loop around the code you show, with
> a wait() for whatever is signalled by call_workers().
> The workers take whatever work there is and have a
> method to obtain a job atomically. If there is no more
> work they call jack_cycle_finished().
>
> - This doesn't seem t work correctly. The first call
> to jack_cycle_finished() is done by the first worker
> that discovers that there is no more work. But this
> doesn't mean the others have finished their work.
> Jack should wait until *all* are ready, and I don't
> see this happen with this code (assuming I read it
> correctly).
>
> - There will be multiple calls to jack_cycle_finished().
> Also they will originate from threads that are not
> known to jackd. Both could complicate the solution.
>
> A simple solution for both problems would be something
> like jackd waiting on a counting semaphore, with the
> initial state supplied by jack_cycle_wait(int N), and
> signalled by jack_cycle_finished (). But this assumes
> that jackd *has* a trhead to do this.
>
> I have another consideration. The code needed to
> distribute the work and to atomically test and get it
> would probably be a lot more complex that what you
> need to signal back to the callback that all workers
> are ready. All _that_ takes is a counting semaphore.
> So why replace that simple method with something that
> could be quite invasive to jackd ? Re-using your code:
>
>
> jack_process_callback() {
>        read_inputs();
>        do_other_non_parallel_stuff();
>        set_sema_state (number_of_workers - 1);
>        call_workers();
> wait_for_sema();
> }
>
> /* several of these */
> while (true) {
>        wait_for_trigger() // from call_workers()
>        while (get_some_work ()) do_stuff();
>        signal_the_sema();
> }
>
> which requires no extra jack_* calls, and also
> allows the callback thread to do some work (not
> shown) after all workers are ready.
>

Seems we hit some problems here... Dave?

Concerning the way the alternate thread model could be setup at the  
API level, I would now suggest to keep a clear distinction between the  
callback and the thread model (and not mix both):

1) Current callback model :

typedef int (*JackProcessCallback)(jack_nframes_t nframes, void *arg);

int jack_set_process_callback (jack_client_t *client,  
JackProcessCallback process_callback, void *arg);


2) Thread model: keep thread creation in libjack as done now, add a  
new function to give the "thread function" to libjack:

typedef void *(*JackRTThread)(void* arg);

int jack_set_process_thread(jack_client_t* client, JackRTThread fun,  
void *arg); // same prototype to the "start_routine" of  the  
pthread_create function.

And then assume the whole thread control (wait/signal) is done using  
the following functions:
       
jack_nframes_t jack_cycle_wait (jack_client_t*);
void jack_cycle_signal (jack_client_t*, int status);

The application has to chose between the 2 models, so that when  
"jack_activate" is called, libjack code knows what to do.

Stephane





-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Alternate thread based model for jack proposal

Fons Adriaensen-2
On Mon, Feb 25, 2008 at 01:07:23PM +0100, Stéphane Letz wrote:

> Concerning the way the alternate thread model could be setup at the API
> level, I would now suggest to keep a clear distinction between the callback
> and the thread model (and not mix both):

1. The callback model is trivially implemented on top
of the jack_thread_wait() one by adding a loop.

2. This does not change if jack_thread_wait() is split
up into jack_cycle_signal() and jack_cycle_wait().

3. This does not change if the thread is created by
the client.

4. All my clients (not only the random-choice ones)
use a mix of both methods wich comes quite naturally.

So the two methods should not be artificially separated
from each other.

--
FA

Laboratorio di Acustica ed Elettroacustica
Parma, Italia

Lascia la spina, cogli la rosa.


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Alternate thread based model for jack proposal

Stéphane Letz

Le 26 févr. 08 à 06:51, Fons Adriaensen a écrit :

> On Mon, Feb 25, 2008 at 01:07:23PM +0100, Stéphane Letz wrote:
>
>> Concerning the way the alternate thread model could be setup at the  
>> API
>> level, I would now suggest to keep a clear distinction between the  
>> callback
>> and the thread model (and not mix both):
>
> 1. The callback model is trivially implemented on top
> of the jack_thread_wait() one by adding a loop.
>
> 2. This does not change if jack_thread_wait() is split
> up into jack_cycle_signal() and jack_cycle_wait().
>
> 3. This does not change if the thread is created by
> the client.
>
> 4. All my clients (not only the random-choice ones)
> use a mix of both methods wich comes quite naturally.

Any source example of that?

Thanks

Stephane



-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel