implemented base class for I/O objects
Stefan Schuermans

Stefan Schuermans commited on 2011-10-25 18:34:13
Showing 4 changed files, with 170 additions and 0 deletions.

... ...
@@ -0,0 +1,89 @@
1
+/* Blinker
2
+   Copyright 2011 Stefan Schuermans <stefan@blinkenarea.org>
3
+   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4
+   a blinkenarea.org project */
5
+
6
+#include <set>
7
+#include <sys/select.h>
8
+
9
+#include "Io.h"
10
+#include "Time.h"
11
+
12
+namespace Blinker {
13
+
14
+/**
15
+ * @brief wait for I/O events
16
+ * @param[in] read I/O objects to check for readability
17
+ * @param[out] read I/O objects that are readable
18
+ * @param[in] write I/O objects to check for writability
19
+ * @param[out] write I/O objects that are writable
20
+ * @param[in] timeout maximum time to wait
21
+ */
22
+void Io::wait(Set &read, Set &write, const Time &timeout)
23
+{
24
+  // get maximum file descriptor, read set and write set
25
+  int max = 0;
26
+  fd_set fd_rd;
27
+  FD_ZERO(&fd_rd);
28
+  for (Set::const_iterator it = read.begin(); it != read.end(); ++it) {
29
+    if ((*it)->m_fd > max)
30
+      max = (*it)->m_fd;
31
+    FD_SET((*it)->m_fd, &fd_rd);
32
+  }
33
+  fd_set fd_wr;
34
+  FD_ZERO(&fd_wr);
35
+  for (Set::const_iterator it = write.begin(); it != write.end(); ++it) {
36
+    if ((*it)->m_fd > max)
37
+      max = (*it)->m_fd;
38
+    FD_SET((*it)->m_fd, &fd_wr);
39
+  }
40
+
41
+  // get timeout
42
+  struct timeval to;
43
+  timeout.toTimeval(to);
44
+
45
+  // wait for I/O event
46
+  fd_set fd_err;
47
+  FD_ZERO(&fd_err);
48
+  int res = select(max + 1, &fd_rd, &fd_wr, &fd_err, &to);
49
+
50
+  // error or timeout
51
+  if (res <= 0) {
52
+    // return with empty sets
53
+    read.clear();
54
+    write.clear();
55
+    return;
56
+  }
57
+
58
+  // remove file descriptors without event pending from sets
59
+  Set::iterator it;
60
+  it = read.begin();
61
+  while (it != read.end()) {
62
+    if (FD_ISSET((*it)->m_fd, &fd_rd)) {
63
+      ++it;
64
+    } else {
65
+      Set::iterator del = it;
66
+      ++it;
67
+      read.erase(del);
68
+    }
69
+  } // while it
70
+  it = write.begin();
71
+  while (it != write.end()) {
72
+    if (FD_ISSET((*it)->m_fd, &fd_wr)) {
73
+      ++it;
74
+    } else {
75
+      Set::iterator del = it;
76
+      ++it;
77
+      write.erase(del);
78
+    }
79
+  } // while it
80
+}
81
+
82
+/// constructor
83
+Io::Io():
84
+  m_fd(-1)
85
+{
86
+}
87
+
88
+} // namespace Blinker
89
+
... ...
@@ -0,0 +1,51 @@
1
+/* Blinker
2
+   Copyright 2011 Stefan Schuermans <stefan@blinkenarea.org>
3
+   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4
+   a blinkenarea.org project */
5
+
6
+#ifndef IO_H
7
+#define IO_H
8
+
9
+#include <set>
10
+
11
+#include "Time.h"
12
+
13
+namespace Blinker {
14
+
15
+/// base class for I/O objects
16
+class Io
17
+{
18
+public:
19
+  /// set of I/O objects
20
+  typedef std::set<Io *> Set;
21
+
22
+public:
23
+  /**
24
+   * @brief wait for I/O events
25
+   * @param[in] read I/O objects to check for readability
26
+   * @param[out] read I/O objects that are readable
27
+   * @param[in] write I/O objects to check for writability
28
+   * @param[out] write I/O objects that are writable
29
+   * @param[in] timeout maximum time to wait
30
+   */
31
+  static void wait(Set &read, Set &write, const Time &timeout);
32
+
33
+public:
34
+  /// constructor
35
+  Io();
36
+
37
+private:
38
+  /// copy constructor disabled
39
+  Io(const Io &that);
40
+
41
+  /// assignment operator disabled
42
+  const Io & operator=(const Io &that);
43
+
44
+protected:
45
+  int m_fd; ///< file descriptor
46
+}; // class Io
47
+
48
+} // namespace Blinker
49
+
50
+#endif // #ifndef IO_H
51
+
... ...
@@ -159,6 +159,29 @@ time_t Time::toSec() const
159 159
     return m_sec;
160 160
 }
161 161
 
162
+/**
163
+ * @brief convert to struct timeval
164
+ * @param[out] tv struct timeval
165
+ */
166
+void Time::toTimeval(struct timeval &tv) const
167
+{
168
+  if (m_sec >= 0) {
169
+    tv.tv_sec = m_sec;
170
+    tv.tv_usec = (m_ns + 500) / 1000;
171
+    if (tv.tv_usec >= 1000000) {
172
+      ++tv.tv_sec;
173
+      tv.tv_usec -= 1000000;
174
+    }
175
+  } else {
176
+    tv.tv_sec = m_sec;
177
+    tv.tv_usec = -((-m_ns + 500) / 1000);
178
+    if (tv.tv_usec <= -1000000) {
179
+      --tv.tv_sec;
180
+      tv.tv_usec += 1000000;
181
+    }
182
+  }
183
+}
184
+
162 185
 /// fix internal time representation after calculation
163 186
 void Time::fix()
164 187
 {
... ...
@@ -7,6 +7,7 @@
7 7
 #define TIME_H
8 8
 
9 9
 #include <stdint.h>
10
+#include <sys/time.h>
10 11
 #include <time.h>
11 12
 
12 13
 namespace Blinker {
... ...
@@ -66,6 +67,12 @@ public:
66 67
    */
67 68
   time_t toSec() const;
68 69
 
70
+  /**
71
+   * @brief convert to struct timeval
72
+   * @param[out] tv struct timeval
73
+   */
74
+  void toTimeval(struct timeval &tv) const;
75
+
69 76
 public:
70 77
   /// sleep for duration
71 78
   void sleepFor() const;
72 79