Csound Csound-dev Csound-tekno Search About

[Csnd] Some questions around the channel API

Date2017-08-29 02:26
FromBenjamin Niemann
Subject[Csnd] Some questions around the channel API
Hello friendly community of Csounders,

I'm playing with Csound, integrating it (as one of several processors)
into an application I'm currently working on.
I'm using channels to pass audio/control data from the app into Csound
and vice versa and while working on the code, some questions come up:

1) Are the pointers returned by
csoundGetChannelPtr/csoundGetChannelLock constant for the duration of
the Csound instance? I had a brief look at the code and that seems to
be true, but a confirmation would be nice. I'm only calling
csoundCompileOrc once, so I wouldn't care, if that would invalidate
those pointers...

2) The documentation says "The host is required to take care of
threadsafety...". In my use case I'm running Csound in the same thread
that writes to/reads from the channels. I.e. for each ksmps of samples
I execute a block
  [...copy data into all input channels...]
  csoundPerformKsmps(csnd);
  [...copy data out of all output channels...]
Do I have to care about the locks at all in this case?

And the next two bleed into Csound-dev territory...

3) When I first tried something like this:
 int *lock = csoundGetChannelLock(csnd, port_name);
 csoundSpinLock(lock);
 *buf = *channel_ptr;
 csoundSpinUnLock(lock);
I was surprised to see gcc complain about "error: unused variable
‘lock’". Digging into this, I saw that csoundSpinLock/csoundSpinUnlock
are defined as macros in csound.h, with different implementations
based on various #ifdefs and defaulting to empty expansions.
Which implementation should be used depends on the compiler flags used
for building csound. But an app using csound uses a completely
different set of flags.
In the worst case (which I'm not sure if it can currently happen), the
app might have a -DHAVE_PTHREAD_SPIN_LOCK, where as csound did not,
which would probably result in a SIGSEGV, because channelEntry_s->lock
does not point to an initialized pthread_spinlock_t struct.
The more common case is probably that csound users on Linux, who don't
compile their code with -DHAVE_PTHREAD_SPIN_LOCK (and why should
they...) end up with no locking when using csoundGetChannelPtr.

I've never encountered such a case before, so I don't know if there's
a good pattern to solve this issue. Two options that I can think of:
Either make these regular functions and move the #ifdef magic into
that function's implementation, where the right compiler flags are in
effect - at the expense of the additional function call overhead.
Or have cmake rewrite the csound.h file that it deploys with the right
#defines, so every app uses the the right code, no matter what -Ds are
used when compiling it.

4) One of the csoundSpinLock/csoundSpinUnlock implementations in
csound.h uses gcc built-ins
__sync_lock_test_and_set/__sync_lock_release, but only if
pthread_spin_lock is not available.
4a) Shouldn't this be slightly faster than a call into libpthread and
thus preferred, if both are available at compile time?
4b) But it does look like dead code anyway, as I don't see
HAVE_SYNC_LOCK_TEST_AND_SET being set anywhere. Did the corresponding
CMakeLists.txt snipped get lost along the way?

Cheers,
-Ben

Csound mailing list
Csound@listserv.heanet.ie
https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND
Send bugs reports to
        https://github.com/csound/csound/issues
Discussions of bugs and features can be posted here

Date2017-08-29 17:56
FromRory Walsh
SubjectRe: [Csnd] Some questions around the channel API
Hi Ben.

1) Are the pointers returned by
csoundGetChannelPtr/csoundGetChannelLock constant for the duration of
the Csound instance? I had a brief look at the code and that seems to
be true, but a confirmation would be nice. I'm only calling
csoundCompileOrc once, so I wouldn't care, if that would invalidate
those pointers...

As far as I know, you shouldn't have any issues calling csoundCompileOrc() as often as you like.
 

2) The documentation says "The host is required to take care of
threadsafety...". In my use case I'm running Csound in the same thread
that writes to/reads from the channels. I.e. for each ksmps of samples
I execute a block
  [...copy data into all input channels...]
  csoundPerformKsmps(csnd);
  [...copy data out of all output channels...]
Do I have to care about the locks at all in this case?

I can't see how that would lead to any threading issues. I do the same all the time. Note that as of Csound6,csoundGetChannelPtr should actually be thread safe. As far as I know Victor added thread safety for channel communication quite a while back.

I can't really comment on the rest of your questions, but for what it's worth, I've been using the API for 10 years or so, and I've never once found the need to use csoundSpinLock(). Maybe I've just been lucky!
Csound mailing list Csound@listserv.heanet.ie https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND Send bugs reports to https://github.com/csound/csound/issues Discussions of bugs and features can be posted here