That should be assert(coroutine.resume(thread, not err, err)) in the middle, sorry for the typo. We want to yield after starting the non-blocking call and resume after the callback gets called.
You'll need special care for functions that may call their callback before returning (aka zalgo functions). On Fri, Jul 17, 2015 at 10:22 PM, Tim Caswell <[email protected]> wrote: > Now that I have a proper keyboard, let me explain a little better. > > I assume that since you're using luv and a write method, you're talking > about the uv.write function in luv. This is non-blocking and coroutines > have nothing to do with it. If you do s:write("a") and s:write("b") in a > coroutine, it won't yield for either one, but rather will put both strings > on the socket's write queue. The coroutine will then move on and finish > without waiting for the data to actually write and flush. Then your second > coroutine will run and do the same thing. > > So actually, the first case is guaranteed to output "abab" and not "aabb" > since there is nothing to cause the first coroutine to yield. The two > coroutines never run concurrently, just one and then the other. > > Now if you were using some coroutine aware stream like the write function > in the coro-net package on lit things would be different. As you're > guessed, the first write would cause the coroutine to yield and not resume > till the data has been flushed. Then the second coroutine would run and do > the same thing. Since the data goes in a fifo queue, the first coroutine > would most likely unblock first. Assuming that your writes are large > enough to cause libuv to wait for each write to flush your output will be > "aabb" since the two coroutines are running concurrently with cooperative > multithreading. > > A common pattern I use to wait for callback based APIs is as follows: > > local function write(socket, data) > local thread = coroutine.running() > socket:write(data, function (err) > assert(coroutine.yield(thread, not err, err)) > end) > return coroutine.yield() > end > > The basic idea is to yield the coroutine whenever we're waiting on a > callback and then to resume once it happens. We rearrange the result > values to lua assert friendly value, error instead of the node-style > callback(err, data). > > On Fri, Jul 17, 2015 at 9:58 PM, Tim Caswell <[email protected]> wrote: > >> Luv is still single threaded. I'm pretty sure that the libuv writes are >> put in a queue. Your strings will never get chopped up even if another >> coroutine tries to write to the same socket. >> On Jul 17, 2015 4:55 PM, "Wes Chow" <[email protected]> wrote: >> >>> Apologies if this isn't the right place for a luv question... >>> >>> If I have two coroutines which each simultaneously do two socket:write >>> operations to the same socket, s: >>> >>> s:write("foo") >>> s:write("bar") >>> >>> I assume that there's a possibility the writes get interleaved. Ie, it's >>> possible that "foofoobarbar" goes out on the socket, and that it might also >>> be possible that "foobarfoobar" goes out. >>> >>> However, if I do this in two coroutines simultaneously: >>> >>> s:write("foobar") >>> >>> Am I guaranteed that data will go out as "foobarfoobar"? Or is it still >>> possible that data gets interleaved within two write calls? >>> >>> Thanks, >>> Wes >>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "luvit" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to [email protected]. >>> For more options, visit https://groups.google.com/d/optout. >>> >> > -- You received this message because you are subscribed to the Google Groups "luvit" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
