source: muxevents.c @ afbf668

barnowl_perlaimdebianowlrelease-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since afbf668 was afbf668, checked in by Erik Nygren <nygren@mit.edu>, 17 years ago
pexec will now incrimentally display data as it is output by the child process. Additionally, commands running under pexec may now be killed by quitting out of the popless window. Added muxevents select loop dispatcher. File descriptors may be registered with muxevents and handlers will be dispatched to when data is available for non-blocking read/write/except. Switched the stderr_redir stuff to use muxevents.
  • Property mode set to 100644
File size: 3.4 KB
Line 
1#include <sys/poll.h>
2#include <sys/time.h>
3#include <sys/types.h>
4#include <unistd.h>
5#include "owl.h"
6
7static const char fileIdent[] = "$Id $";
8
9#define OWL_MUX_MAX_FD (FD_SETSIZE-1)
10
11static int owl_mux_nexthandle = 5000; /* next handle to hand out */
12static int owl_mux_needgc = 0;  /* number of muxevents needing to be gc'd */
13
14/* returns a handle id or 0 on failure */
15int owl_muxevents_add(owl_muxevents *muxevents, int fd, int eventmask, void (*handler_fn)(int handle, int fd, int eventmask, void *data), void *data) {
16  owl_mux *mux;
17 
18  mux = owl_malloc(sizeof(owl_mux));
19  if (!mux) return 0;
20  if (fd > OWL_MUX_MAX_FD) {
21    owl_function_error("owl_muxevents_add: fd %d too large", fd);
22    return 0;
23  }
24  mux->handle = owl_mux_nexthandle++;
25  mux->fd = fd;
26  mux->active = 1;
27  mux->eventmask = eventmask;
28  mux->data = data;
29  mux->handler_fn = handler_fn;
30  if (0!=owl_list_append_element(muxevents, mux)) {
31    owl_free(mux);
32    return(0);
33  }
34  return mux->handle;
35}
36
37/* deactivates a muxevent entry with the given handle */
38void owl_muxevents_remove(owl_muxevents *muxevents, int handle) {
39  int max, i;
40  owl_mux *m;
41
42  max = owl_list_get_size(muxevents);
43  for (i=0; i<max; i++) {
44    m = (owl_mux*)owl_list_get_element(muxevents, i);
45    if (m->handle == handle) {
46      m->active=0;
47      owl_mux_needgc++;
48    }
49  }
50}
51
52/* cleans up a muxevents list at a safe time (ie, when it is
53   not being traversed). */
54void owl_muxevents_gc(owl_muxevents *muxevents) {
55  int max, i, done=0;
56  owl_mux *m;
57
58  if (!owl_mux_needgc) return;
59  while (!done) {
60    max = owl_list_get_size(muxevents);
61    for (i=0; i<max; i++) {
62      m = (owl_mux*)owl_list_get_element(muxevents, i);
63      if (!m->active) {
64        owl_list_remove_element(muxevents, i);
65        owl_free(m);
66        owl_mux_needgc--;
67        break;
68      }
69    } 
70    if (i==max) done=1;
71  }
72}
73
74/* dispatches out events */
75void owl_muxevents_dispatch(owl_muxevents *muxevents, int timeout_usec) {
76  int nevents, i, rv, emask;
77  owl_mux *m;
78  fd_set rfds, wfds, efds;
79  int maxfd=0;
80  struct timeval tv;
81
82  FD_ZERO(&rfds);
83  FD_ZERO(&wfds);
84  FD_ZERO(&efds);
85  nevents = owl_list_get_size(muxevents);
86  for (i=0; i<nevents; i++) {
87      m = (owl_mux*)owl_list_get_element(muxevents, i);
88      if (m->eventmask & OWL_MUX_READ)   FD_SET(m->fd, &rfds);
89      if (m->eventmask & OWL_MUX_WRITE)  FD_SET(m->fd, &wfds);
90      if (m->eventmask & OWL_MUX_EXCEPT) FD_SET(m->fd, &efds);
91      if (m->fd > maxfd) maxfd = m->fd;
92  }
93  tv.tv_sec = 0;
94  tv.tv_usec = timeout_usec;
95  rv = select(maxfd+1, &rfds, &wfds, &efds, &tv);
96  if (rv == 0) return;
97 
98  for (i=0; i<nevents; i++) {
99      m = (owl_mux*)owl_list_get_element(muxevents, i);
100      if (!m->active) continue;
101      emask = 0;
102      if (m->eventmask & OWL_MUX_READ && FD_ISSET(m->fd, &rfds)) {
103        emask |= OWL_MUX_READ;
104      }
105      if (m->eventmask & OWL_MUX_WRITE && FD_ISSET(m->fd, &wfds)) {
106        emask |= OWL_MUX_WRITE;
107      }
108      if (m->eventmask & OWL_MUX_EXCEPT && FD_ISSET(m->fd, &efds)) {
109        emask |= OWL_MUX_EXCEPT;
110      }
111      owl_function_debugmsg("muxevents: dispatching %s%s%s to %d\n",
112                            emask&OWL_MUX_READ?"[read]":"",
113                            emask&OWL_MUX_WRITE?"[write]":"",
114                            emask&OWL_MUX_EXCEPT?"[except]":"",
115                            m->fd);
116      if (emask) {
117        m->handler_fn(m->handle, m->fd, emask, m->data);
118      }
119  }
120
121  owl_function_debugmsg("muxevents: finishing dispatch\n");
122  /* we need to do this here so that the size of muxevents
123  * doesn't change while we're traversing it... */
124  owl_muxevents_gc(muxevents);
125}
126
127
Note: See TracBrowser for help on using the repository browser.