lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Wed, Nov 23, 2016 at 07:11:51PM +0000, Dibyendu Majumdar wrote:
> On 23 November 2016 at 02:38, William Ahern <william@25thandclement.com> wrote:
<snip>
> > Lua-script space. The biggest caveat is that Lua objects are multithread
> > safe.
> >
> 
> Thanks for the detailed reply - much appreciated. Did you mean above
> that Lua objects are not multi-thread safe?

Oops. Yes, I meant not multi-thread safe.

<snip>
> I had a quick look at your project cqueues that presumably does this.
> Would it be a good idea to port this to libuv so that Windows can be
> supported as well (I understand cqueues only works on UNIX like
> environments)?

This is sort of difficult to explain, but in short porting to cqueues is a
little non-sensical.

cqueues is designed not to use callbacks internally or to require callbacks.
That way it can be more easily embedded into projects (applications,
libraries). cqueues is based around the notion of restartable operations. If
you've every had to link an async DNS library to an async socket library to
to an async database library, all utilizing callbacks, you very quickly
realize how horrible callbacks are as a generic interface. They don't
compose well because they cannot make use of the most fundamental control
flow model in almost every language--synchronous function call and return,
where the function result is returned directly.

By contrast, a restartable interface makes it much easier to combine
different libraries because you utilize the normal control flow patterns. It
works just like combining any other code--by invoking a function and
operating on the return value. The only difference is that the return value
might be "try again".

Were cqueues ported to Windows (and that's on the TODO), it would be easy to
tie cqueues into libuv's event loop, just like it's easy to tie cqueues into
libevent or any other common event loop. But only in so far as you're using
libuv for readiness polling; it's I/O interfaces don't make sense in the
cqueues model, and in any event would be superfluous. If you're already
using libuv you don't really need the core cqueues event scheduler, anyhow,
nor the supplemental socket and DNS library.

Porting cqueues to Windows involves serious refactoring of cqueues. epoll,
kqueue, and Solaris Ports all utilize a special descriptor as a handle to
the kernel's polling state. This descriptor can be polled like any other
descriptor. When it polls ready it means events can be dequeued. That's why
cqueues is easy to embed into other event loops--the descriptor is a
transparent proxy for all the events managed by cqueues internally. Even if
cqueues is managing 100,000 socket events, you only need to poll that one
descriptor in your application's mainloop to know to resume the cqueues
controller. There are no parallel threads or callbacks involved; you don't
need to inform cqueues which event is ready; you don't need to worry about
re-entrancy issues (i.e. will cqueues callback into your event loop again);
etc.

Microsoft's vision for highly concurrent asynchronous tasks on Windows has
always been based on a multi-threaded, callback model. Even overlapped I/O
uses multiple threads within the kernel. Some interfaces, like
WaitForMultipleObjects, are superficially similar to epoll, but they're
really just a queue for the results of callbacks invoked from other threads.
And they weren't meant to scale in the single-threaded case the same way
epoll, kqueue, etc can. So it's quite a chore to match up the cqueues model
in a Windows environment. Libraries like libuv and libevent's buffer
interface actually solve this by forcing a more Windows-like model on Unix
applications. For basic tasks this is simple and convenient; but
composability suffers and building complex applications many moving parts
results in so-called callback hell as you bind various callback interfaces
together while struggling to maintain memory and thread safety.