Page 1 of 1

mapPixel in thread 0.9.1

Posted: Wed Jun 11, 2014 7:45 pm
by Ryan1729
Hi. I'm trying to use ImageData:mapPixel in a thread.

main.lua

Code: Select all

function love.load()
    -- setup thread
    thread = love.thread.newThread("thread.lua")
    toThreadChannel = love.thread.getChannel("toThread")
    fromThreadChannel = love.thread.getChannel("fromThread")
    
    thread:start()
    
    winW = love.graphics.getWidth()
    winH = love.graphics.getHeight()
    imageData = love.image.newImageData(winW, winH)
    
    image = love.graphics.newImage( imageData )
    
    toThreadChannel:push(imageData)
    
    print("loaded")
end

function love.draw()
   
    local tempImageData = fromThreadChannel:pop()
    print("popped")
    if tempImageData then
        print("recieved Image")
        imageData = tempImageData
        image = love.graphics.newImage( imageData )
    else 
        print("no image recieved")
    end
    
    love.graphics.setColor(255,255,255,128)
    love.graphics.draw(image)
    
end

function love.keypressed(key)
    if  key == "q" or key == "escape" then
        love.event.push('quit')
    end 
    
end
thread.lua

Code: Select all

print("thread started")

toThreadChannel = love.thread.getChannel("toThread")
fromThreadChannel = love.thread.getChannel("fromThread")

function drawFunction(x, y, r, g, b, a)
-- perform computations giving the new values for r, g, b and a
    a = 255 
    r = x*y
    g = x*y
    b = x*y  
    return r, g, b, a
end

print("waiting on imageData")
imageData = toThreadChannel:demand()
print("got it: ".. type(imageData))

imageData:mapPixel( drawFunction )

print("sending image")
fromThreadDataChannel:push(imageData)
print("sent")
When I run it I get the following output:

Code: Select all

thread started
waiting on imageData
loaded
got it: userdata
popped
no image recieved
popped
no image recieved
popped
no image recieved
popped
no image recieved
popped
no image recieved
popped
no image recieved
popped
no image recieved
... and so on. Basically, everything is working until the actual imageData:mapPixel( drawFunction ) call. And since it's in a thread apparently that means no error message at all. :ehem:

Re: mapPixel in thread 0.9.1

Posted: Wed Jun 11, 2014 8:32 pm
by bartbes
You can use the love.threaderror callback to get any error messages in a thread.

Re: mapPixel in thread 0.9.1

Posted: Wed Jun 11, 2014 8:47 pm
by slime
You need to explicitly require love modules you want to use in a thread (aside from love.thread itself). require("love.image") in this case.

As bartbes mentioned, adding something like this to main.lua will help with debugging:

Code: Select all

function love.threaderror(thread, err)
    error(err)
end

Re: mapPixel in thread 0.9.1

Posted: Thu Jun 12, 2014 4:19 am
by Ryan1729
It all works now. Thanks for the help!

Re: mapPixel in thread 0.9.1

Posted: Thu Jun 12, 2014 3:28 pm
by Ref
Failed to point out that you not only added require '"love.image" but changed
:

Code: Select all

fromThreadDataChannel:push(imageData)
to

Code: Select all

fromThreadChannel:push(imageData)

Re: mapPixel in thread 0.9.1

Posted: Wed Jun 18, 2014 7:08 pm
by Ref
Wondering if anyone has a better thread handshake library?
This is what I've hacked together so far:

Code: Select all

local threadcode	= {}

threadcode.thread = {}
threadcode.thread.ReceiveChannel	= love.thread.getChannel( 'toThread' )
threadcode.thread.SendChannel		= love.thread.getChannel( 'fromThread' )

function threadcode.thread.receive()	-- thread loops until data received
	print( 'thread: waiting' )
	local dat	= nil
	while not dat do dat = threadcode.thread.ReceiveChannel:demand() end
	print( 'thread: received '.. type( dat ) )
	threadcode.thread.SendChannel:push( dat )	-- confirm receiving without expecting response
	return dat
	end

function threadcode.thread.send( dat )
	print( 'thread: sending '..type( dat ) )
	threadcode.thread.SendChannel:push( dat )
	print( 'thread: '..type( dat )..' sent' )
	local Received = false		-- delay until received
	while not Received do Received = threadcode.thread.receive() end
	end

threadcode.main = {}
threadcode.main.SendChannel	= love.thread.getChannel( 'toThread' )
threadcode.main.ReceiveChannel	= love.thread.getChannel( 'fromThread' )

function threadcode.main.send( dat )
	print( 'main: sending '..type( dat ) )
	threadcode.main.SendChannel:push( dat )
	print( 'main: '..type( dat )..' sent' )
	threadcode.main.receiveConfirmation()	-- main blocked
	end

function threadcode.main.requestData()		-- non-blocking, checking availability
	print( 'main: waiting for reply' )
	local data = threadcode.main.ReceiveChannel:pop()
	if data then
		print( 'main: '..type(data)..' received' )
		threadcode.main.send( true )		-- confirm reception
		end
	return data
	end

function threadcode.main.receiveConfirmation()	-- blocking until transfer confirmed
	print( 'main: waiting confirmation' )
	dat	= nil
	while not dat do dat = threadcode.main.ReceiveChannel:demand() end
	print('main: Glad to hear thread received '..type( dat ))
	return dat
	end

return threadcode
Attached demo really not a good example of what a thread should be used for.
Note: addition of collectgarbage( 'collect' ) need to compensate for memory leak.
EDIT: Attached file does not run via forum. Runs fine if download to my computer - a window machine. Cause unknown????
EDIT: Only runs in original folder. All components present in zip. All files lower case. Doing something obviously wrong! Help!
EDIT: For some reason, didn't like my require in the thread? Replaced thread functions directly into thread. Reloaded demo.
EDIT: Dumb mistake. In thread, I required 'love.filesystem' AFTER require 'threadcode'.

Re: mapPixel in thread 0.9.1

Posted: Wed Jun 18, 2014 8:18 pm
by bartbes
Something like my async library? The docs aren't really there yet, but the example pretty much shows all of it.

Re: mapPixel in thread 0.9.1

Posted: Wed Jun 18, 2014 11:07 pm
by Ref
Thanks bartbes!
Will have to see how your code works.
Look forward for some docs.
Best!