Created
July 1, 2011 11:28
-
-
Save mwild1/1058346 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local wrapclient = require "net.server".wrapclient; | |
local socket = require "socket"; | |
local coroutine = coroutine; | |
local comap = {}; | |
local function yield(conn) | |
comap[conn] = coroutine.running(); | |
local r = coroutine.yield(); | |
comap[conn] = nil; | |
return r; | |
end | |
local function wrap_blocking_socket(conn, err) | |
if not conn then return nil, err; end | |
local coro = assert(coroutine.running(), "Can only wrap blocking socket inside a coroutine"); | |
conn:settimeout(0); | |
local listener = { default_mode = "*l" }; | |
function listener.onincoming(conn, data) | |
coroutine.resume(coro, data); | |
end | |
local connect_host, connect_port = conn:getpeername(); | |
return wrapclient(conn, connect_host, connect_port, listener, listener.default_mode); | |
end | |
local function async_wrap(f, ...) | |
local f_ = coroutine.wrap(f); | |
f_(...); | |
end | |
local buffers = {}; | |
local function async_read(conn, len) | |
local buffer = buffers[conn] or ""; | |
if type(len) == "number" then | |
while #buffer < len do | |
buffer = buffer..coroutine.yield(); | |
end | |
local r = buffer:sub(1,len); | |
buffer = buffer:sub(len+1); | |
if buffer == "" then buffer = nil; end | |
buffers[conn] = buffer; | |
return r; | |
elseif len == "*l" or len == nil then | |
while true do | |
local line, rest = buffer:match("([^\n]\n)(.*)"); | |
if line then | |
buffer = rest; | |
if buffer == "" then buffer = nil; end | |
buffers[conn] = buffer; | |
return line; | |
end | |
buffers[conn] = buffer..coroutine.yield(); | |
end | |
end | |
end | |
local function async_write(client, data) | |
assert(client.network.socket:write(data)); | |
end | |
coroutine.wrap(function () | |
-- Create the redis client as normal here | |
-- (it must never be used outside this function) | |
-- Then do: | |
client.network.socket = wrap_blocking_socket(client.network.socket); | |
client.network.read = async_read; | |
client.network.write = async_write; | |
end)(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment