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