[libdispatch-dev] Windows compatibility

Mark Heily mark at heily.com
Fri Sep 25 20:25:01 PDT 2009


Robert N. M. Watson wrote:
> 
> This is an interesting idea. My first thought was to look at whether 
> pthreads + libevent would provide a reasonable foundation for a 
> libnqkqueue ("not quite kqueue") wrapper library implementing (roughly) 
> the kqueue interface on non-supporting systems. There are some problems 
> with this idea, not least that libevent can't provided a unified event 
> source for some of the types of events supported by kqueue. On the other 
> hand, it would offer significantly more portability (at the cost of less 
> efficiency and fewer capabilities). 

APR and libevent aren't mutually exclusive. You could use APR to emulate 
pthreads on Windows, and libevent to emulate kqueue(2) on non-BSD systems.

You might also want to look at a library I wrote called pnotify. This 
provides a wrapper around BSD's kqueue and Linux's inotify to monitor 
filesystem events. The website is here:

	http://mark.heily.com/pnotify/

If portability to non-POSIX platforms is a goal, libevent doesn't provide 
any emulation of pthreads, so you would need something like APR.

Regards,

  - Mark


P.S. Here are my notes from examining libevent and APR and thinking about 
the requirements of libdispatch. Hope this is helpful.


Requirements for portability
---

In order to support non-POSIX operating systems like MS Windows, libdispatch 
needs to utilize the following operating system primitives in a portable way:

  1. threads
  2. mutexes
  3. time functions; e.g. gettimeofday(2)
  4. semaphores
  5. threadsafe atomic operations
  6. thread pools

Suitability of APR
---

   APR is very well suited to writing portable applications.

  1. threads

     Supported.

     See:
         apr_thread_create()

  2. mutexes

     Supported.

     See:
         apr_thread_mutex_create()
         apr_thread_mutex_lock()
         apr_thread_mutex_unlock()

  3. time functions; e.g. gettimeofday(2)

     Supported.

     See:
         apr_time_now()

  4. semaphores

     Not supported directly; however, condition variables are supported
     which may work. Semaphores are also trivial to implement as follows[1]:

     sem_wait(...) {
       if (apr_atomic_dec32 (&count) < 0)
           apr_thread_mutex_lock (mutex);
     }

     sem_post(...) {
     if ((apr_int32_t) apr_atomic_inc32 (&count) <= 0)
         apr_thread_mutex_unlock (mutex);
     }

     [1] Credit to http://markmail.org/message/qqp7nni2gyltvyrd

  5. threadsafe atomic operations

     APR provides a wide range of atomic aperations.

     See:

         apr_atomic_inc32
         apr_atomic_dec32
         apr_atomic_cas32

  6. thread pools

     APR 1.3 provides a very sophisticated thread pool implementation.

     See:
         apr_thread_pool_create()
         apr_thread_pool_push()


Suitability of libevent
---

     libevent does not provide any abstractions for operating system
     primitives.


=======================================================================


Requirements for dispatch sources
---

libdispatch needs to support the following dispatch sources:

  1. socket readiness
  2. signals
  3. filesystem changes
  4. timers
  5. subprocess changes (fork, exit, etc.)
  6. user-defined event sources


Suitability of APR
---

  1. socket readiness

     APR provides a generic polling mechanism that uses kqueue, epoll,
     poll, select, or WSApoll.

     See:
         apr_pollset_add()
         apr_pollset_remove()
         apr_pollset_poll()

  2. signals

     APR allows you to setup a dedicated thread to perform signal handling.
     This is generally better than using signal handlers, because it avoids
     the need to add EINTR checks after every system call.

     See:

         apr_setup_signal_thread();
         apr_signal_thread();

  3. timers

     Not supported.

     One solution would be to have a dedicated timekeeper thread that
     wakes up at regular intervals and generates timer events.

  4. filesystem changes

     Not supported.

     One solution would be to have a dedicated filesystem event thread that
     uses platform-specific facilities for monitoring filesystem events.

  5. subprocess changes (fork, exit, etc.)

     Not supported.

     I'm not sure how this event source is useful.

  6. user-defined event sources

     This could be implemented in separate threads.


Suitability of libevent
---

  1. socket readiness

     libevent can uses kqueue, epoll, poll, select, or WSApoll.

     See:
         event_set()
         event_add()

  2. signals

     signal handling is performed using a signal handler that writes to a
     pipe that is monitored by poll(2) or the platform-specific alternative.

     See:

         signal_set()
         signal_add()

  3. timers

     Timers are supported.

     See:

         evtimer_set()
         evtimer_add()

  4. filesystem changes

     Not supported.

     One solution would be to have a dedicated filesystem event thread that
     uses platform-specific facilities for monitoring filesystem events.
     A socketpair(2) would be needed to notify the event_dispatch() loop
     of new events.

  5. subprocess changes (fork, exit, etc.)

     Not supported.

     I'm not sure how this event source is useful.

  6. user-defined event sources

     This could be implemented in separate threads.
     A socketpair(2) would be needed to notify the event_dispatch() loop
     of new events.




More information about the libdispatch-dev mailing list