CPN
Computational Process Networks
FileHandle.cc
Go to the documentation of this file.
1 //=============================================================================
2 // Computational Process Networks class library
3 // Copyright (C) 1997-2006 Gregory E. Allen and The University of Texas
4 //
5 // This library is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU Library General Public License as published
7 // by the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Library General Public License for more details.
14 //
15 // The GNU Public License is available in the file LICENSE, or you
16 // can write to the Free Software Foundation, Inc., 59 Temple Place -
17 // Suite 330, Boston, MA 02111-1307, USA, or you can find it on the
18 // World Wide Web at http://www.fsf.org.
19 //=============================================================================
24 #include "common_priv.h"
25 #include <cpn/io/FileHandle.h>
27 #include <sys/select.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <errno.h>
31 #include <algorithm>
32 
33 
35  fd_set rfd;
36  fd_set wfd;
37  FD_ZERO(&rfd);
38  FD_ZERO(&wfd);
39  int maxfd = 0;
40  IteratorRef<FileHandle*> itr = begin;
41  while (itr != end) {
42  FileHandle *han = *itr;
43  int fd = han->FD();
44  if (fd < 0) {
45  return -1;
46  } else {
47  bool set = false;
48  if (!han->Readable()) {
49  FD_SET(fd, &rfd);
50  set = true;
51  }
52  if (!han->Writeable()) {
53  FD_SET(fd, &wfd);
54  set = true;
55  }
56  if (set) { maxfd = std::max(maxfd, fd); }
57  }
58  ++itr;
59  }
60  timeval tv;
61  timeval *ptv = 0;
62  if (timeout >= 0) {
63  tv.tv_sec = (int)timeout;
64  tv.tv_usec = (int)((timeout - tv.tv_sec) * 1e6);
65  ptv = &tv;
66  }
67  int ret = select(maxfd + 1, &rfd, &wfd, 0, ptv);
68  if (ret < 0) {
69  if (errno == EINTR) {
70  return 0;
71  }
72  throw ErrnoException();
73  }
74  itr = begin;
75  while (itr != end) {
76  FileHandle *han = *itr;
77  int fd = han->FD();
78  if (fd >= 0) {
79  if (FD_ISSET(fd, &rfd)) {
80  han->OnReadable();
81  }
82  if (FD_ISSET(fd, &wfd)) {
83  han->OnWriteable();
84  }
85  }
86  ++itr;
87  }
88  return ret;
89 }
90 
92  : fd(-1), readable(false), writeable(true), eof(false)
93 {
94 }
95 
97  : fd(filed), readable(false), writeable(true), eof(false)
98 {
99 }
100 
102  if (fd != -1) { close(fd); }
103  Reset();
104 }
105 
106 int FileHandle::Poll(double timeout) {
107  FileHandle *fh = this;
108  return Poll(&fh, &fh + 1, timeout);
109 }
110 
111 void FileHandle::SetBlocking(bool blocking) {
112  SetBlocking(FD(), blocking);
113 }
114 
115 void FileHandle::SetBlocking(int fd, bool blocking) {
116  int flags = fcntl(fd, F_GETFL, 0);
117  if (-1 == flags) { throw ErrnoException(); }
118  if (blocking) {
119  flags &= ~O_NONBLOCK;
120  } else {
121  flags |= O_NONBLOCK;
122  }
123  if (fcntl(fd, F_SETFL, flags) != 0) {
124  throw ErrnoException();
125  }
126 }
127 
129  return IsBlocking(FD());
130 }
131 
133  int flags = fcntl(fd, F_GETFL, 0);
134  if (-1 == flags) { throw ErrnoException(); }
135  return !(flags & O_NONBLOCK);
136 }
137 
139  ALock al(file_lock);
140  readable = false;
141  writeable = false;
142  eof = false;
143  fd = -1;
144 }
145 
147  ALock al(file_lock);
148  if (fd != -1) {
149  if (close(fd) != 0) {
150  throw ErrnoException();
151  }
152  fd = -1;
153  }
154  readable = false;
155  writeable = false;
156  eof = false;
157 }
158 
159 unsigned FileHandle::Read(void *ptr, unsigned len) {
160  int filed;
161  {
162  ALock al(file_lock);
163  if (eof || fd == -1) { return 0; }
164  filed = fd;
165  }
166  unsigned bytesread = 0;
167  int num = read(filed, ptr, len);
168  if (num < 0) {
169  int error = errno;
170  switch (error) {
171  case EAGAIN:
172  Readable(false);
173  case EINTR:
174  case ENOMEM:
175  break;
176  default:
177  throw ErrnoException(error);
178  }
179  } else if (num == 0 && len != 0) {
180  ALock al(file_lock);
181  eof = true;
182  readable = false;
183  } else {
184  if (unsigned(num) < len) { Readable(false); }
185  bytesread = num;
186  }
187  return bytesread;
188 }
189 
190 unsigned FileHandle::Readv(const iovec *iov, int iovcnt) {
191  int filed;
192  {
193  ALock al(file_lock);
194  if (eof || fd == -1) { return 0; }
195  filed = fd;
196  }
197  unsigned len = 0;
198  for (int i = 0; i < iovcnt; ++i) {
199  len += iov[i].iov_len;
200  }
201  unsigned bytesread = 0;
202  int num = readv(filed, iov, iovcnt);
203  if (num < 0) {
204  int error = errno;
205  switch (error) {
206  case EAGAIN:
207  Readable(false);
208  case EINTR:
209  case ENOMEM:
210  break;
211  default:
212  throw ErrnoException(error);
213  }
214  } else if (num == 0 && len != 0) {
215  ALock al(file_lock);
216  eof = true;
217  readable = false;
218  } else {
219  if (unsigned(num) < len) { Readable(false); }
220  bytesread = num;
221  }
222  return bytesread;
223 }
224 
225 unsigned FileHandle::Write(const void *ptr, unsigned len) {
226  int filed;
227  {
228  ALock al(file_lock);
229  if (fd == -1) { return 0; }
230  filed = fd;
231  }
232  unsigned written = 0;
233  int num = write(filed, ptr, len);
234  if (num < 0) {
235  int error = errno;
236  switch (error) {
237  case EAGAIN: // Would block
238  //case EWOULDBLOCK:
239  Writeable(false);
240  case EINTR: // Returned because of signal
241  case ENOMEM:
242  case ENOBUFS: // Buffers are full
243  break;
244  case EPIPE:
245  case EBADF:
246  case EFAULT:
247  case EFBIG:
248  case EINVAL:
249  case EIO:
250  case ENOSPC:
251  default:
252  throw ErrnoException(error);
253  }
254  } else {
255  if (unsigned(num) < len) { Writeable(false); }
256  written = num;
257  }
258  return written;
259 }
260 
261 unsigned FileHandle::Writev(const iovec *iov, int iovcnt) {
262  int filed;
263  {
264  ALock al(file_lock);
265  if (fd == -1) { return 0; }
266  filed = fd;
267  }
268  unsigned written = 0;
269  int num = writev(filed, iov, iovcnt);
270  if (num < 0) {
271  int error = errno;
272  switch (error) {
273  case EAGAIN:
274  Writeable(false);
275  case EINTR:
276  case ENOMEM:
277  case ENOBUFS:
278  break;
279  default:
280  throw ErrnoException(error);
281  }
282  } else {
283  unsigned len = 0;
284  for (int i = 0; i < iovcnt; ++i) {
285  len += iov[i].iov_len;
286  }
287  if (unsigned(num) < len) { Writeable(false); }
288  written = num;
289  }
290  return written;
291 }
292 
294  if (fsync(FD()) != 0) {
295  throw ErrnoException();
296  }
297 }
298 
void Flush()
Tell the OS to flush any buffers it has. May not be supported for all file types. ...
Definition: FileHandle.cc:293
bool IsBlocking() const
Test if the current file is in blocking or non blocking mode.
Definition: FileHandle.cc:128
virtual void OnWriteable()
Called by Poll when it detects that the file is writeable.
Definition: FileHandle.h:212
bool writeable
Definition: FileHandle.h:216
bool Writeable(bool w)
Set that this file is currently writeable or not.
Definition: FileHandle.h:97
PthreadMutex file_lock
Definition: FileHandle.h:213
static int Poll(IteratorRef< FileHandle * > begin, IteratorRef< FileHandle * > end, double timeout)
poll a list of FileHandles for any activity and call the appropriate On method.
Definition: FileHandle.cc:34
void SetBlocking(bool blocking)
Manipulate how the current file handles blocking.
Definition: FileHandle.cc:111
void Close()
Close the file and reset the internal state.
Definition: FileHandle.cc:146
virtual ~FileHandle()
Close the file descriptor. Use Reset if one wants to not close the file descriptor.
Definition: FileHandle.cc:101
unsigned Writev(const iovec *iov, int iovcnt)
scatter gather io version of Write
Definition: FileHandle.cc:261
A class to make it easy to deal with file descriptors.
A reference to an iterator.
Definition: IteratorRef.h:46
FileHandle()
Construct a closed FileHandle.
Definition: FileHandle.cc:91
bool Writeable() const
Gives the current writability status of the file.
Definition: FileHandle.h:102
void Reset()
Clear all internal state including the file descriptor! WARNING does not close the file! ...
Definition: FileHandle.cc:138
int FD() const
Definition: FileHandle.h:106
bool Readable(bool r)
Set that the file is currently readable or not.
Definition: FileHandle.h:86
bool readable
Definition: FileHandle.h:215
bool Readable() const
Gives the current readability status of the file.
Definition: FileHandle.h:91
unsigned Readv(const iovec *iov, int iovcnt)
scatter gather io version of Read
Definition: FileHandle.cc:190
unsigned Read(void *ptr, unsigned len)
Read data from the file descriptor.
Definition: FileHandle.cc:159
Generic file handle could be a file, or a socket or a device.
Definition: FileHandle.h:41
virtual void OnReadable()
Called by Poll when it detects that the file is readable.
Definition: FileHandle.h:210
unsigned Write(const void *ptr, unsigned len)
Write data to the file descriptor.
Definition: FileHandle.cc:225