jack1 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

162 lines
4.5KB

  1. // fakepoll.h
  2. // poll using select
  3. // Warning: a call to this poll() takes about 4K of stack space.
  4. // Greg Parker gparker-web@sealiesoftware.com December 2000
  5. // This code is in the public domain and may be copied or modified without
  6. // permission.
  7. // Updated May 2002:
  8. // * fix crash when an fd is less than 0
  9. // * set errno=EINVAL if an fd is greater or equal to FD_SETSIZE
  10. // * don't set POLLIN or POLLOUT in revents if it wasn't requested
  11. // in events (only happens when an fd is in the poll set twice)
  12. #ifndef _FAKE_POLL_H
  13. #define _FAKE_POLL_H
  14. #include <limits.h>
  15. #include <sys/types.h>
  16. #include <sys/time.h>
  17. #include <unistd.h>
  18. #include <stdlib.h>
  19. #include <errno.h>
  20. typedef struct pollfd {
  21. int fd; /* file desc to poll */
  22. short events; /* events of interest on fd */
  23. short revents; /* events that occurred on fd */
  24. } pollfd_t;
  25. // poll flags
  26. #define POLLIN 0x0001
  27. #define POLLOUT 0x0004
  28. #define POLLERR 0x0008
  29. // synonyms
  30. #define POLLNORM POLLIN
  31. #define POLLPRI POLLIN
  32. #define POLLRDNORM POLLIN
  33. #define POLLRDBAND POLLIN
  34. #define POLLWRNORM POLLOUT
  35. #define POLLWRBAND POLLOUT
  36. // ignored
  37. #define POLLHUP 0x0010
  38. #define POLLNVAL 0x0020
  39. inline int poll(struct pollfd *pollSet, int pollCount, int pollTimeout)
  40. {
  41. struct timeval tv;
  42. struct timeval *tvp;
  43. fd_set readFDs, writeFDs, exceptFDs;
  44. fd_set *readp, *writep, *exceptp;
  45. struct pollfd *pollEnd, *p;
  46. int selected;
  47. int result;
  48. int maxFD;
  49. if (!pollSet) {
  50. pollEnd = NULL;
  51. readp = NULL;
  52. writep = NULL;
  53. exceptp = NULL;
  54. maxFD = 0;
  55. }
  56. else {
  57. pollEnd = pollSet + pollCount;
  58. readp = &readFDs;
  59. writep = &writeFDs;
  60. exceptp = &exceptFDs;
  61. FD_ZERO(readp);
  62. FD_ZERO(writep);
  63. FD_ZERO(exceptp);
  64. // Find the biggest fd in the poll set
  65. maxFD = 0;
  66. for (p = pollSet; p < pollEnd; p++) {
  67. if (p->fd > maxFD) maxFD = p->fd;
  68. }
  69. if (maxFD >= FD_SETSIZE) {
  70. // At least one fd is too big
  71. errno = EINVAL;
  72. return -1;
  73. }
  74. // Transcribe flags from the poll set to the fd sets
  75. for (p = pollSet; p < pollEnd; p++) {
  76. if (p->fd < 0) {
  77. // Negative fd checks nothing and always reports zero
  78. } else {
  79. if (p->events & POLLIN) FD_SET(p->fd, readp);
  80. if (p->events & POLLOUT) FD_SET(p->fd, writep);
  81. if (p->events != 0) {
  82. FD_SET(p->fd, exceptp);
  83. }
  84. // POLLERR is never set coming in; poll() always reports errors
  85. // But don't report if we're not listening to anything at all.
  86. }
  87. }
  88. }
  89. // poll timeout is in milliseconds. Convert to struct timeval.
  90. // poll timeout == -1 : wait forever : select timeout of NULL
  91. // poll timeout == 0 : return immediately : select timeout of zero
  92. if (pollTimeout >= 0) {
  93. tv.tv_sec = pollTimeout / 1000;
  94. tv.tv_usec = (pollTimeout % 1000) * 1000;
  95. tvp = &tv;
  96. } else {
  97. tvp = NULL;
  98. }
  99. selected = select(maxFD+1, readp, writep, exceptp, tvp);
  100. if (selected < 0) {
  101. // Error during select
  102. result = -1;
  103. }
  104. else if (selected > 0) {
  105. // Select found something
  106. // Transcribe result from fd sets to poll set.
  107. // Also count the number of selected fds. poll returns the
  108. // number of ready fds; select returns the number of bits set.
  109. int polled = 0;
  110. for (p = pollSet; p < pollEnd; p++) {
  111. p->revents = 0;
  112. if (p->fd < 0) {
  113. // Negative fd always reports zero
  114. } else {
  115. if ((p->events & POLLIN) && FD_ISSET(p->fd, readp)) {
  116. p->revents |= POLLIN;
  117. }
  118. if ((p->events & POLLOUT) && FD_ISSET(p->fd, writep)) {
  119. p->revents |= POLLOUT;
  120. }
  121. if ((p->events != 0) && FD_ISSET(p->fd, exceptp)) {
  122. p->revents |= POLLERR;
  123. }
  124. if (p->revents) polled++;
  125. }
  126. }
  127. result = polled;
  128. }
  129. else {
  130. // selected == 0, select timed out before anything happened
  131. // Clear all result bits and return zero.
  132. for (p = pollSet; p < pollEnd; p++) {
  133. p->revents = 0;
  134. }
  135. result = 0;
  136. }
  137. return result;
  138. }
  139. #endif