love-loader: load resources in a separate thread, easily

Showcase your libraries, tools and other projects that help your fellow love users.
User avatar
slime
Solid Snayke
Posts: 3161
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: love-loader: load resources in a separate thread, easily

Post by slime »

If you serialize the argument values and pass those to the thread, it would work for everything, right?

Something like:

Code: Select all

function SerializeArgs(...)
	local args = {}
	for i=1, select("#", ...) do
		local val = select(i, ...)
		if type(val) == "string" then
			args[i] = string.format("%q", val)
		else
			args[i] = tostring(val)
		end
	end
	return table.concat(args, ", ")
end

function UnserializeArgs(argstr)
	return loadstring("return "..argstr)()
end
Last edited by slime on Sun Jan 29, 2012 8:15 pm, edited 1 time in total.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: love-loader: load resources in a separate thread, easily

Post by kikito »

Not that easy - in some cases the parameters passed are userData. But thanks for the code.
When I write def I mean function.
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: love-loader: load resources in a separate thread, easily

Post by Robin »

But LÖVE objects can just be passed to other threads, right? So it would just take a Decoder as argument, which can be passed just as easily as an Image (AFAIK).
Jasoco wrote:It appears to be a license for usage of the music file in that folder which is an MP3 (Converted to OGG) of a remix from Mega Man 9 called "Astro Fusion" from the Galaxy Man stage.
Oh man, I didn't even look! I thought it was a binary file, and opening it would teach me nothing.
Help us help you: attach a .love.
User avatar
Jasoco
Inner party member
Posts: 3726
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: love-loader: load resources in a separate thread, easily

Post by Jasoco »

I think it should be labeled "License.txt" or "OCLicense.txt" or something more obvious.
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: love-loader: load resources in a separate thread, easily

Post by Robin »

Tru dat.
Help us help you: attach a .love.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: love-loader: load resources in a separate thread, easily

Post by kikito »

Regarding soundData: I'm really wondering if it makes sense at all to include the soundDatas created from 4 integers on this lib. Is that really a blocking call that benefits from loading in another thread?

I really think I need to understand this better before modifying the lib unnecessarily. I have created a separate post demanding explanations.
Jasoco wrote:I think it should be labeled "License.txt" or "OCLicense.txt" or something more obvious.
Will do. EDIT: Done.
When I write def I mean function.
User avatar
bartbes
Sex machine
Posts: 4946
Joined: Fri Aug 29, 2008 10:35 am
Location: The Netherlands
Contact:

Re: love-loader: load resources in a separate thread, easily

Post by bartbes »

kikito wrote:Is that really a blocking call that benefits from loading in another thread?
Not really. I mean it blocks, but it really only allocates some memory, and therefore takes barely any time.

As for the send/receive => set/get change, in the code I've written that's supposed to be portable I define local functions that either call send or set depending on the love version, and then use that. (Same goes for receive and get, of course.)

Code: Select all

local set
local get

if love._version_major > 0 or love._version_minor > 7 then
    set = function(thread, key, value)
        return thread:set(key, value)
    end
    get = function(thread, key)
        return thread:get(key)
    end
else
    set = function(thread, key, value)
        return thread:send(key, value)
    end
    get = function(thread, key)
        return thread:receive(key)
    end
end
(Untested, I may have borked the version check.)

EDIT: Something I thought of while looking at the code, perhaps you could implement a function that waits for the thread to finish, if it is not? It's something I've implemented in the past, where if someone was to skip the intro, it would just start loading all (remaining) resources in a blocking way.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: love-loader: load resources in a separate thread, easily

Post by kikito »

bartbes wrote:
kikito wrote:Is that really a blocking call that benefits from loading in another thread?
Not really. I mean it blocks, but it really only allocates some memory, and therefore takes barely any time.
I already figured that much on my cry for help in the support forum. I just have been a bit busy this week to post much or do any work on love-loader. But thanks for confirming.
bartbes wrote:As for the send/receive => set/get change, in the code I've written that's supposed to be portable I define local functions that either call send or set depending on the love version, and then use that. (Same goes for receive and get, of course.)
Makes sense. I don't like having to test for the concrete love version though. Seems a bit brittle. How about testing whether the thread has a method or not?

Code: Select all

local function set(thread, key, value)
  local f = thread.send or thread.set
  return f(thread, key, value)
end
And same with receive/get. Does it look right to you?
bartbes wrote:EDIT: Something I thought of while looking at the code, perhaps you could implement a function that waits for the thread to finish, if it is not? It's something I've implemented in the past, where if someone was to skip the intro, it would just start loading all (remaining) resources in a blocking way.
That goes pretty much against what I wanted to accomplish. The whole idea is not blocking the main thread while loading resources. But there is an alternative. The command that "starts the loading thread" is loader.start(finishCallback, loadedResourceCallback). They are both optional. But finishcallback is very recommended (in fact, in the initial version of love-loader it was mandatory).

One can check that everything has been loaded by setting a boolean, or changing the game state from "loading" to "finishedLoading" in the finishCallback. While it is loading, you can play an animation of a dancing fish, or what have you, and it will play without hiccups.

A much worse alternative, but one that also works, would be comparing love.loadedCount with love.resourceCount on each update cycle. When love.loadedCount == love.resourceCount, all files have been loaded. But your code will be much cleaner if you just use finishCallback to perform the action of that if.

My point is - if you want to block the main thread while loading, it's better not using love-loader at all. Its core idea is avoiding blocking on the main thread.

The second loader.start parameter is a callback called every time an individual resource is finished loading. It receives some parameters, like what kind of resource was it, what was its name, and where it is stored. If you open the demo in the console, you will see that loadedResourceCallback prints lots of stuff on it.

Regarding the loading of imageData/soundData: I'm pretty sure that if I'm to support those, soundDatas will only be "supported" while being created from a path or a decoder. I'm also investigating whether it would be possible to get a soundData or imageData from a source or image in an issue. Will update this when I know more.
When I write def I mean function.
User avatar
bartbes
Sex machine
Posts: 4946
Joined: Fri Aug 29, 2008 10:35 am
Location: The Netherlands
Contact:

Re: love-loader: load resources in a separate thread, easily

Post by bartbes »

Code: Select all

local function set(thread, key, value)
  local f = thread.send or thread.set
  return f(thread, key, value)
end
I don't know how well userdata behaves with these manipulations, but if it works, that'd be fine.
kikito wrote: That goes pretty much against what I wanted to accomplish. [snip]
I know, my reasoning was that sometimes when having loaded stuff in a parallel fashion for a while, you might want to simply cut to the chase and wait, I guess with your code that doesn't really matter too much, but my loader spread things out over the available loading time.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: love-loader: load resources in a separate thread, easily

Post by kikito »

bartbes wrote:I know, my reasoning was that sometimes when having loaded stuff in a parallel fashion for a while, you might want to simply cut to the chase and wait, I guess with your code that doesn't really matter too much, but my loader spread things out over the available loading time.
Just to make sure we understand each other: changing the game state on the "finishedLoading" callback accomplishes just that; you stay on the "loading state" until everything is loaded. But love.update() and love.draw() are still being called every frame.

EDIT: I made a new (alpha for now) version. Please find modified demo for that version below.

On this new version:
  • I have changed names of lots of internal things to make the code more clear
  • I have added support for soundData(only when creating it from a path or decoder) and ImageData
  • I have added forward-compatibility with 0.8.x thread methods
  • After loading, the spacebar will play a source loaded directly with love-loader, while the intro key will play a source created from a soundData loaded with love-loader.
I'd be especially grateful if you could please test in in 0.8.x, since I don't have it yet.

If everything goes well, I'll release the new version with those enhancements tomorrow.
Attachments
love-loader.love
(4.27 MiB) Downloaded 397 times
When I write def I mean function.
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest