File: suio%2B%2B.h

package info (click to toggle)
sfs 1%3A0.5k-8
  • links: PTS
  • area: main
  • in suites: woody
  • size: 5,388 kB
  • ctags: 8,556
  • sloc: cpp: 43,410; ansic: 17,574; sh: 8,412; makefile: 771; yacc: 277; lex: 96; sed: 47
file content (267 lines) | stat: -rw-r--r-- 6,900 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
// -*-c++-*-
/* $Id: suio++.h,v 1.20 2001/02/10 18:18:53 dm Exp $ */

/*
 *
 * Copyright (C) 1998 David Mazieres (dm@uun.org)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 *
 */

#ifndef _ASYNC_SUIOXX_H_
#define _ASYNC_SUIOXX_H_ 1

#include "opnew.h"
#include "vec.h"
#include "callback.h"

class iovmgr {
  const iovec *iov;
  const iovec *lim;
  iovec cur;

public:
  iovmgr (const iovec *iov, int iovcnt);
  void skip (size_t);
  size_t copyout (char *, size_t);
  size_t size () const;
};

size_t iovsize (const iovec *, int);

class suio {
public:
  enum { smallbufsize = 0x80 };
  enum { blocksize = 0x2000 };

private:
  typedef callback<void>::ref cb_t;

  class uiocb {
    uiocb &operator= (const uiocb &);
  public:
    cb_t cb;
    u_int64_t nbytes;
    uiocb (u_int64_t nb, cb_t cb) : cb (cb), nbytes (nb) {}
  };

  vec<iovec, 4> iovs;
  vec<uiocb, 2> uiocbs;

  size_t uiobytes;
  u_int64_t nrembytes;
  u_int64_t nremiov;

  char *lastiovend;

  char *scratch_buf;
  char *scratch_pos;
  char *scratch_lim;

  suio (const suio &);
  suio &operator= (const suio &);

protected:
  void *(*allocator) (size_t);
  void (*deallocator) (void *, size_t);

  char defbuf[smallbufsize];

  static void *default_allocator (size_t n) { return txmalloc (n); }
  static void default_deallocator (void *p, size_t) { xfree (p); }

  void makeuiocbs ();
  char *morescratch (size_t);
  void pushiov (const void *base, size_t len);
  void slowcopy (const void *, size_t);
  void slowfill (char c, size_t n);

public:
  suio ();
  ~suio ();
  void clear ();

  char *getspace (size_t n);
  char *getspace_aligned (size_t n);
  void fill (char c, ssize_t n);
  void copy (const void *, size_t);
  void copyv (const iovec *iov, size_t cnt, size_t skip = 0);
  void copyu (const suio *uio) { copyv (uio->iov (), uio->iovcnt ()); }
  void print (const void *, size_t);
  void take (suio *src);
  void rembytes (size_t n);

  void iovcb (cb_t cb) {
    if (uiobytes)
      uiocbs.push_back (uiocb (nrembytes + uiobytes, cb));
    else
      (*cb) ();
  }
  void breakiov () { lastiovend = NULL; }

  const iovec *iov () const { return iovs.base (); }
  const iovec *iovlim () const { return iovs.lim (); }
  size_t iovcnt () const { return iovs.size (); }
  size_t resid () const { return uiobytes; }
  u_int64_t iovno () const { return nremiov; }
  u_int64_t byteno () const { return nrembytes; }

  int (output) (int fd, int cnt = -1);
  size_t copyout (void *buf, size_t len) const;
  size_t copyout (void *buf) const { return copyout (buf, (size_t) -1); }

  size_t fastspace () const { return scratch_lim - scratch_pos; }
  int (input) (int fd, size_t len = blocksize);
};

inline void
suio::pushiov (const void *_base, size_t len)
{
  void *base = const_cast<void *> (_base);
  if (base == lastiovend) {
    lastiovend += len;
    iovs.back ().iov_len += len;
  }
  else if (len) {
    iovec *iov = &iovs.push_back ();
    iov->iov_base = static_cast<iovbase_t> (base);
    iov->iov_len = len;
    lastiovend = static_cast<char *> (base) + len;
  }
  uiobytes += len;
  if (base == scratch_pos) {
    scratch_pos += len;
#ifdef CHECK_BOUNDS
    assert (scratch_pos <= scratch_lim);
#endif /* CHECK_BOUNDS */
  }
}

inline char *
suio::getspace (size_t n)
{
  if (n <= (size_t) (scratch_lim - scratch_pos))
    return scratch_pos;
  return morescratch (n);
}

inline char *
suio::getspace_aligned (size_t n)
{
  scratch_pos += - reinterpret_cast<size_t> (scratch_pos) & 3;
  return getspace (n);
}

inline void
suio::fill (char c, ssize_t n)
{
  if (n <= 0)
    return;
  if (n <= scratch_lim - scratch_pos) {
    memset (scratch_pos, c, n);
    pushiov (scratch_pos, n);
  }
  else
    slowfill (c, n);
}

inline void
suio::copy (const void *buf, size_t len)
{
  if (len <= (size_t) (scratch_lim - scratch_pos)) {
    memcpy (scratch_pos, buf, len);
    pushiov (scratch_pos, len);
  }
  else
    slowcopy (buf, len);
}

size_t iovsize (const iovec *, int);
inline void
iovscrub (const iovec *iov, int cnt)
{
  const iovec *end = iov + cnt;
  while (iov < end)
    bzero (iov->iov_base, iov->iov_len);
}

/* Suio_printcheck for debugging */

#ifdef DMALLOC
void __suio_printcheck (const char *, suio *, const void *, size_t);
void __suio_check (const char *, suio *, const void *, size_t);
#else /* !DMALLOC */
#define __suio_printcheck(line, uio, buf, len) (uio)->print (buf, len)
#endif /* !DMALLOC */

#define suio_printcheck(uio, buf, len) \
  __suio_printcheck (__FL__, uio, buf, len)


inline void
suio::print (const void *buf, size_t len)
{
#ifdef DMALLOC
  if (buf != scratch_pos)
    __suio_check ("suio::print", this, buf, len);
#endif /* DMALLOC */
  if (len <= smallbufsize && buf != scratch_pos)
    copy (buf, len);
  else
    pushiov (buf, len);
}

/* Printf */

#ifndef DSPRINTF_DEBUG
/* The uprintf functions build up uio structures based on format
 * strings.  String ("%s") arguments are NOT copied, so you must not
 * modify any strings passed in.  Also, a format string of '%m'
 * doesn't convert any arguments but is equivalent to '%s' with an
 * argument of strerror (errno).  (This is like syslog.)  */
extern void suio_vuprintf (struct suio *, const char *, va_list);
extern void suio_uprintf (struct suio *, const char *, ...)
     __attribute__ ((format (printf, 2, 3)));
#else /* DSPRINTF_DEBUG */
extern void __suio_vuprintf (const char *, struct suio *,
			     const char *, va_list);
#define suio_vuprintf(uio, fmt, ap) __suio_vuprintf (__FL__, uio, fmt, ap)
extern void __suio_uprintf (const char *, struct suio *, const char *, ...)
  __attribute__ ((format (printf, 3, 4)));
#define suio_uprintf(uio, args...) __suio_uprintf (__FL__, uio, args)
#endif /* DSPRINTF_DEBUG */

/* Compatibility */

#ifdef DMALLOC
char *__suio_flatten (const struct suio *, const char *, int);
#define suio_flatten(uio) __suio_flatten (uio, __FILE__, __LINE__)
#else /* !DMALLOC */
char *suio_flatten (const struct suio *);
#endif /* !DMALLOC */

#define suio_fill(uio, c, len) (uio)->fill (c, len)
#define suio_copy(uio, buf, len) (uio)->copy (buf, len)
#define suio_callback(uio, cb) (uio)->iovcb (cb)

inline void
suio_print (suio *uio, const void *buf, size_t len)
{
  uio->print (buf, len);
}

#endif /* !_ASYNC_SUIOXX_H_ */