// 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_WIN32_COMPLETER_H #define HU_VARADIISTVAN_SCPL_IO_WIN32_COMPLETER_H //------------------------------------------------------------------------------ #include "../Failable.h" #include "Overlapped.h" #include "Overlappable.h" //------------------------------------------------------------------------------ namespace hu { namespace varadiistvan { namespace scpl { namespace io { //------------------------------------------------------------------------------ /** * Base class for objects that handle the completion of some * operation. They are associated with an Overlappable, and if that * overlappable is non-blocking (i.e. has a waiter), an Overlapped * object is created and stored in this object. */ class Completer : public FailableReference { protected: /** * The overlappable object this completer belongs to. */ Overlappable& overlappable; /** * The overlapped object. */ Overlapped* overlapped; protected: /** * Construct the completer for the given Overlappable. */ Completer(Overlappable* overlappable); /** * Destroy the completer. */ virtual ~Completer(); /** * Add the overlapped object (if any) to the given waiter. */ void addTo(Waiter* waiter); /** * Remove the overlapped object (if any) from the waiter it is * associated with. */ void removeFromWaiter(); /** * Determine if there is an overlapped object and it is being * waited for. */ bool isWaited() const; /** * Get the result of the overlapped operation, if any. * * @see Overlapped::getResult */ bool getResult(DWORD& size); /** * Check whether we are waiting for an overlapped result and if * so, return that. * * @param result will contain the result to return if we are * waiting for an overlapped result. * * @return whether we are waiting for an overlapped result */ bool checkWaitedResult(bool& result); /** * Handle the given result coming from an overlapped object. */ virtual void handleWaitedResult(DWORD size) = 0; private: /** * Get the failable object. */ const Failable& getFailable() const; /** * Get the failable object. */ Failable& getFailable(); friend class FailableReference; }; //------------------------------------------------------------------------------ // Inline definitions //------------------------------------------------------------------------------ inline Completer::Completer(Overlappable* overlappable) : overlappable(*overlappable), overlapped((overlappable->waiter==0) ? 0 : new Overlapped(*overlappable)) { } //------------------------------------------------------------------------------ inline Completer::~Completer() { delete overlapped; } //------------------------------------------------------------------------------ inline void Completer::addTo(Waiter* waiter) { if (overlapped!=0 && waiter!=0) overlapped->addTo(*waiter); } //------------------------------------------------------------------------------ inline void Completer::removeFromWaiter() { if (overlapped!=0) overlapped->removeFromWaiter(); } //------------------------------------------------------------------------------ inline bool Completer::isWaited() const { return overlapped!=0 && overlapped->isWaited(); } //------------------------------------------------------------------------------ inline bool Completer::getResult(DWORD& size) { return overlapped!=0 && overlapped->getResult(size, overlappable.handle); } //------------------------------------------------------------------------------ inline bool Completer::checkWaitedResult(bool& result) { if (!isWaited()) { return false; } DWORD size = 0; result = getResult(size); if (result) { removeFromWaiter(); handleWaitedResult(size); } else if (overlappable.failed()) { removeFromWaiter(); } return true; } //------------------------------------------------------------------------------ inline const Failable& Completer::getFailable() const { return overlappable; } //------------------------------------------------------------------------------ inline Failable& Completer::getFailable() { return overlappable; } //------------------------------------------------------------------------------ } /* namespace hu::varadiistvan::scpl::io */ } /* namespace hu::varadiistvan::scpl */ } /* namespace hu::varadiistvan */ } /* namespace hu */ //------------------------------------------------------------------------------ #endif // HU_VARADIISTVAN_SCPL_IO_WIN32_COMPLETER_H // Local Variables: // mode: C++ // c-basic-offset: 4 // indent-tabs-mode: nil // End: