Esempio n. 1
0
/*
* QBufPipe_Finish
*
* Blocks until the reader thread handles all commands
* or terminates with an error.
*/
void QBufPipe_Finish( qbufPipe_t *pipe ) {
	while( Sys_Atomic_CAS( &pipe->cmdbuf_len, 0, 0, pipe->cmdbuf_mutex ) == false && !pipe->terminated ) {
		QMutex_Lock( pipe->nonempty_mutex );
		QBufPipe_Wake( pipe );
		QMutex_Unlock( pipe->nonempty_mutex );
		QThread_Yield();
	}
}
Esempio n. 2
0
/*
* QBufPipe_WriteCmd
*
* Add new command to buffer. Never allow the distance between the reader
* and the writer to grow beyond the size of the buffer.
*
* Note that there are race conditions here but in the worst case we're going
* to erroneously drop cmd's instead of stepping on the reader's toes.
*/
void QBufPipe_WriteCmd( qbufPipe_t *pipe, const void *cmd, unsigned cmd_size )
{
	void *buf;
	unsigned write_remains;
	bool was_empty;
	
	if( !pipe ) {
		return;
	}
	if( pipe->terminated ) {
		return;
	}

	assert( pipe->bufSize >= pipe->write_pos );
	if( pipe->bufSize < pipe->write_pos ) {
		pipe->write_pos = 0;
	}

	was_empty = Sys_Atomic_CAS( &pipe->cmdbuf_len, 0, 0, pipe->cmdbuf_mutex ) == true;
	write_remains = pipe->bufSize - pipe->write_pos;

	if( sizeof( int ) > write_remains ) {
		while( pipe->cmdbuf_len + cmd_size + write_remains > pipe->bufSize ) {
			if( pipe->blockWrite ) {
				QThread_Yield();
				continue;
			}
			return;
		}

		// not enough space to enpipe even the reset cmd, rewind
		QBufPipe_BufLenAdd( pipe, write_remains ); // atomic
		pipe->write_pos = 0;
	} else if( cmd_size > write_remains ) {
		int *cmd;

		while( pipe->cmdbuf_len + sizeof( int ) + cmd_size + write_remains > pipe->bufSize ) {
			if( pipe->blockWrite ) {
				QThread_Yield();
				continue;
			}
			return;
		}

		// explicit pointer reset cmd
		cmd = QBufPipe_AllocCmd( pipe, sizeof( int ) );
		*cmd = -1;

		QBufPipe_BufLenAdd( pipe, sizeof( *cmd ) + write_remains ); // atomic
		pipe->write_pos = 0;
	}
	else
	{
		while( pipe->cmdbuf_len + cmd_size > pipe->bufSize ) {
			if( pipe->blockWrite ) {
				QThread_Yield();
				continue;
			}
			return;
		}
	}

	buf = QBufPipe_AllocCmd( pipe, cmd_size );
	memcpy( buf, cmd, cmd_size );
	QBufPipe_BufLenAdd( pipe, cmd_size ); // atomic

	// wake the other thread waiting for signal
	if( was_empty ) {
		QMutex_Lock( pipe->nonempty_mutex );
		QBufPipe_Wake( pipe );
		QMutex_Unlock( pipe->nonempty_mutex );
	}
}