Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

wvstreamlist.cc

Go to the documentation of this file.
00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  * 
00005  * WvStreamList holds a list of WvStream objects -- and its select() and
00006  * callback() functions know how to handle multiple simultaneous streams.
00007  */
00008 #include "wvstreamlist.h"
00009 
00010 // enable this to add some read/write trace messages (this can be VERY
00011 // verbose)
00012 #define STREAMTRACE 0
00013 #if STREAMTRACE
00014 # define TRACE(x, y...) fprintf(stderr, x, ## y)
00015 #else
00016 #ifndef _MSC_VER
00017 # define TRACE(x, y...)
00018 #else
00019 # define TRACE
00020 #endif
00021 #endif
00022 
00023 WvStreamList::WvStreamList()
00024 {
00025     auto_prune = true;
00026 }
00027 
00028 
00029 WvStreamList::~WvStreamList()
00030 {
00031     // nothing to do
00032 }
00033 
00034 
00035 bool WvStreamList::isok() const
00036 {
00037     return WvError::isok();  // only !isok() if we explicitly set an error
00038 }
00039 
00040 
00041 bool WvStreamList::pre_select(SelectInfo &si)
00042 {
00043     bool one_dead = false;
00044     SelectRequest oldwant;
00045     
00046     // usually because of WvTask, we might get here without having finished
00047     // the _last_ set of sure_thing streams...
00048     // 
00049     // FIXME: this isn't really a good fix.  It doesn't deal properly with
00050     // the case where a continue_selectable callback is called by someone
00051     // *other* than WvStreamList... eg. WvStreamClone calling its cloned
00052     // callback().
00053     // 
00054     // FIXME: this hack makes it so calling select() on this object from
00055     // its own callback always returns true.  This is why we can't apply
00056     // this hack inside WvStreamClone.
00057     if (running_callback)
00058         return true;
00059     
00060     sure_thing.zap();
00061     
00062     time_t alarmleft = alarm_remaining();
00063     if (alarmleft == 0)
00064         return true; // alarm has rung
00065     
00066     oldwant = si.wants;
00067     
00068     Iter i(*this);
00069     for (i.rewind(); i.next(); )
00070     {
00071         WvStream &s(*i);
00072         
00073         if (!s.isok())
00074         {
00075             one_dead = true;
00076             if (auto_prune)
00077                 i.xunlink();
00078             continue;
00079         }
00080         
00081         //if (si.wants.readable && inbuf.used() && inbuf.used() > queue_min)
00082         //    sure_thing.append(&s, false, i.link->id);
00083         
00084         if (s.isok() && s.pre_select(si))
00085             sure_thing.append(&s, false, i.link->id);
00086     }
00087 
00088     if (alarmleft >= 0 && (alarmleft < si.msec_timeout || si.msec_timeout < 0))
00089         si.msec_timeout = alarmleft;
00090     
00091     si.wants = oldwant;
00092     return one_dead || !sure_thing.isempty();
00093 }
00094 
00095 
00096 bool WvStreamList::post_select(SelectInfo &si)
00097 {
00098     bool one_dead = false;
00099     SelectRequest oldwant = si.wants;
00100     
00101     Iter i(*this);
00102     for (i.rewind(); i.cur() && i.next(); )
00103     {
00104         WvStream &s(*i);
00105         if (s.isok())
00106         {
00107             if (s.post_select(si))
00108                 sure_thing.append(&s, false, i.link->id);
00109         }
00110         else
00111             one_dead = true;
00112     }
00113     
00114     si.wants = oldwant;
00115     return one_dead || !sure_thing.isempty();
00116 }
00117 
00118 
00119 // distribute the callback() request to all children that select 'true'
00120 void WvStreamList::execute()
00121 {
00122     static int level = 0;
00123     const char *id;
00124     level++;
00125     
00126     WvStream::execute();
00127     
00128     TRACE("\n%*sList@%p: (%d sure) ", level, "", this, sure_thing.count());
00129     
00130     WvStreamListBase::Iter i(sure_thing);
00131     for (i.rewind(); i.next(); )
00132     {
00133 #if STREAMTRACE
00134         WvStreamListBase::Iter x(*this);
00135         if (!x.find(&i()))
00136             TRACE("Yikes! %p in sure_thing, but not in main list!\n",
00137                   i.cur());
00138 #endif
00139         WvStream &s(*i);
00140         
00141         id = i.link->id;
00142         TRACE("[%p:%s]", &s, id);
00143         
00144         i.xunlink();
00145         
00146         if (s.isok())
00147             s.callback();
00148         
00149         // list might have changed!
00150         i.rewind();
00151     }
00152     
00153     sure_thing.zap();
00154 
00155     level--;
00156     TRACE("[DONE %p]\n", this);
00157 }

Generated on Sat Mar 13 14:55:56 2004 for WvStreams by doxygen 1.3.6-20040222