Difference between revisions of "love.thread"

(Examples)
(18 intermediate revisions by 7 users not shown)
Line 4: Line 4:
 
Threads are separate Lua environments, running in parallel to the main code. As their code runs separately, they can be used to compute complex operations without adversely affecting the frame rate of the main thread. However, as they are separate environments, they cannot access the variables and functions of the main thread, and communication between threads is limited.
 
Threads are separate Lua environments, running in parallel to the main code. As their code runs separately, they can be used to compute complex operations without adversely affecting the frame rate of the main thread. However, as they are separate environments, they cannot access the variables and functions of the main thread, and communication between threads is limited.
  
All LOVE objects (userdata) are shared among threads so you'll only have to send their references across threads. You may run into concurrency issues if you manipulate an object on multiple threads at the same time.
+
All LÖVE objects (userdata) are shared among threads so you'll only have to send their references across threads. You may run into concurrency issues if you manipulate an object on multiple threads at the same time.
  
 
When a [[Thread]] is started, it only loads the love.thread module. Every other module has to be loaded with [[require]].
 
When a [[Thread]] is started, it only loads the love.thread module. Every other module has to be loaded with [[require]].
{{notice|The [[love.graphics]] module has several restrictions and therefore should only be used in the main thread.}}
+
 
 +
{{notice|The [[love.graphics]] and [[love.window]] modules have several restrictions and therefore can only be used in the main thread.}}
 +
{{notice|Unless you define the [[love.threaderror]] callback or call [[Thread:getError]] you won't see any errors your thread code throws.}}
 +
 
 
== Types ==
 
== Types ==
 
{{#ask: [[Category:Types]] [[parent::love.thread]] [[Concept:Current]]
 
{{#ask: [[Category:Types]] [[parent::love.thread]] [[Concept:Current]]
Line 33: Line 36:
 
{{#set:Description=Allows you to work with threads.}}
 
{{#set:Description=Allows you to work with threads.}}
 
{{#set:Since=070}}
 
{{#set:Since=070}}
== Example ==
+
== Examples ==
=== from http://love2d.org/forums/viewtopic.php?f=5&t=9934&p=60592&hilit=thread#p60592 ===
+
A simple example showing the general usage of a thread and using channels for communication.
=== main.lua ===
 
 
<source lang="lua">
 
<source lang="lua">
-- new thread
+
-- This is the code that's going to run on the our thread. It should be moved
thread = love.thread.newThread('thread','thread.lua')
+
-- to its own dedicated Lua file, but for simplicity's sake we'll create it
thread:start()
+
-- here.
 +
local threadCode = [[
 +
-- Receive values sent via thread:start
 +
local min, max = ...
  
function love.update(dt)
+
for i = min, max do
  msg_table      = msg_table or {}
+
    -- The Channel is used to handle communication between our main thread and
  -- process messages when other thread is "done"
+
    -- this thread. On each iteration of the loop will push a message to it which
  if thread:get('done') then
+
    -- we can then pop / receive in the main thread.
  msg_table[1]  = thread:get('number')
+
    love.thread.getChannel( 'info' ):push( i )
  msg_table[2]  = thread:get('string')
+
end
  msg_table[3]  = tostring(thread:get('condition'))
+
]]
  -- concat our messages into a long string
 
  message         = table.concat(msg_table,'\n')
 
  -- get image data from the other thread
 
  imageData      = imageData or thread:get('image')
 
  
  -- initialize image
+
local thread -- Our thread object.
  image  = love.graphics.newImage(imageData)
+
local timer  -- A timer used to animate our circle.
  end
 
  if thread:get('hasCounter') then
 
  msg_table[4]  = thread:get('counter')
 
  message        = table.concat(msg_table,'\n')
 
  end
 
end
 
  
function love.draw()
+
function love.load()
  if image then
+
    thread = love.thread.newThread( threadCode )
  love.graphics.draw(image,50,50)
+
    thread:start( 99, 1000 )
  end
 
  if message then
 
  love.graphics.print(message,10,10)
 
  end
 
 
end
 
end
</source>
 
=== thread.lua ===
 
<source lang="lua">
 
-- load modules b/c new thread
 
require 'love.filesystem'
 
require 'love.image'
 
require 'love.timer'
 
  
-- get this thread's id
+
function love.update( dt )
thisThread  = love.thread.getThread()
+
    timer = timer and timer + dt or 0
-- load image file, userdata can be sent also!
 
file      = love.image.newImageData('love.png')
 
  
-- send messages to this thread's inbox
+
    -- Make sure no errors occured.
thisThread:set('image',file)
+
    local error = thread:getError()
thisThread:set('number',1337)
+
    assert( not error, error )
thisThread:set('string','a string message')
+
end
thisThread:set('condition',true)
 
thisThread:set('done',true)
 
  
time0 = love.timer.getTime()
+
function love.draw()
counter = 0
+
    -- Get the info channel and pop the next message from it.
 +
    local info = love.thread.getChannel( 'info' ):pop()
 +
    if info then
 +
        love.graphics.print( info, 10, 10 )
 +
    end
  
-- count per second and send counter to inbox
+
    -- We smoothly animate a circle to show that the thread isn't blocking our main thread.
while true do
+
    love.graphics.circle( 'line', 100 + math.sin( timer ) * 20, 100 + math.cos( timer ) * 20, 20 )
  timeD = love.timer.getTime() - time0
 
  if timeD > 1 then
 
  counter = counter + 1
 
  thisThread:set('counter',counter)
 
  thisThread:set('hasCounter',true)
 
  time0 = love.timer.getTime()
 
  end
 
 
end
 
end
 
</source>
 
</source>
 +
 
== See Also ==
 
== See Also ==
 
* [[parent::love]]
 
* [[parent::love]]

Revision as of 00:31, 7 February 2018

Available since LÖVE 0.7.0
This module is not supported in earlier versions.

Allows you to work with threads.

Threads are separate Lua environments, running in parallel to the main code. As their code runs separately, they can be used to compute complex operations without adversely affecting the frame rate of the main thread. However, as they are separate environments, they cannot access the variables and functions of the main thread, and communication between threads is limited.

All LÖVE objects (userdata) are shared among threads so you'll only have to send their references across threads. You may run into concurrency issues if you manipulate an object on multiple threads at the same time.

When a Thread is started, it only loads the love.thread module. Every other module has to be loaded with require.

O.png The love.graphics and love.window modules have several restrictions and therefore can only be used in the main thread.  


O.png Unless you define the love.threaderror callback or call Thread:getError you won't see any errors your thread code throws.  


Types

Channel An object which can be used to send and receive data between different threads. Added since 0.9.0
Thread A Thread represents a thread. Added since 0.7.0

Functions

love.thread.getChannel Creates or retrieves a named thread channel. Added since 0.9.0
love.thread.getThread Look for a thread and get its object. Added since 0.7.0 Removed in 0.9.0
love.thread.getThreads Get all threads. Added since 0.7.0 Removed in 0.9.0
love.thread.newChannel Creates a new unnamed thread channel. Added since 0.9.0
love.thread.newThread Creates a new Thread from a filename, string or FileData object containing Lua code. Added since 0.7.0


Examples

A simple example showing the general usage of a thread and using channels for communication.

-- This is the code that's going to run on the our thread. It should be moved
-- to its own dedicated Lua file, but for simplicity's sake we'll create it
-- here.
local threadCode = [[
-- Receive values sent via thread:start
local min, max = ...

for i = min, max do
    -- The Channel is used to handle communication between our main thread and
    -- this thread. On each iteration of the loop will push a message to it which
    -- we can then pop / receive in the main thread.
    love.thread.getChannel( 'info' ):push( i )
end
]]

local thread -- Our thread object.
local timer  -- A timer used to animate our circle.

function love.load()
    thread = love.thread.newThread( threadCode )
    thread:start( 99, 1000 )
end

function love.update( dt )
    timer = timer and timer + dt or 0

    -- Make sure no errors occured.
    local error = thread:getError()
    assert( not error, error )
end

function love.draw()
    -- Get the info channel and pop the next message from it.
    local info = love.thread.getChannel( 'info' ):pop()
    if info then
        love.graphics.print( info, 10, 10 )
    end

    -- We smoothly animate a circle to show that the thread isn't blocking our main thread.
    love.graphics.circle( 'line', 100 + math.sin( timer ) * 20, 100 + math.cos( timer ) * 20, 20 )
end

See Also

Other Languages