You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by br...@apache.org on 2005/10/23 08:43:19 UTC

svn commit: r327756 - in /apr/apr/trunk: CHANGES include/apr_poll.h poll/unix/epoll.c

Author: brianp
Date: Sat Oct 22 23:43:17 2005
New Revision: 327756

URL: http://svn.apache.org/viewcvs?rev=327756&view=rev
Log:
Added an optional APR_POLLSET_NOCOPY flag for apr_pollset_create().
This flag prevents the pollset implementation from making an internal
copy of the descriptor object passed to apr_pollset_add().  Instead,
a pointer to the descriptor itself is registered as the client_data
for the underlying poll mechanism.  This saves the cost of a copy,
and in the case of the epoll-based implementation it eliminates the
O(n)-time loop that's otherwise needed in apr_pollset_remove() to
find and free the structure that contains a copy of the descriptor.

Note that, when an application creates a pollset using APR_POLLSET_NOCOPY,
the application must ensure that all descriptors passed to
apr_pollset_add() have sufficiently long lifetimes.

With this commit, the epoll-based implementation of apr_pollset
implements the APR_POLLSET_NOCOPY optimization.  The kqueue-based
implementation would benefit from the same optimization.

Modified:
    apr/apr/trunk/CHANGES
    apr/apr/trunk/include/apr_poll.h
    apr/apr/trunk/poll/unix/epoll.c

Modified: apr/apr/trunk/CHANGES
URL: http://svn.apache.org/viewcvs/apr/apr/trunk/CHANGES?rev=327756&r1=327755&r2=327756&view=diff
==============================================================================
--- apr/apr/trunk/CHANGES (original)
+++ apr/apr/trunk/CHANGES Sat Oct 22 23:43:17 2005
@@ -1,5 +1,9 @@
 Changes for APR 1.3.0
 
+  *) Add APR_POLLSET_NOCOPY option to apr_pollset API to eliminate
+     O(n)-time lookup in apr_pollset_remove() (currently implemented
+     only for epoll).  [Brian Pane]
+
   *) Add apr_file_buffer_set() and apr_file_buffer_size_get() functions
      to support variable buffer sizes with APR file handles.
      [Colm MacCarthaigh]

Modified: apr/apr/trunk/include/apr_poll.h
URL: http://svn.apache.org/viewcvs/apr/apr/trunk/include/apr_poll.h?rev=327756&r1=327755&r2=327756&view=diff
==============================================================================
--- apr/apr/trunk/include/apr_poll.h (original)
+++ apr/apr/trunk/include/apr_poll.h Sat Oct 22 23:43:17 2005
@@ -55,6 +55,7 @@
  * Pollset Flags
  */
 #define APR_POLLSET_THREADSAFE 0x001 /**< Adding or Removing a Descriptor is thread safe */
+#define APR_POLLSET_NOCOPY     0x002 /**< Descriptors passed to apr_pollset_create() are not copied */
 
 /** Used in apr_pollfd_t to determine what the apr_descriptor is */
 typedef enum { 

Modified: apr/apr/trunk/poll/unix/epoll.c
URL: http://svn.apache.org/viewcvs/apr/apr/trunk/poll/unix/epoll.c?rev=327756&r1=327755&r2=327756&view=diff
==============================================================================
--- apr/apr/trunk/poll/unix/epoll.c (original)
+++ apr/apr/trunk/poll/unix/epoll.c Sat Oct 22 23:43:17 2005
@@ -101,7 +101,8 @@
 
     *pollset = apr_palloc(p, sizeof(**pollset));
 #if APR_HAS_THREADS
-    if (flags & APR_POLLSET_THREADSAFE &&
+    if ((flags & APR_POLLSET_THREADSAFE) &&
+        !(flags & APR_POLLSET_NOCOPY) &&
         ((rv = apr_thread_mutex_create(&(*pollset)->ring_lock,
                                        APR_THREAD_MUTEX_DEFAULT,
                                        p) != APR_SUCCESS))) {
@@ -123,10 +124,11 @@
     apr_pool_cleanup_register(p, *pollset, backend_cleanup, backend_cleanup);
     (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
 
-    APR_RING_INIT(&(*pollset)->query_ring, pfd_elem_t, link);
-    APR_RING_INIT(&(*pollset)->free_ring, pfd_elem_t, link);
-    APR_RING_INIT(&(*pollset)->dead_ring, pfd_elem_t, link);
-
+    if (!(flags & APR_POLLSET_NOCOPY)) {
+        APR_RING_INIT(&(*pollset)->query_ring, pfd_elem_t, link);
+        APR_RING_INIT(&(*pollset)->free_ring, pfd_elem_t, link);
+        APR_RING_INIT(&(*pollset)->dead_ring, pfd_elem_t, link);
+    }
     return APR_SUCCESS;
 }
 
@@ -140,23 +142,28 @@
 {
     struct epoll_event ev;
     int ret = -1;
-    pfd_elem_t *elem;
+    pfd_elem_t *elem = NULL;
     apr_status_t rv = APR_SUCCESS;
 
-    pollset_lock_rings();
+    ev.events = get_epoll_event(descriptor->reqevents);
 
-    if (!APR_RING_EMPTY(&(pollset->free_ring), pfd_elem_t, link)) {
-        elem = APR_RING_FIRST(&(pollset->free_ring));
-        APR_RING_REMOVE(elem, link);
+    if (pollset->flags & APR_POLLSET_NOCOPY) {
+        ev.data.ptr = (void *)descriptor;
     }
     else {
-        elem = (pfd_elem_t *) apr_palloc(pollset->pool, sizeof(pfd_elem_t));
-        APR_RING_ELEM_INIT(elem, link);
-    }
-    elem->pfd = *descriptor;
+        pollset_lock_rings();
 
-    ev.events = get_epoll_event(descriptor->reqevents);
-    ev.data.ptr = elem;
+        if (!APR_RING_EMPTY(&(pollset->free_ring), pfd_elem_t, link)) {
+            elem = APR_RING_FIRST(&(pollset->free_ring));
+            APR_RING_REMOVE(elem, link);
+        }
+        else {
+            elem = (pfd_elem_t *) apr_palloc(pollset->pool, sizeof(pfd_elem_t));
+            APR_RING_ELEM_INIT(elem, link);
+        }
+        elem->pfd = *descriptor;
+        ev.data.ptr = elem;
+    }
     if (descriptor->desc_type == APR_POLL_SOCKET) {
         ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_ADD,
                         descriptor->desc.s->socketdes, &ev);
@@ -166,17 +173,23 @@
                         descriptor->desc.f->filedes, &ev);
     }
 
-    if (0 != ret) {
-        rv = APR_EBADF;
-        APR_RING_INSERT_TAIL(&(pollset->free_ring), elem, pfd_elem_t, link);
+    if (pollset->flags & APR_POLLSET_NOCOPY) {
+        if (0 != ret) {
+            rv = APR_EBADF;
+        }
     }
     else {
-        pollset->nelts++;
-        APR_RING_INSERT_TAIL(&(pollset->query_ring), elem, pfd_elem_t, link);
+        if (0 != ret) {
+            rv = APR_EBADF;
+            APR_RING_INSERT_TAIL(&(pollset->free_ring), elem, pfd_elem_t, link);
+        }
+        else {
+            pollset->nelts++;
+            APR_RING_INSERT_TAIL(&(pollset->query_ring), elem, pfd_elem_t, link);
+        }
+        pollset_unlock_rings();
     }
 
-    pollset_unlock_rings();
-
     return rv;
 }
 
@@ -188,8 +201,6 @@
     struct epoll_event ev;
     int ret = -1;
 
-    pollset_lock_rings();
-
     ev.events = get_epoll_event(descriptor->reqevents);
 
     if (descriptor->desc_type == APR_POLL_SOCKET) {
@@ -204,22 +215,26 @@
         rv = APR_NOTFOUND;
     }
 
-    if (!APR_RING_EMPTY(&(pollset->query_ring), pfd_elem_t, link)) {
-        for (ep = APR_RING_FIRST(&(pollset->query_ring));
-             ep != APR_RING_SENTINEL(&(pollset->query_ring),
-                                     pfd_elem_t, link);
-             ep = APR_RING_NEXT(ep, link)) {
-
-            if (descriptor->desc.s == ep->pfd.desc.s) {
-                APR_RING_REMOVE(ep, link);
-                APR_RING_INSERT_TAIL(&(pollset->dead_ring),
-                                     ep, pfd_elem_t, link);
-                break;
+    if (!(pollset->flags & APR_POLLSET_NOCOPY)) {
+        pollset_lock_rings();
+
+        if (!APR_RING_EMPTY(&(pollset->query_ring), pfd_elem_t, link)) {
+            for (ep = APR_RING_FIRST(&(pollset->query_ring));
+                 ep != APR_RING_SENTINEL(&(pollset->query_ring),
+                                         pfd_elem_t, link);
+                 ep = APR_RING_NEXT(ep, link)) {
+                
+                if (descriptor->desc.s == ep->pfd.desc.s) {
+                    APR_RING_REMOVE(ep, link);
+                    APR_RING_INSERT_TAIL(&(pollset->dead_ring),
+                                         ep, pfd_elem_t, link);
+                    break;
+                }
             }
         }
-    }
 
-    pollset_unlock_rings();
+        pollset_unlock_rings();
+    }
 
     return rv;
 }
@@ -247,11 +262,21 @@
         rv = APR_TIMEUP;
     }
     else {
-        for (i = 0; i < ret; i++) {
-            pollset->result_set[i] =
-                (((pfd_elem_t *) (pollset->pollset[i].data.ptr))->pfd);
-            pollset->result_set[i].rtnevents =
-                get_epoll_revent(pollset->pollset[i].events);
+        if (pollset->flags & APR_POLLSET_NOCOPY) {
+            for (i = 0; i < ret; i++) {
+                pollset->result_set[i] =
+                    *((apr_pollfd_t *) (pollset->pollset[i].data.ptr));
+                pollset->result_set[i].rtnevents =
+                    get_epoll_revent(pollset->pollset[i].events);
+            }
+        }
+        else {
+            for (i = 0; i < ret; i++) {
+                pollset->result_set[i] =
+                    (((pfd_elem_t *) (pollset->pollset[i].data.ptr))->pfd);
+                pollset->result_set[i].rtnevents =
+                    get_epoll_revent(pollset->pollset[i].events);
+            }
         }
 
         if (descriptors) {
@@ -259,12 +284,14 @@
         }
     }
 
-    pollset_lock_rings();
+    if (!(pollset->flags & APR_POLLSET_NOCOPY)) {
+        pollset_lock_rings();
 
-    /* Shift all PFDs in the Dead Ring to be Free Ring */
-    APR_RING_CONCAT(&(pollset->free_ring), &(pollset->dead_ring), pfd_elem_t, link);
+        /* Shift all PFDs in the Dead Ring to be Free Ring */
+        APR_RING_CONCAT(&(pollset->free_ring), &(pollset->dead_ring), pfd_elem_t, link);
 
-    pollset_unlock_rings();
+        pollset_unlock_rings();
+    }
 
     return rv;
 }