[963] in BarnOwl Developers

home help back first fref pref prev next nref lref last post

[D-O-H] r950 - trunk/owl

daemon@ATHENA.MIT.EDU (asedeno@MIT.EDU)
Thu Oct 29 18:11:37 2009

Resent-From: nelhage@mit.edu
Resent-To: barnowl-dev-mtg@charon.mit.edu
X-Original-To: nelhage@nelhage.com
To: dirty-owl-hackers@mit.edu
From: asedeno@MIT.EDU
Reply-to: dirty-owl-hackers@MIT.EDU
Date: Mon, 18 Feb 2008 20:54:45 -0500 (EST)

Author: asedeno
Date: 2008-02-18 20:54:45 -0500 (Mon, 18 Feb 2008)
New Revision: 950

Added:
   trunk/owl/select.c
Log:
Merging in the select branch, part 2. select.c

Added: trunk/owl/select.c
===================================================================
--- trunk/owl/select.c	                        (rev 0)
+++ trunk/owl/select.c	2008-02-19 01:54:45 UTC (rev 950)
@@ -0,0 +1,242 @@
+#include "owl.h"
+
+static const char fileIdent[] = "$Id: select.c 894 2008-01-17 07:13:44Z asedeno $";
+
+/* Returns the index of the dispatch for the file descriptor. */
+int owl_select_find_dispatch(int fd)
+{
+  int i, len;
+  owl_list *dl;
+  owl_dispatch *d;
+  
+  dl = owl_global_get_dispatchlist(&g);
+  len = owl_list_get_size(dl);
+  for(i = 0; i < len; i++) {
+    d = (owl_dispatch*)owl_list_get_element(dl, i);
+    if (d->fd == fd) return i;
+  }
+  return -1;
+}
+
+/* Adds a new owl_dispatch to the list, replacing existing ones if needed. */
+void owl_select_add_dispatch(owl_dispatch *d)
+{
+  int elt;
+  owl_list *dl;
+
+  elt = owl_select_find_dispatch(d->fd);
+  dl = owl_global_get_dispatchlist(&g);
+  
+  if (elt != -1) {  /* If we have a dispatch for this FD */
+    owl_dispatch *d_old;
+    d_old = (owl_dispatch*)owl_list_get_element(dl, elt);
+    /* Ignore if we're adding the same dispatch again.  Otherwise
+       replace the old dispatch. */
+    if (d_old != d) {
+      owl_list_replace_element(dl, elt, d);
+      owl_free(d_old);
+    }
+  }
+  else {
+    owl_list_append_element(dl, d);
+  }
+}
+
+/* Removes an owl_dispatch to the list, based on it's file descriptor. */
+void owl_select_remove_dispatch(int fd)
+{
+  int elt;
+  owl_list *dl;
+
+  elt = owl_select_find_dispatch(fd);
+  dl = owl_global_get_dispatchlist(&g);
+  
+  if (elt != -1) {
+    owl_dispatch *d;
+    d = (owl_dispatch*)owl_list_get_element(dl, elt);
+    owl_list_remove_element(dl, elt);
+    if (d->pfunc) {
+      owl_perlconfig_dispatch_free(d);
+    }
+    owl_free(d);
+  }
+}
+
+int owl_select_dispatch_count()
+{
+  return owl_list_get_size(owl_global_get_dispatchlist(&g));
+}
+
+int owl_select_add_perl_dispatch(int fd, SV *cb)
+{
+  int elt;
+  owl_dispatch *d;
+  elt = owl_select_find_dispatch(fd);
+  if (elt != -1) {
+    d = (owl_dispatch*)owl_list_get_element(owl_global_get_dispatchlist(&g), elt);
+    if (d->pfunc == NULL) {
+      /* don't mess with non-perl dispatch functions from here. */
+      return 1;
+    }
+  }
+
+  d = malloc(sizeof(owl_dispatch));
+  d->fd = fd;
+  d->cfunc = NULL;
+  d->pfunc = cb;
+  owl_select_add_dispatch(d);
+  return 0;
+}
+
+int owl_select_remove_perl_dispatch(int fd)
+{
+  int elt;
+  owl_dispatch *d;
+  
+  elt = owl_select_find_dispatch(fd);
+  if (elt != -1) {
+    d = (owl_dispatch*)owl_list_get_element(owl_global_get_dispatchlist(&g), elt);
+    if (d->pfunc != NULL) {
+      owl_select_remove_dispatch(fd);
+      return 0;
+    }
+  }
+  return 1;
+}
+
+int owl_select_dispatch_prepare_fd_sets(fd_set *r, fd_set *w, fd_set *e)
+{
+  int i, len, max_fd;
+  owl_dispatch *d;
+  owl_list *dl;
+
+  dl = owl_global_get_dispatchlist(&g);
+  FD_ZERO(r);
+  FD_ZERO(e);
+  max_fd = 0;
+  len = owl_select_dispatch_count(g);
+  for(i = 0; i < len; i++) {
+    d = (owl_dispatch*)owl_list_get_element(dl, i);
+    FD_SET(d->fd, r);
+    FD_SET(d->fd, w);
+    FD_SET(d->fd, e);
+    if (max_fd < d->fd) max_fd = d->fd;
+  }
+  return max_fd + 1;
+}
+
+void owl_select_dispatch(fd_set *fds, int max_fd)
+{
+  int i, len;
+  owl_dispatch *d;
+  owl_list *dl;
+
+  dl = owl_global_get_dispatchlist(&g);
+  len = owl_select_dispatch_count();
+  for(i = 0; i < len; i++) {
+    d = (owl_dispatch*)owl_list_get_element(dl, i);
+    /* While d shouldn't normally be null, the list may be altered by
+     * functions we dispatch to. */
+    if (d != NULL && FD_ISSET(d->fd, fds)) {
+      if (d->cfunc != NULL) {
+        (d->cfunc)();
+      }
+      else if (d->pfunc != NULL) {
+        owl_perlconfig_do_dispatch(d);
+      }
+    }
+  }
+}
+
+int owl_select_aim_hack(fd_set *fds)
+{
+  aim_conn_t *cur;
+  aim_session_t *sess;
+  int max_fd;
+
+  FD_ZERO(fds);
+  max_fd = 0;
+  sess = owl_global_get_aimsess(&g);
+  for (cur = sess->connlist, max_fd = 0; cur; cur = cur->next) {
+    if (cur->fd != -1) {
+      FD_SET(cur->fd, fds);
+      if (cur->fd > max_fd)
+        max_fd = cur->fd;
+    }
+  }
+  cur = owl_global_get_bosconn(&g);
+  if (cur->fd != -1) {
+    FD_SET(cur->fd, fds);
+    if (cur->fd > max_fd)
+      max_fd = cur->fd;
+  }
+  
+  return max_fd;
+}
+
+void owl_select()
+{
+  int i, max_fd, aim_max_fd, aim_done;
+  fd_set r;
+  fd_set w;
+  fd_set e;
+  fd_set aim_fds;
+  struct timeval timeout;
+
+  timeout.tv_sec = 1;
+  timeout.tv_usec = 0;
+
+  max_fd = owl_select_dispatch_prepare_fd_sets(&r, &w, &e);
+
+  /* AIM HACK: 
+   *
+   *  The problem - I'm not sure where to hook into the owl/faim
+   *  interface to keep track of when the AIM socket(s) open and
+   *  close. In particular, the bosconn thing throws me off. So,
+   *  rather than register particular dispatchers for AIM, I look up
+   *  the relevant FDs and add them to select's watch lists, then
+   *  check for them individually before moving on to the other
+   *  dispatchers. --asedeno
+   */
+  aim_done = 1;
+  FD_ZERO(&aim_fds);
+  FD_ZERO(&w);
+  if (owl_global_is_doaimevents(&g)) {
+    aim_done = 0;
+    aim_max_fd = owl_select_aim_hack(&aim_fds);
+    if (max_fd < aim_max_fd) max_fd = aim_max_fd;
+    for(i = 0; i <= aim_max_fd; i++) {
+      if (FD_ISSET(i, &aim_fds)) {
+        FD_SET(i, &r);
+        FD_SET(i, &w); /* Yes, we're checking writable sockets
+                          here. Without it, AIM login is really
+                          slow. */
+        FD_SET(i, &e);
+      }
+    }
+  }
+  /* END AIM HACK */
+  
+  if ( select(max_fd, &r, &w, &e, &timeout) ) {
+    /* Merge fd_sets and clear AIM FDs. */
+    for(i = 0; i <= max_fd; i++) {
+      /* Merge all interesting FDs into one set, since we have a
+         single dispatch per FD. */
+      if (FD_ISSET(i, &r) || FD_ISSET(i, &w) || FD_ISSET(i, &e)) {
+        /* AIM HACK: no separate dispatch, just process here if
+           needed, and only once per run through. */
+        if (!aim_done && FD_ISSET(i, &aim_fds)) {
+          owl_process_aim();
+          aim_done = 1;
+        }
+        else {
+          FD_SET(i, &r);
+        }
+      }
+    }
+
+    /* NOTE: the same dispatch function is called for both exceptional
+       and read ready FDs. */
+    owl_select_dispatch(&r, max_fd);
+  }
+}


home help back first fref pref prev next nref lref last post