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

wvistreamlist.cc

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

Generated on Sat Feb 21 21:05:29 2004 for WvStreams by doxygen 1.3.5