// Copyright (c) 2013 by István Váradi // This file is part of VSCPL, a simple cross-platform utility library // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // 1. Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // The views and conclusions contained in the software and documentation are those // of the authors and should not be interpreted as representing official policies, // either expressed or implied, of the FreeBSD Project. #ifndef HU_VARADIISTVAN_SCPL_IO_BLOCKINGSTREAM_H #define HU_VARADIISTVAN_SCPL_IO_BLOCKINGSTREAM_H //------------------------------------------------------------------------------ #include "Failable.h" #include "BufferedStream.h" #include "WaitableEvent.h" #include //------------------------------------------------------------------------------ namespace hu { namespace varadiistvan { namespace scpl { namespace io { //------------------------------------------------------------------------------ /** * Wrapper for a buffered stream, which an event and provides * blocking, but interruptible read() and write() operations. * * The class is designed in a way, that it expects its constructed * instances to be called only from a single thread at a time, except * for the interrupt() function, which may be called from another * thread anytime. */ class BlockingStream : public Failable { private: /** * The buffered stream used. */ BufferedStream& stream; /** * The waitable event. */ WaitableEvent event; /** * Indicate if we are interrupted. */ bool interrupted; /** * The offset in the buffer of the reading stream. */ size_t readingOffset; /** * Indicate if the end-of-file has been reached while reading. */ bool eof; public: /** * Construct the blocking stream for the given buffered stream. * * The stream must have a waiter which is used for waiting. */ BlockingStream(BufferedStream& stream); /** * Determine if the stream has neither failed nor been * interrupted. */ operator bool() const; /** * Interrupt the stream. Pending or future read and write calls * will return indicating error. The isInterrupted() function can * be used to check if the stream was interrupted or not. */ void interrupt(); /** * Indicate if the stream is interrupted or not. */ bool isInterrupted(); /** * Read the given number of bytes into the given buffer. * * @return if the reading has succeeded */ bool read(void* dest, size_t length); /** * Skip the given number of bytes. */ bool skip(size_t length); /** * Write the given number of bytes from the given buffer. The data * may not be written to the underlying stream fully, so if you * want to make sure that it is sent, call flush() afterwards. * * @return true on success, false on error. */ bool write(const void* src, size_t length); /** * Flush anything written so far into the buffer, but not to the * underlying stream. * * @return whether the operation has succeeded. */ bool flush(); private: /** * Fill the buffer with data from the stream. */ bool fill(); /** * Check for the stream being interrupted. * * @return if the stream is interrupted, false otherwise */ bool checkInterrupted(); }; //------------------------------------------------------------------------------ // Inline definitions //------------------------------------------------------------------------------ inline BlockingStream::BlockingStream(BufferedStream& stream) : stream(stream), event(stream.getWaiter()), interrupted(false), readingOffset(0), eof(false) { } //------------------------------------------------------------------------------ inline BlockingStream::operator bool() const { return !failed() && !interrupted && !eof; } //------------------------------------------------------------------------------ inline void BlockingStream::interrupt() { event.fire(); } //------------------------------------------------------------------------------ inline bool BlockingStream::isInterrupted() { return interrupted; } //------------------------------------------------------------------------------ } /* namespace hu::varadiistvan::scpl::io */ } /* namespace hu::varadiistvan::scpl */ } /* namespace hu::varadiistvan */ } /* namespace hu */ //------------------------------------------------------------------------------ #endif // HU_VARADIISTVAN_SCPL_IO_BLOCKINGSTREAM_H // Local Variables: // mode: C++ // c-basic-offset: 4 // indent-tabs-mode: nil // End: