lua-users home
lua-l archive

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


It was thus said that the Great Juris Kalnins once stated:
> On Wed, 07 Oct 2009 09:37:18 +0300, Sean Conner <sean@conman.org> wrote:
> >  The reason I'm using the userdata and not a lightuserdata is the  
> >former I
> >can attach a metatable to, which would simplify the Lua code a bit.
> 
> you _can_ set global metatable for all lightuserdata. and use
> some logic in C code to detect what kind of data pointer points to, and
> call appropriate functions depending on that.

  Maybe an explanation of what I'm doing is in order.

  I have a Unix daemon that listens in on a TCP port, accepts connections,
and processes requests.  The main logic is already there, in C, in a large
epoll() driven loop.  In fact, here's the main loop:

	static void mainloop(void)
	{
	  struct epoll_event *list;
	  int                 events;
	  int                 i; 
	  PollNode            node;
	  
	  list = malloc(sizeof(struct epoll_event) * c_pollqueue);
	 
	  while(1)
	  {
	    check_signals();
	    events = epoll_wait(g_queue,list,c_pollqueue,60);
	  
	    if (events == -1)
	      continue;
	  
	    for (i = 0 ; i < events ; i++)
	    {
	      node = list[i].data.ptr;
	      (*node->fn)(&list[i]);
	    }
	  }
	}  

  What (*node->fn)() does depends upon the type of node---for listening
sockets, it does an accept(), set the connection socket to nonblocking,
create a socket node (derived off of PollNode, and yes, this is straight C
here) and adds the connection socket to the epoll queue looking for read,
write or disconnect, edge triggered events.

  (*node->fn)() for connection sockets will either read the data, or write
the data, depending upon the event (read, write, or disconnect).  

  This exists and it works.

  Only I'd like to handle input and output via Lua (like I said, it's a
proof-of-concept).  And to make it easy, I'd like the Lua code to look
something like:

	function main(socket)
	  while true do
	    local x = socket:read("*l")
	   
	    if x == "SHOW" then
	      io.stdout:write(string.format("SHOW ME THE TABLE!\n"))
	      table.show(socket,_G)
	    elseif x == "QUIT" then
	      io.stdout:write(string.format("Quitting the thread\n"))
	      thread.exit(0)
	    elseif x == nil then
	      io.stdout:write(string.format("Quitting the thread because no input\n"))
	      thread.exit(0)
	    else
	      io.stdout:write(string.format("%s\n",x))
	      socket:write(x)
	      socket:write("\n")
	    end
	  end
	end

  socket is the userdata I'm trying to pass around (and this may be a hack,
but this is exploratory for me) and the functions socket:read(),
socket:write and thread:exit() are all functions that yield (and are written
in C).  I'm not using the built-in io routines to handle the sockets
because, well, I want to run one Lua thread per connection, and at any point
where the lua thread could block is where I want to switch threads.

  Another thing to keep in mind---the C code wants to push data, the Lua
code wants to pull data and that's where the disconnect is happening.  There
may very well be a better way of dealing with this, but like I said, this is
my way to learn the Lua internals.

  -spc (Although I may have bitten off more than I should have ... )