From 6c18a877843879c8cb7cf83d34a803e5310e6120 Mon Sep 17 00:00:00 2001 From: Miles Bader Date: Tue, 15 Aug 1995 17:45:43 +0000 Subject: (struct pipe): Keep separate ref counts for readers and writers. (pipe_aquire_reader, pipe_aquire_writer): New functions. (pipe_release_reader, pipe_release_writer): New functions. (pipe_add_reader, pipe_add_writer): New functions. (pipe_remove_reader, pipe_remove_writer): New functions. (_pipe_first_writer): New function decl. (_pipe_no_writers, _pipe_no_writers): New function decl. (pipe_aquire, pipe_release): Function deleted. (pipe_break): Function decl deleted. --- libpipe/pipe.h | 87 +++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 74 insertions(+), 13 deletions(-) (limited to 'libpipe') diff --git a/libpipe/pipe.h b/libpipe/pipe.h index f24a2ca4..005a1873 100644 --- a/libpipe/pipe.h +++ b/libpipe/pipe.h @@ -63,7 +63,7 @@ struct pipe deallocated (say by socket_shutdown), it doesn't actually go away until the reader realizes what happened. It is normally frobbed using pipe_aquire & pipe_release, which do locking as well.. */ - unsigned refs; + unsigned readers, writers; /* Various flags, from PIPE_* below. */ unsigned flags; @@ -152,35 +152,96 @@ pipe_wait (struct pipe *pipe, int noblock, int data_only) /* Wake up all threads waiting on PIPE, which should be locked. */ void pipe_kick (struct pipe *pipe); - + /* Creates a new pipe of class CLASS and returns it in RESULT. */ error_t pipe_create (struct pipe_class *class, struct pipe **pipe); /* Free PIPE and any resources it holds. */ void pipe_free (struct pipe *pipe); + +/* Take any actions necessary when PIPE aquires its first writer. */ +void _pipe_first_writer (struct pipe *pipe); + +/* Take any actions necessary when PIPE's last reader has gone away. PIPE + should be locked. */ +void _pipe_no_readers (struct pipe *pipe); + +/* Take any actions necessary when PIPE's last writer has gone away. PIPE + should be locked. */ +void _pipe_no_writers (struct pipe *pipe); -/* Discard a reference to PIPE, which should be unlocked, being sure to make - users aware of this. */ -void pipe_break (struct pipe *pipe); +/* Lock PIPE and increment its readers count. */ +extern inline void +pipe_aquire_reader (struct pipe *pipe) +{ + mutex_lock (&pipe->lock); + pipe->readers++; +} -/* Lock PIPE and increment its ref count. */ +/* Lock PIPE and increment its writers count. */ extern inline void -pipe_aquire (struct pipe *pipe) +pipe_aquire_writer (struct pipe *pipe) { mutex_lock (&pipe->lock); - pipe->refs++; + if (pipe->writers++ == 0) + _pipe_first_writer (pipe); } -/* Decrement PIPE's (which should be locked) ref count and unlock it. If the - ref count goes to zero, PIPE will be destroyed. */ +/* Decrement PIPE's (which should be locked) reader count and unlock it. If + there are no more refs to PIPE, it will be destroyed. */ extern inline void -pipe_release (struct pipe *pipe) +pipe_release_reader (struct pipe *pipe) { - if (--pipe->refs == 0) - pipe_free (pipe); + if (--pipe->readers == 0) + _pipe_no_readers (pipe); else mutex_unlock (&pipe->lock); } + +/* Decrement PIPE's (which should be locked) writer count and unlock it. If + there are no more refs to PIPE, it will be destroyed. */ +extern inline void +pipe_release_writer (struct pipe *pipe) +{ + if (--pipe->writers == 0) + _pipe_no_writers (pipe); + else + mutex_unlock (&pipe->lock); +} + +/* Increment PIPE's reader count. PIPE should be unlocked. */ +extern inline void +pipe_add_reader (struct pipe *pipe) +{ + pipe_aquire_reader (pipe); + mutex_unlock (&pipe->lock); +} + +/* Increment PIPE's writer count. PIPE should be unlocked. */ +extern inline void +pipe_add_writer (struct pipe *pipe) +{ + pipe_aquire_writer (pipe); + mutex_unlock (&pipe->lock); +} + +/* Decrement PIPE's (which should be unlocked) reader count and unlock it. If + there are no more refs to PIPE, it will be destroyed. */ +extern inline void +pipe_remove_reader (struct pipe *pipe) +{ + mutex_lock (&pipe->lock); + pipe_release_reader (pipe); +} + +/* Decrement PIPE's (which should be unlocked) writer count and unlock it. If + there are no more refs to PIPE, it will be destroyed. */ +extern inline void +pipe_remove_writer (struct pipe *pipe) +{ + mutex_lock (&pipe->lock); + pipe_release_writer (pipe); +} /* Empty out PIPE of any data. PIPE should be locked. */ extern inline void -- cgit v1.2.3