Using Channels to effect asynchronous threads

Technical questions regarding the XTC tools and programming with XMOS.
User avatar
lilltroll
XCore Expert
Posts: 956
Joined: Fri Dec 11, 2009 3:53 am
Location: Sweden, Eskilstuna

Post by lilltroll »

https://www.xmos.com/published/xmos-xs1 ... ion=latest
Read page 22-24 regarding the END token that closes the channel.


User avatar
Obtuse
Member++
Posts: 29
Joined: Mon Jul 09, 2012 11:54 pm

Post by Obtuse »

PAUSE....interesting. Have to look into that.
It will open the channel, send the data, and close the channel again, making the switch free to use for other channel messages from other threads.
But if thread1 is not ready to rx the data it blocks thread2 from proceeding. Which is
partly what is needed, depending on conditions in thread2.

My original plan was to use two XC channels, kind of a circular Stop & Go.

Hm........

EDIT: Perhaps the OUTCT(I) and CHECKCT(I) will do the job. (?)
User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am
Contact:

Post by segher »

What is it that you *really* want to do? You have a bunch of "clients"
and a "server", and then what? They talk and stuff? And you want
some of them to block sometimes, it seems?

We need more details to give you any good advice ;-)
User avatar
lilltroll
XCore Expert
Posts: 956
Joined: Fri Dec 11, 2009 3:53 am
Location: Sweden, Eskilstuna

Post by lilltroll »

Sometimes you have a main thread always running and many service/slave threads like a LCD, buttons, UART etc.
A solution is to use a select with a default in each service threads. Each service thread can cont. to run, but when the main threads sends a message on the channel, it will instead answer and thereafter cont. it´s own service stuff*.
This way the main thread will never block, and it can ask any service for data anytime.
If the main thread is running in an infinite loop you may send a message to the slave but wait until the next loopiteration for the readback to hide the small delay, depending on the priority of the threads.

*if a service thread collects alot of data, you may instead send a pointer/reference to the memory over the channel to the main thread avoiding stalling the services with a large channel data transfer (but only if the two threads are on the same core).
User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am
Contact:

Post by segher »

lilltroll wrote:A solution is to use a select with a default in each service threads. Each service thread can cont. to run, but when the main threads sends a message on the channel, it will instead answer and thereafter cont. it´s own service stuff*.
This way the main thread will never block, and it can ask any service for data anytime.
The main thread *does* block in this case, until the client thread is ready
to answer (that is, is executing that select statement). The delay should be
small (or you have a big problem), but it is certainly not negligible.
priority of the threads
What's that? This isn't pthreads or similar, thank goodness :-)
User avatar
Folknology
XCore Legend
Posts: 1274
Joined: Thu Dec 10, 2009 10:20 pm
Contact:

Post by Folknology »

pthr#*ds
No swearing on this channel please ;-)

N.B. 'We prefer the term artificial threads..'
User avatar
Obtuse
Member++
Posts: 29
Joined: Mon Jul 09, 2012 11:54 pm

Post by Obtuse »

What I was looking to do is toggle a channel on and off and use this as a variable time length go/no-go switch for threads on separate cores.

(I have plenty to read and play with right now.)

case 1:

(thread X)
LOOP.
wait for external input to change.
input = data.
send channel data.
// thread is blocked
Back to LOOP.

(thread Y)
AGAIN.
long delay.
long delay.
read channel data.
// channel is established. Thread X is unblocked.
Do processing on data.
Back to AGAIN.

The problem here is thread Y will keep looping on the old data.
It will not wait until the next change on thread X input.

case 2:

(thread X)
LOOP.
wait for external input to change.
input = data.
send channel data. // possible block waiting for read from Y.
Back to LOOP.

(thread Y)
AGAIN.
long delay.
long delay.
read channel data. // Possible block waiting for send from X.
// channel is established. Thread X is unblocked.
Kill channel. ****
Do processing on data.
Back to AGAIN.

This time the channel(ends) must be re-established or either thread could be blocked.

This is not a real life problem. Just part of the learning curve.
Anyway, just looking for/trying different possibilities.
For now, as per the suggestions made, it's "Back to the books".

Geez :( ...When will I know it all? :)
User avatar
rp181
Respected Member
Posts: 395
Joined: Tue May 18, 2010 12:25 am
Contact:

Post by rp181 »

The problem here is thread Y will keep looping on the old data.
This isn't true. In Thread Y, the statement "read channel data." will block until new data is sent from Thread X. I think you are misunderstanding channels.

Channels are not memory stores, but rather FIFO paths of communication. Once you read the data from the channel, the data is no longer in the channel. Reading it again would simply block until new data is provided. Therefore, there is no "old data" it would keep receiving.

Again, if you don't want a channel communication to block, use a select guard.
User avatar
Obtuse
Member++
Posts: 29
Joined: Mon Jul 09, 2012 11:54 pm

Post by Obtuse »

I think you are misunderstanding channels.
You got that right. :-(

Good thing this place is here. :-)
User avatar
Obtuse
Member++
Posts: 29
Joined: Mon Jul 09, 2012 11:54 pm

Post by Obtuse »

RP181 wrote:
Channels are not memory stores, but rather FIFO paths of communication. Once you read the data from the channel, the data is no longer in the channel. Reading it again would simply block until new data is provided.
That's it! :)

That paragraph made the logic sink in.

It should be added to the tutorial for thick heads like mine.

Also, in the 'Using Channels in XC' tutorial, in the paragraph below the code section that contains;
Pong received Ping
Ping received Pong
Pong received Ping

it states;
Channels require symmetric input and output, that is for every input there must be an input, if this isn't observed it will crash the program.
input, input?

and maybe use, 'crash or block'?

Anyway.......FREE beer for all, and many thanks for the help. :)
Post Reply