Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   Related Pages   Examples  

here is a breakdown of the example source file, example.cc.

example.cc follows the general use pattern explained on the main page.

we'll skip the cvs and licensing info, as well as the includes. the complete file can be viewed under "examples" on the navigation above.

    namespace /*anonymous*/{
    #ifdef TRADITIONAL
      typedef fpoller::traditional_poller example_poller;
    #else
      typedef fpoller::poller example_poller;
    #endif
      example_poller *the_poller = NULL;
    }
create a pointer to the poller we will be using. the file can compile using traditional poll() or a fast delegate. if no fast delegate (i.e. /dev/poll or kqueue) exists on the system traditional poller and poller are identical. use anonymous namespace to get translation unit level scoping.

    typedef fpoller::write_callback<const char, fpoller::writer::close_on_exit> example_writer;
just use a default writer that takes a buffer and a size, sends the buffer and closes the file descriptor.

    struct example_parser{
      example_parser(){}
      void parse (int fd, svec &incoming, int request_size){
        the_poller->add(fd,fpoller::WRITE,new example_writer(pcc(incoming),request_size));
      }
    };
the most trivial possible parser of incoming requests. It just passes on what it gets in to a newly created example_writer.

    typedef fpoller::read_callback<example_parser,
      fpoller::reader::socket_read, fpoller::reader::purge,fpoller::reader::stderr_report,fpoller::reader::termination_string>
    example_reader;
we'll use the parser we just created as a template argument to the read_callback. The other template args are defautls, so we could have left them out.

    int main(){
      signal(SIGPIPE,SIG_IGN);
very important to ignore SIGPIPE, as it is sent every time a client closes a connection, and will cause the program to terminate if it not ignored.

      fpoller::reader::termination_string::set_terminator("\n");
      int fd;
      try {
        the_poller = new example_poller;
        fd = fpoller::get_listen_socket(8081);
        fpoller::set_non_blocking(fd);
      }catch (fpoller::exception &e){
        std::cerr <<"fatal error. "<<e.where()<<"\n\t"<<e.what()<<"\n";
        exit(1);
initialize poller, and get a listening socket. this is the only time we are really worried about exceptions being thrown. the program is useless if it can't listen or has no poller, so just report and exit.

      }
      the_poller->add(fd,fpoller::READ,new fpoller::accept_callback<example_reader,example_poller>(the_poller));
use the convenience class accept_callback to listen on the listening socket we got above and set it as the poller's first socket. The accept_callback will create a read_callback for every connection it accepts and add it to the poller.

      int nready;
      for (;;){
        if ((nready = the_poller->poll(1000)) >= 0){
          std::cerr <<"poll finished "<<nready<<" ready \n";
        }else{
          std::cerr <<"errno == "<<errno<<" error from poll(): "<< strerror(errno) <<"\n";
        }
      }//for
this is the heart of the program, which just loops around the poller->poll() and reports what's going on. the callbacks manage themselves (the accept_callback creates example_readers which create example_writers, and they are all managed by smart pointers), so we don't have to do anything.

      delete the_poller;
      return 0;
    }
these lines are pro forma; never get here anyway.


Generated at Wed Oct 16 16:02:39 2002 for fpoller by doxygen1.2.9.1 written by Dimitri van Heesch, © 1997-2001