#+TITLE: ioxx                               -*- mode: org; fill-column: 79; -*-
#+STARTUP: hidestars odd

* Design

*** DONE Should there be such a thing as an invalid =ioxx::socket=?

    The design could enforce that a =socket= is always valid, i.e. there would
    be no default constructor and no =release()= method. Is that desirable? Or
    is the additional flexibility of a stateful =socket= implementing
    =reset()=, =swap()=, and =release()= all over the place?

    [2008-04-27 Sun]: The answer is *no*. A =socket= is always valid; any
    attempt to construct an invalid socket throws an exception. A stateful
    socket can be readily emulated by using a socket pointer, i.e. a
    scoped_ptr<socket> or shared_ptr<socket>.

*** DONE Will ioxx have a link library?

    Link libraries are a pain in the ass once different kinds of variants are
    involved. At the same time, a lot of socket code can be put into a link
    library just fine; including all those system headers everywhere is plain
    unnecessary.

    [2008-05-10 Sat]: No link library, we try to be header-only.

* Known Bugs and Portability Problems

*** DONE Specialization for =size(iovec const &)= doesn't compile with ICC 9.11.

    Boost 1.35 defines that function to return =range_difference<T>::type= --
    the signed type =byte_offset= for us --, but the current specialization
    returns =byte_size=, which is unsigned.

*** TODO Boost libraries don't compile on AIX.

    The header-only libraries probably work, but Boost.Build doesn't seem to
    know about the IBM xlC++ compiler. Is it a good idea to use Boost.System
    after all? It's the only link library ioxx really needs at this point. The
    unit tests also need the unit_test_framework, naturally, but not being able
    to build those is a smaller problem than not being able to build the actual
    library. A simple replacement class for =system_error= might make things a
    lot easier.

    [2008-05-02 Fri]: ioxx no longer depends on any boost link libraries;
    everything is header-only.

    [2008-05-09 Fri]: Test programs *do* depend on link libraries. However, the
    build should be able to fall back to header-only by including the special
    version of boost_unit_test.

*** TODO All non-copiable classes should support =swap()=.

*** DONE Add a scoped task class to =schedule=.

    The standard =task_id= is not scoped, i.e. the task is not cancelled on
    destruction. A common use case for scheduled tasks, however, are timeouts,
    and those tasks will exist only for a certain scope, namely the time the
    application is waiting for the i/o operation to complete.

    [2008-05-02 Fri]: Added =schedule<>::timeout=.

*** DONE =dispatch::run()= is insufficient

    The function calls =deliver_events()= directly after waiting. This means
    that the active handlers will run with a -- potentially -- screwed up
    notion of 'now' because the user had no chance to update the system timer.
    There are two ways out of this:

    - Split =wait()= out of =run()=, like it is in =demux=.
    - Pass a reference to =time= so that our loop can call =update()=.

*** TODO Demux and dispatcher sockets need constructors for weak ownership.

    The demuxers don't forward the dont-close-on-destruction constructor. The
    concept check test should proably enforce that.

*** DONE All our classes must accept an allocators object at construction.

    Having a template parameter is nice, but it must be possible to pass a
    concrete instance.

    [2008-05-09 Fri]: It turns out that most STL classes don't accept an
    allocator at construction! So this is probably a nice-to-have but not
    important feature.

*** DONE The =AX_WITH_PROG= macro has some screwed up documentation.

    [2008-04-30 Wed]: [[gnus:nnml:mail.archive#8089][Asked Francesco.]]
    [2008-05-02 Fri]: Fixed.

*** DONE Try linking =adns_init()= without =-ladns= first.

    The user may want to specify an entirely different library in =$LIBS=. If
    that is the case, then linking =-ladns= might break a link that would have
    succeeded otherwise.

    [2008-05-02 Fri]: Implemented in AX_HAVE_ADNS.

*** TODO Add a dummy DNS server we can use is case ADNS isn't available.

*** DONE Fix comments in =AX_HAVE_POLL_PWAIT=.

*** TODO Don't assume to know the =msghdr= layout.

    On Solaris, the structure doesn't have the layout it does on Linux, so our
    all-in-one initialization style fails to compile =socket::sendmsg()=, etc.

*** TODO The SUN compiler has no real std::reverse_iterator.

    The boost libraries fail to compile as much as our own iovec
    specializations do. Not sure how this can be remedied at all.

    [2008-05-19 Mon]: The new class design is un-compilable with that old SUN
    compiler, not just because it doesn't understand =std::reverse_iterator=.
    Apparently SUN Studio 11 might improve matters, but right now there is no
    way to verify that.

    Curiously enough, the definitions of =reverse_iterator= for =iovec= are
    redundant, because the Boost.Range library defaults to use its own version
    based on the iterator library. Whether that's preferable to the one found
    in the STL is hard to say.

*** TODO Don't rely on the compiler to deduce return type of bind().

    When binding function pointers, older compilers cannot determine the return
    type. The SUN compiler doesn't even understand bind<T>() syntax; so we need
    to use bind(type<T>(), ...) instead.

    [2008-05-09 Fri]: Most bind() calls have been fixed.

*** TODO Link boost_unit_test shared library correctly.

    To link that bloody library, binaries need to be compiled with
    =BOOST_TEST_DYN_LINK= defined.

    [2008-05-09 Fri]: Added macro that recognizes this problem, but it's still
    very hacky and needs to be improved. Particularly, the macro should guess
    the library's name too, meaning it shouldn't depend on BOOST_SUFFIX to be
    set.

    Related to [[*Boost libraries don t compile on AIX]].

*** TODO NetBSD doesn't have sighandler_t type.

*** TODO Add a DNS test case with an unreachable server.

*** TODO Implement a real test case for the i/o dispatcher.

    Create a large number of pipes and chain them together using some
    to-be-written forwarder class so that they become a kind of loop:

    : p1i --> ... --> p1o --> p2i --> ... --> p2o --> p2i --> ... +
    :                                                             |
    : p9o <-- ... <-- p9i <-- p8o <-- ... --> p8i <-- p7o <-- ... +

    Simply put: what is written to the first pipe's input end, comes out at the
    last pipe's output end. The test forwarder can do funky stuff like writing
    random block sizes or simulate network delays by writing by means of a
    scheduled task, etc. Verification can take place by CRCing the (random)
    data stream.

*** TODO =Schedule::run()= shouldn't be called twice per loop in =test/dns.cpp=.

    See commit bfde4809d49c739b29f7de252e972c4f8ab0546b for details. The same
    problem exists in =core::run()=.

*** TODO =adns= must use an allocator to get new sockets, not =operator new()=.

*** TODO Enable optional use of =boost::system::system_error=.

    Autoconf can detect whether it's available and enable optional support.

*** TODO Use strerror_r() if available.

    This affects the definition of =[[file:include/ioxx/error.hpp::std%20runtime_error%20std%20string%20context%20std%20strerror%20ec][system_error]]=.

*** TODO Clean up handling of =event_set= flags in =poll= and =epoll=.

    Currently, we map them to readable, writable, and pridata without exposing
    that they were ever set, but the code is clumsy. Relevant for [[file:include/ioxx/detail/poll.hpp::ev%20socket%20readable%20socket%20writable%20socket%20pridata][poll.hpp]] and
    [[file:include/ioxx/detail/epoll.hpp::ev%20socket%20readable%20socket%20writable%20socket%20pridata][epoll.hpp]]. Here is what POSIX has to say about the meaning of those flags:

***** =POLLIN=

      Data other than high-priority data may be read without blocking. For
      STREAMS, this flag is set in revents even if the message is of zero
      length. This flag shall be equivalent to =POLLRDNORM | POLLRDBAND=.

    * =POLLRDNORM=

      Normal data may be read without blocking. For STREAMS, data on priority
      band 0 may be read without blocking. This flag is set in revents even if
      the message is of zero length.

***** =POLLRDBAND=

      Priority data may be read without blocking. For STREAMS, data on priority
      bands greater than 0 may be read without blocking. This flag is set in
      revents even if the message is of zero length.

***** =POLLPRI=

      High-priority data may be read without blocking. For STREAMS, this flag
      is set in revents even if the message is of zero length.

***** =POLLOUT=

      Normal data may be written without blocking. For STREAMS, data on
      priority band 0 may be written without blocking.

***** =POLLWRNORM=

      Equivalent to POLLOUT.

***** =POLLWRBAND=

      Priority data may be written. For STREAMS, data on priority bands greater
      than 0 may be written without blocking. If any priority band has been
      written to on this STREAM, this event only examines bands that have been
      written to at least once.

***** =POLLERR=

      An error has occurred on the device or stream. This flag is only valid in
      the revents bitmask; it shall be ignored in the events member.

***** =POLLHUP=

      The device has been disconnected. This event and =POLLOUT= are
      mutually-exclusive; a stream can never be writable if a hangup has
      occurred. However, this event and =POLLIN=, =POLLRDNORM=, =POLLRDBAND=,
      or =POLLPRI= are not mutually-exclusive. This flag is only valid in the
      revents bitmask; it shall be ignored in the events member.

***** =POLLNVAL=

      The specified fd value is invalid. This flag is only valid in the revents
      member; it shall ignored in the events member.

*** TODO Provide a logxx logging callback to =adns_init()=.

    A simple example is in [[file::test/adns-logging-test.cpp][adns-logging-test.cpp]].
