lua-users home
lua-l archive

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


Even if no yield/resume is used, since session_data encapsulates some data which are external to Lua, its contents could have been modified between any two ordinary Lua instructions; session_data:handle_login() should be implemented to throw an error if the session_data contents have become invalid. The same applies to a callback-based system; the session_data object still needs to be checked for consistency whenever it is used. 

Where the implicit coroutine yield approach can be problematic is when the user expects a non-local pure Lua object to contain the same values before and after this:log(). It can be a big gotcha, but the clarity of exposition and preservation of the stack might be worth it.

On May 11, 2012, at 12:21 PM, Jay Carlson wrote:

> On Fri, May 11, 2012 at 2:27 PM, Tim Caswell <tim@creationix.com> wrote:
>> I mean I don't want to call `sleep(10)` and suddenly be suspended till 10
>> seconds later when the timeout occurs.  The problem with this is any
>> function that I call could in turn call something else that implicitly
>> suspends me.  Your wrapper is plenty explicit.
> 
> Here's the problem case:
> 
> function web_server:handle_login_html(req)
>   -- Grab the current session and ensure it's valid
>   local session_data = this:find_session(req) or this:die()
>   -- Log the request
>   this:log(req)
>   -- delegate to session
>   session_data:handle_login(req)
> end
> 
> The problem is "this:log(req)". Logging could be implemented by
> writing to a socket--and you can't tell by looking at this code. If it
> writes to a socket, the socket may want to block. In a simple socket
> coroutine system, operations which would block instead are suspended
> until the socket can be read or written. Waiting for this:log() could
> take arbitrarily long. The session_data we grabbed at the top may be
> stale by then.
> 
> Adding to the fun, *most* of the time the log socket will probably be
> ready to write; only under load will two identical requests end up
> going separate ways.
> 
> I hadn't thought about how the coroutine style preserves the stack,
> which is nice. But transparently converting blocking operations to
> coroutine dispatch can give you back many of the concurrency problems
> when you aren't expecting them. I guess neither should be surprising;
> it's non-preemptive green threads.
> 
> Jay
>