Passing Parameters while creating threads

Now that I have the interop to thread routine: RunLuaThread(void *) life is grand… or is it?

The signature of the routine is just that: RunLuaThread(void *)

With this, I’m able to do exactly what I showed before, namely, pass in a bit of lua code, and it will get executed, in its own thread, running on its own lua_State.  But, I also need to pass a parameter into my thread code as well.  Basically, I want: RunLuaThread(char * codechunk, void * param)

What to do?

Well, easy enough, since we’re dealing with scrict here, just do a little scripting.  I can do the following:

ffi.cdef("typedef struct {int Data;}buffer;")

local code1 = [[  
  ffi = require "ffi"
  ffi.cdef("typedef struct {int Data;}buffer;")

  print("thread code 1")  
  local voidptr = ffi.cast("void *",_ThreadParam)  
  local buff = ffi.cast("buffer *", voidptr)
  print("Buffer Data: ", buff.Data) 
]]

If you blink, you’ll miss the trick.  That _ThreadParam is something that I prepended to the script before I handed it to the thread routine for execution.  It happened like this:

local threadprogram = PrependThreadParam(codechunk, param)

local threadId = ffi.new("DWORD[1]")  
self.Handle = kernel32.CreateThread(nil,   0,   lua.RunLuaThread,   
    ffi.cast("void *", threadprogram),   
    flags,   
    threadId)  
threadId = threadId[0]  self.ThreadId = threadId

and the PrependThreadParam function looks like this:

function PrependThreadParam(codechunk, threadparam)  
    if threadparam == nil or codechunk == nil then return codechunk end
    local paramAsString = CreatePointerString(threadparam)
    return string.format("local _ThreadParam = %s\n\n%s", paramAsString, codechunk) 
end

So, basically, take whatever code you’ve got, take the parameter that’s been passed in and get it’s address, stuff that into a variable, that is now part of the script.  Now, the script is free to do whatever it wants with that variable.  It’s the same thing that happens when your lua script is executed from the command line.  Take argv, argc, and make them available to your script.

This mechanism is a bit wasteful of string allocation, but, eh, it only happens once in the life of this thread, so it’s probably ok.

And there you have it.  I can now specify the parameter to the thread to be executed, as well as the script that will act as the body of the thread itself.  That’s great, because for the I/O completion worker thread, I need to pass in the handle of the IO Completion port so the thread can do its thing.



Leave a comment