threading
Sturla Molden
sturla.molden at gmail.com
Thu Apr 10 11:24:46 EDT 2014
Marko Rauhamaa <marko at pacujo.net> wrote:
> Other points:
>
> * When you wake up from select() (or poll(), epoll()), you should treat
> it as a hint. The I/O call (accept()) could still raise
> socket.error(EAGAIN).
>
> * The connections returned from accept() have to be individually
> registered with select() (poll(), epoll()).
>
> * When you write() into a connection, you may be able to send only part
> of the data or get EAGAIN. You need to choose a buffering strategy --
> you should not block until all data is written out. Also take into
> account how much you are prepared to buffer.
>
> * There are two main modes of multiplexing: level-triggered and
> edge-triggered. Only epoll() (and kqueue()) support edge-triggered
> wakeups. Edge-triggered requires more discipline from the programmer
> but frees you from having to tell the multiplexing facility if you
> are interested in readability or writability in any given situation.
>
> Edge-triggered wakeups are only guaranteed after you have gotten an
> EAGAIN from an operation. Make sure you keep on reading/writing until
> you get an EAGAIN. On the other hand, watch out so one connection
> doesn't hog the process because it always has active I/O to perform.
>
> * You should always be ready to read to prevent deadlocks.
>
> * Sockets can be half-closed. Your state machines should deal with the
> different combinations gracefully. For example, you might read an EOF
> from the client socket before you have pushed the response out. You
> must not close the socket before the response has finished writing.
> On the other hand, you should not treat the half-closed socket as
> readable.
>
> * While a single-threaded process will not have proper race conditions,
> you must watch out for preemption. IOW, you might have Object A call
> a method of Object B, which calls some other method of Object A.
> Asyncio has a task queue facility. If you write your own main loop,
> you should also implement a similar task queue. The queue can then be
> used to make such tricky function calls in a safe context.
>
> * Asyncio provides timers. If you write your own main loop, you should
> also implement your own timers.
>
> Note that modern software has to tolerate suspension (laptop lid,
> virtual machines). Time is a tricky concept when your server wakes up
> from a coma.
>
> * Specify explicit states. Your connection objects should have a data
> member named "state" (or similar). Make your state transitions
> explicit and obvious in the code. In fact, log them. Resist the
> temptation of deriving the state implicitly from other object
> information.
>
> * Most states should be guarded with a timer. Make sure to document for
> each state, which timers are running.
>
> * In each state, check that you handle all possible events and
> timeouts. The state/transition matrix will be quite sizable even for
> seemingly simple tasks.
And exactly how is getting all of this correct any easier than just using
threads and blocking i/o?
I'd like to see the programmer who can get all of this correct, but has no
idea how to use a queue og mutex without deadlocking.
Sturla
More information about the Python-list
mailing list