[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[Libevent-users] Multithreading



Hello,

   I'm not really clear on what EV_WRITE means for UDP. Does it
essentially guarantee that sendto() won't return EAGAIN, ENOBUFS et al
(backend quirks aside)?

   Assuming I'm on a pthreads platform, and I have a few TCP channels
which are used for query-operations, and a query can take a while
(anything from under a second to a few minutes), is it safe to hand over
a "struct bufferevent *ev" to other thread, and let it handle the reply?
I.e:

   ----------------------------
   void do_read(struct bufferevent *bev, void *ctx)
   {
     parsedata *ps = ctx;
     int done;

     done = parse_query(bev, ps);

     if(done)
     {
       start_worker_thread(worker, bev, ps);
     }
   }

   void worker(struct bufferevent *bev, parsedata *ps)
   {
      struct evbuffer *output = bufferevent_get_output(bev);
      char *result;
      int len;

      long_operation(ps, &result, &len);

      evbuffer_add(output, result, len)
   }
   ----------------------------

   How does one handle the situation where a client closes the socket
prematurely (during long_operation() for instance)? Does 'bev' and
'output' become toxic [by the base thread] if the client closes the
socket, or will they exist until I call event_del() on bev? (Which I
would assume is safe to do on the worker() thread, given I'm running
libevent 2.x?).

   With regards to multithreading and UDP: Is there any point to queuing
outbound UDP packets, and send them in a "do_write()" event handler,
rather than just calling sendto() directly from the worker threads which
generate outbound packets? I.e does this:

   ----------------------------
   workerthread(...)
   {
     packet_t *pkt;
     ...
     make_packet(&pkt);
     lock(outqueue)
     queue_push(outqueue, pkt);
     unlock(outqueue)
     if(!ev)
       ev = event_new(base, s, EV_WRITE, do_write, NULL);
   }

   do_write(...)
   {
      ...
      lock(outqueue)
      pkt = queue_pull(outqueue)
      unlock(outqueue)
      if(pkt)
        sendto(..., pkt->data, ...)
      else
      {
        event_del(ev)
        ev = NULL
      }
   }
   ----------------------------

   [the handling of ev is merely conceptual, the point is that the event
handler is added when there are packets to be send, and it is removed
when there are no more packets waiting to be transferred]

   ...offer any any benefits over this:

   ----------------------------
   workerthread(...)
   {
     packet_t *pkt;
     ...
     make_packet(&pkt);
     sendto(..., pkt->data, ...)
   }
   ----------------------------

   ?

   As made obvious by these questions, I'm completely new to libevent.
If there are any radically different ways of doing these things using
other means in libevent, feel free to point me to the relevant function
names.

-- 
Kind regards,
Jan Danielsson

***********************************************************************
To unsubscribe, send an e-mail to majordomo@xxxxxxxxxxxxx with
unsubscribe libevent-users    in the body.