20070403

audio_fifo sports one thread that is supposed to read from the pipe in the background.
audio_fifo methods work with the shared buffer (protected via locks) or control the worker thread
This control is tricky.
One main complication is that currently, I need to stop the thread in order to clear the pipe in mpg123_input.
Ideally, I should make the fifo thread do the work and really encapsulate the pipe, but for now this situation can be seen as an opportunity to implement proper thread control.

Control means:
1. start the thread
	It's enough to know that the thread will begin work "soon". Important is that when wait for it to do work, it is really working.
2. stop the thread
	Here it's vital to ensure that after the stop() method, the thread really is not touching the pipe.
	We need to wait for it to acknowledge the halt.
3. query status
	I need to know if the thread is currently active. 

The thread has this basic structure:

	while(1)
	{
		sem_wait(&af->rsem);
		// make sure that we awake only once
		while(sem_trywait(&af->rsem) == 0){}

		while(!af->got_end && af->readstate == 0)
		{
			if(af->reader_pause) break; // could go into loop condition
			// wait for data via select()
			// lock buffer and read into it if data there
			if(reached_end()) af->got_end = true;
			if(error_on_pipe()) af->readstate = -1;
		}
	}

Starting the thread means sem_post(&af->rsem). Depending on the conditions, it will actually do its work.
Stopping is handled via setting af->reader_pause (should do this via semaphore, perhaps...). Thread does some work (which is always non-blocking) and eventually encounters the flag, goes into waiting mode.
Now the stopper needs to know when this happened. Thus, the thread should hold a semaphore which indicates that it's waiting.
The stop method would set the flag, sem_wait() and then again do sem_post() to enable others to check the semaphore value for the thread's status.
If the semaphore is not set, the thread is somewhere in its loop and possibly doing something useful.
If it is set, it is ensured that the thread does nothing.
...this includes the thread clearing this semaphore when it gets activated.

So:

	while(1)
	{
		sem_post(&af->wsem);
		sem_wait(&af->rsem);
		// make sure that we awake only once
		while(sem_trywait(&af->rsem) == 0){}
		// clear the waiting semaphore
		while(sem_trywait(&af->wsem) == 0){}

		while(!af->got_end && af->readstate == 0)
		{
			if(af->reader_pause) break; // could go into loop condition
			// wait for data via select()
			// lock buffer and read into it if data there
			if(reached_end()) af->got_end = true;
			if(error_on_pipe()) af->readstate = -1;
		}
		debug("%p fifo_reader done for now, readstate=%i, got_end=%i", p, af->readstate, (int)af->got_end);
	}

then the control methods:

bool waiting()
{
	int w;
	sem_getvalue(&wsem, &w);
	return (w > 0);
}

start()
{
	if(waiting()) sem_post(&rsem);
}

stop()
{
	if(!waiting())
	{
		reader_pause = true;
		sem_wait(&wsem);
		sem_post(&wsem); // put the value back
		reader_pause = false;
	}
}
