Lua/Love2D Resource Loader (Queue) I made this resource queue in Love2D.

function GameState:queue(file, arg)
    self.res.loaded = self.res.loaded + 1;
    self.res.queue[self.res.loaded] = {f = file, t = game.getResourceType(file), id = self.res.loaded, s = arg};
    game.log("Resource Queued: "..file);
    return {f = self.res.loaded, t = game.getResourceType(file), id = self.res.loaded, s = arg};
end

function GameState:loadQueue(loader, post)
    self.post = post or function() self.state = self.prevState end;

    game.log("Loading Resource Queue...");

    queueThread = love.thread.newThread("queue.lua");
    queueChannel = love.thread.getChannel("queue");

    local fonts = {};

    for k, v in pairs(self.res.queue) do
        if (not v or not v.f or not v.t) then goto continue end;
        if (v.t ~= self.RESOURCE_FONT) then
            queueChannel:push(v);
        else
            fonts[k] = v;
        end
        ::continue::
    end

    for k, v in pairs(fonts) do
        self.res.fnt[k] = love.graphics.newFont(v.f, v.s);
        print("Loaded Resource: "..v.f);
    end

    queueChannel:push(table.size(self.res.queue)-table.size(fonts));

    if (table.size(self.res.queue)-table.size(fonts) &gt; 0) then
        queueThread:start();
    else
        queueChannel = nil;
        queueThread = nil;
        return;
    end

    self.state = self.STATE_LOADING
end


The thread:

require "love.image"
require "love.audio"
require "love.sound"
require "love.timer"

queue = {};
img = {};
snd = {};
local queueChannel = love.thread.getChannel("queue");

local pop = queueChannel:pop();

while (type(pop) ~= "number" and pop) do
    queue[pop.id] = pop;
    pop = queueChannel:pop();
end

for k, v in pairs(queue) do
    if (not v or not v.f or not v.t) then print("Resource Load Failed!"); goto continue; end;

    if (v.t == 0) then -- image
        img[k] = love.image.newImageData(v.f);
        queueChannel:supply({data = img[k], t = 0, id = k, s = v.s});
    end
    if (v.t == 1) then -- sound
        snd[k] = love.audio.newSource(v.f, "static");
        queueChannel:supply({data = snd[k], t = 1, id = k, s = v.s});
    end
    ::continue::
    queue[k] = nil;
    print("Loaded Resource: "..v.f);
    love.timer.sleep(0.01);
end

queueChannel:clear();
queueChannel:push(true);

return;


Handling while loading resources:

if (self.state == self.STATE_LOADING) then
    local e = queueThread:getError();
    if (e ~= nil) then
        print("Thread: "..e)
    end

    local r = queueChannel:peek();
    if (type(r) == "table" and r and r.data and r.t) then
        if (r.t == self.RESOURCE_IMAGE) then
            if (r.s) then
                love.graphics.setDefaultFilter(r.s, r.s);
            end
            self.res.img[r.id] = love.graphics.newImage(r.data);
        end
        if (r.t == self.RESOURCE_SOUND) then
            self.res.snd[r.id] = r.data;
        end
        queueChannel:pop();
    end

    if (queueChannel:peek() == true and type(queueChannel:peek()) == "boolean") then
        self.post();
        game.log("Finished Loading Resources.");
    end
end


If there's any bad habits, or anything that could be improved, please let me know.
In Lua, it's not necessary to separate statements by a semicolon (it's not even necessary to do it when writting several statements in the same line). However it's possible to do it.

In this snippet:


for k, v in pairs(self.res.queue) do
    if (not v or not v.f or not v.t) then goto continue end;
    if (v.t ~= self.RESOURCE_FONT) then
        queueChannel:push(v);
    else
        fonts[k] = v;
    end
    ::continue::
end



You're using pairs in several parts of the code to iterate tables which are actually arrays. Variable self.res.queue is an array since:


function GameState:queue(file, arg)
    self.res.loaded = self.res.loaded + 1;
    self.res.queue[self.res.loaded] = &lt;object&gt;;
end



In the cases a table is actually an array is preferred to use ipairs because is way more faster than pairs. In addition to that, it tells other people reading the code the table is actually an array (which is a valuable hint in a dynamic language such as Lua).

At the bottom of GameState:loadQueue:


if (table.size(self.res.queue)-table.size(fonts) &gt; 0) then
    queueThread:start(); else
    queueChannel = nil;
    queueThread = nil;
    return;
end

self.state = self.STATE_LOADING



The return statement in the else branch can be removed if you move self.state up to the then branch. The semantics hold as either queueThread:start() or not.

if (table.size(self.res.queue)-table.size(fonts) &gt; 0) then
    self.state = self.STATE_LOADING;
    queueThread:start();
else
    queueChannel = nil;
    queueThread = nil;
    return;
end