00001
00002
00003
00004
00005
00006
00007
00008 #include "wvistreamlist.h"
00009
00010 #ifndef _WIN32
00011 #include "wvfork.h"
00012 #endif
00013
00014
00015
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
00045 }
00046
00047
00048 bool WvIStreamList::isok() const
00049 {
00050 return true;
00051 }
00052
00053
00054 bool WvIStreamList::pre_select(SelectInfo &si)
00055 {
00056 bool one_dead = false;
00057 SelectRequest oldwant;
00058
00059
00060
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;
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
00086
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
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
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
00169 globallist.zap(false);
00170 }
00171 }
00172 #endif