Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

StreamModule.cxx

00001 /*
00002  * Copyright (C) 1991-9 Eric M. Hopper <hopper@omnifarious.mn.org>
00003  * 
00004  *     This program is free software; you can redistribute it and/or modify it
00005  *     under the terms of the GNU Lesser General Public License as published
00006  *     by the Free Software Foundation; either version 2 of the License, or
00007  *     (at your option) any later version.
00008  * 
00009  *     This program is distributed in the hope that it will be useful, but
00010  *     WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  *     Lesser General Public License for more details.
00013  * 
00014  *     You should have received a copy of the GNU Lesser General Public
00015  *     License along with this program; if not, write to the Free Software
00016  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 /* $Header: /home/hopper/src/cvs/C++/StrMod/StreamModule.cxx,v 1.12 2002/03/12 21:48:57 hopper Exp $ */
00020 
00021 // For log information, see ChangeLog
00022 
00023 #ifdef __GNUG__
00024 #  pragma implementation "StreamModule.h"
00025 #endif
00026 
00027 #include "StrMod/StreamModule.h"
00028 #include "StrMod/StrChunkPtr.h"
00029 
00030 namespace strmod {
00031 namespace strmod {
00032 
00033 //! A unique identifier for this class.
00034 const STR_ClassIdent StreamModule::identifier(1UL);
00035 //! A unique identifier for this class.
00036 const STR_ClassIdent StreamModule::Plug::identifier(2UL);
00037 
00038 /*!
00039  * \param other A reference to the plug to plug into.  <strong>(A pointer to
00040  * it is stored)</strong>.
00041  *
00042  * A pointer to \a other will be stored by the plug until it's unplugged or
00043  * destroyed.  \a other is a reference because it's not allowed to be \c NULL.  */
00044 bool StreamModule::Plug::plugInto(Plug &other)
00045 {
00046    // Make sure neither plug is already plugged in.
00047    if ((other_ == NULL) && (other.other_ == NULL))
00048    {
00049       other_ = &other;
00050       other.other_ = this;
00051       flags_.notifyonread_ = other.needsNotifyReadable();
00052       other.flags_.notifyonread_ = needsNotifyReadable();
00053       flags_.notifyonwrite_ = other.needsNotifyWriteable();
00054       other.flags_.notifyonwrite_ = needsNotifyWriteable();
00055       notifyOtherReadable();
00056       if (other_ != NULL)
00057       {
00058          other_->notifyOtherReadable();
00059       }
00060       notifyOtherWriteable();
00061       if (other_ != NULL)
00062       {
00063          other_->notifyOtherWriteable();
00064       }
00065       if (isReadable() && (pluggedInto() != NULL))
00066       {
00067          pushLoop();
00068       }
00069       if (isWriteable() && (pluggedInto() != NULL))
00070       {
00071          pullLoop();
00072       }
00073       return(true);
00074    }
00075    else
00076    {
00077       return(false);
00078    }
00079 }
00080 
00081 /** \name Push and pulll loops
00082  * The loops that get everything done.
00083  *
00084  * Because of these loops, and the infrastructure that exists in the base
00085  * StreamModule and StreamModule::Plug class that calls them, you should never
00086  * have to call \c i_Read() or \c i_Write().
00087  *
00088  * These member functions are part of that infrastructure.  They handle
00089  * setting the \p iswriting_ and \p isreading_ flags properly.  They also loop
00090  * until no more data can be moved in the direction they're moving it because
00091  * one Plug became unwriteable, or one plug became unreadable.
00092  *
00093  * In short, don't bypass them unless you really know what you're doing.
00094  */
00095 //@{
00096 /*!
00097  * This keeps the isreading and iswriting flags set until the loop exits.
00098  *
00099  * This loop can exit for a number of reasons, including disconnection, one
00100  * side 'drying up' and having nothing to read, or one side 'filling up'
00101  * and not being able to be written to.
00102  */
00103 void StreamModule::Plug::pushLoop()
00104 {
00105    assert(isReadable() && (flags_.isreading_ == false));
00106 
00107    Plug *other = pluggedInto();
00108 
00109    assert(other != NULL);
00110 
00111    if (other != NULL && other->isWriteable())
00112    {
00113       other->setIsWriting(true);
00114    }
00115    setIsReading(true);
00116    while (flags_.canread_ && (other != NULL) && getFlagsFrom(*other).canwrite_)
00117    {
00118       other->i_Write(i_Read());
00119 
00120       if (pluggedInto() != other)
00121       {
00122          other->setIsWriting(false);
00123          other = pluggedInto();
00124          if (other != NULL && other->isWriteable())
00125          {
00126             other->setIsWriting(true);
00127          }
00128       }
00129    }
00130    setIsReading(false);
00131    if (other != NULL)
00132    {
00133       other->setIsWriting(false);
00134    }
00135 }
00136 
00137 /*!
00138  * This keeps the isreading and iswriting flags set until the loop exits.
00139  *
00140  * This loop can exit for a number of reasons, including disconnection, one
00141  * side 'drying up' and having nothing to read, or one side 'filling up' and
00142  * not being able to be written to.
00143  */
00144 void StreamModule::Plug::pullLoop()
00145 {
00146    assert(isWriteable() && (flags_.iswriting_ == false));
00147 
00148    Plug *other = pluggedInto();
00149 
00150    assert(other != NULL);
00151 
00152    setIsWriting(true);
00153    if (other != NULL && other->isReadable())
00154    {
00155       other->setIsReading(true);
00156    }
00157    while (flags_.canwrite_ && (other != NULL) && getFlagsFrom(*other).canread_)
00158    {
00159       i_Write(other->i_Read());
00160 
00161       if (pluggedInto() != other)
00162       {
00163          other->setIsReading(false);
00164          other = pluggedInto();
00165          if (other != NULL && other->isReadable())
00166          {
00167             other->setIsReading(true);
00168          }
00169       }
00170    }
00171    setIsWriting(false);
00172    if (other != NULL)
00173    {
00174       other->setIsReading(false);
00175    }
00176 }
00177 //@}
00178 
00179 }  // End namespace strmod
00180 }  // End namespace strmod

Generated on Wed Jan 29 00:32:44 2003 for libNet by doxygen1.3-rc1