root/lang/c/picoev/trunk/picoev_select.c @ 35109

Revision 35109, 4.5 kB (checked in by mattn, 5 years ago)

oops!

Line 
1/*
2 * Copyright (c) 2009, Cybozu Labs, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 *   this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 *   this list of conditions and the following disclaimer in the documentation
12 *   and/or other materials provided with the distribution.
13 * * Neither the name of the <ORGANIZATION> nor the names of its contributors
14 *   may be used to endorse or promote products derived from this software
15 *   without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#ifndef _WIN32
31# include <sys/select.h>
32#else
33# include <ws2tcpip.h>
34#endif
35
36#include "picoev.h"
37
38#ifdef _WIN32
39# define PICOEV_W32_INTERNAL
40# include "picoev_w32.h"
41# define PICOEV_FD_SET(x, y) FD_SET(picoev_w32_fd2sock(x), y)
42# define PICOEV_FD_ISSET(x, y) FD_ISSET(picoev_w32_fd2sock(x), y)
43
44typedef struct picoev_w32_globals_st {
45  int* fds;
46  void* _fds_free_addr;
47} picoev_w32_globals;
48
49picoev_w32_globals picoev_w32;
50
51int picoev_w32_sock2fd(int sock) {
52  int i;
53  for (i = 0; i < picoev.max_fd && picoev_w32.fds[i]; ++i)
54    if (picoev_w32.fds[i] == sock) return i;
55  assert(PICOEV_IS_INITED_AND_FD_IN_RANGE(i));
56  picoev_w32.fds[i] = sock;
57  return i;
58}
59
60int picoev_w32_fd2sock(int fd) {
61  assert(PICOEV_IS_INITED_AND_FD_IN_RANGE(fd));
62  return picoev_w32.fds[fd];
63}
64
65extern int picoev_w32_deinit(void);
66
67int picoev_w32_init(int max_fd) {
68  int r = picoev_init(max_fd);
69  if ((picoev_w32.fds = (int*)picoev_memalign(sizeof(int) * max_fd,
70                                                &picoev_w32._fds_free_addr, 1))
71        == NULL) {
72    picoev_deinit();
73    return -1;
74  }
75}
76
77int picoev_w32_deinit(void) {
78  free(picoev_w32._fds_free_addr);
79  picoev_w32.fds = NULL;
80  picoev_w32._fds_free_addr = NULL;
81  return picoev_deinit();
82}
83
84#else
85# define PICOEV_FD_SET(x, y) FD_SET(x, y)
86# define PICOEV_FD_ISSET(x, y) FD_ISSET(x, y)
87#endif
88
89picoev_globals picoev;
90
91picoev_loop* picoev_create_loop(int max_timeout)
92{
93  picoev_loop* loop;
94 
95  assert(PICOEV_IS_INITED);
96  if ((loop = (picoev_loop*)malloc(sizeof(picoev_loop))) == NULL) {
97    return NULL;
98  }
99  if (picoev_init_loop_internal(loop, max_timeout) != 0) {
100    free(loop);
101    return NULL;
102  }
103 
104  return loop;
105}
106
107int picoev_destroy_loop(picoev_loop* loop)
108{
109  picoev_deinit_loop_internal(loop);
110  free(loop);
111  return 0;
112}
113
114int picoev_update_events_internal(picoev_loop* loop, int fd, int events)
115{
116  picoev.fds[fd].events = events & PICOEV_READWRITE;
117  return 0;
118}
119
120int picoev_poll_once_internal(picoev_loop* loop, int max_wait)
121{
122  fd_set readfds, writefds, errorfds;
123  struct timeval tv;
124  int i, r, maxfd = 0;
125 
126  /* setup */
127  FD_ZERO(&readfds);
128  FD_ZERO(&writefds);
129  FD_ZERO(&errorfds);
130  for (i = 0; i < picoev.max_fd; ++i) {
131    picoev_fd* fd = picoev.fds + i;
132    if (fd->loop_id == loop->loop_id) {
133      if ((fd->events & PICOEV_READ) != 0) {
134        PICOEV_FD_SET(i, &readfds);
135        if (maxfd < i) {
136          maxfd = i;
137        }
138      }
139      if ((fd->events & PICOEV_WRITE) != 0) {
140        PICOEV_FD_SET(i, &writefds);
141        if (maxfd < i) {
142          maxfd = i;
143        }
144      }
145    }
146  }
147 
148  /* select and handle if any */
149  tv.tv_sec = max_wait;
150  tv.tv_usec = 0;
151  r = select(maxfd + 1, &readfds, &writefds, &errorfds, &tv);
152  if (r == -1) {
153    return -1;
154  } else if (r > 0) {
155    for (i = 0; i < picoev.max_fd; ++i) {
156      picoev_fd* target = picoev.fds + i;
157      if (target->loop_id == loop->loop_id) {
158        int revents = (PICOEV_FD_ISSET(i, &readfds) ? PICOEV_READ : 0)
159          | (PICOEV_FD_ISSET(i, &writefds) ? PICOEV_WRITE : 0);
160        if (revents != 0) {
161          (*target->callback)(loop, i, revents, target->cb_arg);
162        }
163      }
164    }
165  }
166 
167  return 0;
168}
Note: See TracBrowser for help on using the browser.