home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************
- File: PIPE.CPP Copyright 1989 by Dlugosz Software
- Pipes for the C++ multitasking system
- *****************************************************/
-
- #include "usual.hpp"
- #include "task.hpp"
- #include "sem.hpp"
- #include "pipe.hpp"
- #include <string.h>
- //need memcpy()
-
- /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
-
- pipe::pipe (void* buf, unsigned size)
- : suspend(0)
- {
- buffer= buf;
- bufsize= room= size;
- dynamic= FALSE;
- writepos= readpos= 0;
- }
-
- /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
-
- pipe::pipe (unsigned size)
- : suspend(0)
- {
- buffer= new byte[size];
- bufsize= room= size;
- dynamic= TRUE;
- writepos= readpos= 0;
- }
-
- /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
-
- pipe::~pipe()
- {
- /* I've got to be careful destroying a pipe. Another task may be using
- the pipe at this moment. So, I need an exclusine lock. Any other
- task using the pipe will be waiting at a semaphore, which will then
- return errors. */
- if (! --in_use) return; //already destroyed
- if (dynamic) delete buffer;
- // semaphores destroyed automatically
- }
-
- /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
-
- bool pipe::send (void* data, unsigned size)
- {
- if (! --writer) return FALSE; //get exclusive access to write
- /* I am now the only writer in the system, but someone may be
- reading at this very moment. */
- if (! --in_use) return FALSE;
- // I am now the only one using this pipe.
- while (size) { //stuff left to be written
- if (size <= room) { //it all fits
- put (data, size);
- if (int(suspend) < 0) suspend++;
- //tell any suspended reader to continue
- in_use++; //signal any waiting reader to go ahead
- writer++; //let the next writer in
- return TRUE; //mission complete!
- }
- else { //have to do it piece-wise, co-ordinating with a reader
- if (room) {
- unsigned temp= room; //put() changes room.
- put (data, room); //as much as will fit
- size -= temp;
- data= temp + (byte*)data; //where I left off
- if (int(suspend) < 0) suspend++;
- }
- in_use++; //signal any waiting reader to go ahead
- if (!suspend--) return FALSE; //wait for signal from reader to continue
- // and loop back to the beginning
- }
- }
- }
-
- /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
-
- bool pipe::receive (void* buffer, unsigned size)
- {
- if (! --reader) return FALSE; //get exclusive access to read
- if (! --in_use) return FALSE;
- // I am now the only one using this pipe
- while (size) {
- unsigned stuff= bufsize - room; //how much is in the buffer
- if (stuff >= size) { //enough available
- get (buffer, size);
- if (int(suspend) < 0) suspend++;
- //tell any suspended writer to continue
- in_use++; //signal any waiting writer to go ahead
- reader++; //let the next reader in
- return TRUE;
- }
- else { //do it piece-wise
- if (stuff) {
- get (buffer, stuff); //take everything
- size -= stuff;
- buffer= stuff + (byte*) buffer;
- if (int(suspend) < 0) suspend++;
- }
- in_use++; //signal waiting writer to go ahead with more
- if (!suspend--) return FALSE; //wait for signal from writer
- //loop back to read more
- }
- }
- }
-
- /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
- /* primitive circular queue functions */
- /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
-
- void pipe::get (void* buf, unsigned size)
- {
- /* get 'size' bytes from the pipe's buffer. It does not need a
- return value since the caller (receive()) never askes for more
- then there is. */
- unsigned firsthalf= bufsize-readpos; //how much before 'wrap around'
- if (firsthalf < size) { //I'll need to wrap around
- //get to the end first
- memcpy (buf, buffer+readpos, firsthalf);
- buf= firsthalf+(byte*)buf;
- size -= firsthalf;
- room += firsthalf;
- readpos= 0; //wrap to the beginning
- }
- memcpy (buf, buffer+readpos, size);
- room += size;
- readpos += size;
- }
-
- /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
-
- void pipe::put (void* buf, unsigned size)
- {
- unsigned firsthalf= bufsize-writepos; //how much before 'wrap around'
- if (firsthalf < size) { //I'll need to wrap around
- memcpy (buffer+writepos, buf, firsthalf);
- buf= firsthalf+(byte*)buf;
- size -= firsthalf;
- room -= firsthalf;
- writepos= 0;
- }
- memcpy (buffer+writepos, buf, size);
- room -= size;
- writepos += size;
- }
-
- /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
-
-