Domanda
Sto avendo qualche difficoltà a capire come utilizzare coroutines correttamente con luabind.C'è una funzione basato su modelli:
template<class Ret>
Ret resume_function(object const& obj, ...)
Dove (Ret
) dovrebbe contenere i valori passati al yield
da Lua.
Il mio attuale punti di confusione, sono:
- Cosa succede se la funzione restituisce invece di chiamare
yield
?Nonresume_function
restituire il valore restituito dalla funzione? - Come fare per utilizzare questa funzione se non si sa in anticipo quale (o quanti) i parametri sono trasferiti a
yield
?Per esempio, se ci sono molteplici possibilità di cedere le funzioni che la funzione chiamata. - Qual è il tipo di
Ret
se sono di più i valori sono passato ayield
?
Io sono del tutto erroneo come tutto questo funziona?Mi immagino qualcosa di simile a questo.Il Lua lato:
local img = loadImage("foo.png")
loadImage
sarebbe una funzione C++ che richiede il caricamento dell'immagine in un altro thread e poi chiama lua_yield
, e qualche tempo dopo luabind::resume_function
viene chiamato con img
come parametro.
Devo passare "foo.png"
per yield
come parametro?Per una funzione diversa prima di chiamare yield
, e quindi non passano mai di valori da yield
?Qual è il modo giusto per la struttura di questo?Ovviamente sto fraintendimento qualcosa qui.
Soluzione
Dove (Ret) deve contenere i valori passati alla resa da Lua.
Luabind supporta solo i valori di ritorno, in modo che solo restituisce il primo valore passato coroutine.yield
.
Cosa succede se la funzione restituisce piuttosto che chiamare la resa?Non resume_function restituire il valore restituito dalla funzione?
Sì, si ottiene il valore di ritorno.
Come fare per utilizzare questa funzione se non si sa in anticipo quale (o quanti) i parametri sono trasferiti alla resa?Per esempio, se ci sono molteplici possibilità di cedere le funzioni che la funzione chiamata.
Che a voi;sono le funzioni.È necessario sviluppare convenzioni su ciò che il cedimento funzione(s) riceve come parametri, e che la funzione di riprendere la coroutine fornisce.
Qual è il tipo di Ret se più valori vengono passati alla resa?
Quello che si desidera essere.È il parametro di modello.Il numero di parametri a una funzione non ha alcun effetto sul ritorno dei valori che la funzione fornisce.
Ricordate:Funzioni Lua prendere qualsiasi numero di parametri e può restituire nulla.Tutti Luabind può fare è passare lungo i parametri di dare e di convertire il valore restituito dalle funzioni Lua in quello che ci si aspetta che il valore di ritorno di essere.Luabind farà tipo di controllo sul valore di ritorno di corso.Ma è la vostra responsabilità di assicurarsi che le funzioni di rendimento/ritorno restituirà qualcosa che è trasformabile per il tipo di utente fornisce per Ret.
loadImage sarebbe una funzione C++ che richiede il caricamento dell'immagine in un altro thread e quindi chiama lua_yield, e qualche tempo dopo luabind::resume_function viene chiamato con img come parametro.
Se si utilizza Luabind non chiamare mai lua_yield
direttamente.Il modo corretto per cedere in Luabind è quello di aggiungere un attributo di una funzione di registrazione che sarà resa ogni volta che viene restituito dalla funzione.La sintassi è la seguente:
module(L)
[
def("do_thing_that_takes_time", &do_thing_that_takes_time, yield)
];
Che è una funzione C++ che rese necessario sempre la resa.Questa è una limitazione di Luabind, come con regolare Lua, è possibile scegliere se cedere o meno come si vede in forma.
Non dimenticate, inoltre, che Lua coroutines non sono la stessa cosa come reale thread.Non sono di prelazione;essi solo eseguire quando lo si dica esplicitamente per coroutine.resume
o l'equivalente di riprendere la chiamata.
Inoltre, si dovrebbe mai eseguire la stessa Lua istanza da più di C/C++ thread;Lua non è thread-safe, all'interno della stessa istanza (che più o meno significa che la stessa lua_State oggetto).
Quello che sembri voler fare è di avere Lua chiamare qualche funzione in C++ che di per sé genera un thread per fare un po di processo, quindi il codice Lua attendere che il thread è completa e quindi riceve la sua risposta.
Per fare questo, è necessario dare il Lua script di un oggetto che rappresenta il C++ thread.Così il vostro loadImage
la funzione non dovrebbe essere utilizzando coroutine logica;dovrebbe restituire un oggetto che rappresenta il C++ thread.Lua script può chiedere l'oggetto se non è stata completata, e se si dispone, è in grado di interrogare i dati da esso.
Il luogo in cui coroutines può entrare in gioco qui è se non si desidera che il Lua script di aspettare fino a quando questo è finito.Che è, si chiama il Lua script ogni tanto, ma se il C++ thread non è fatto, allora si dovrebbe solo tornare.In questo caso, si può fare qualcosa di simile a questo:
function loadImageAsCoroutine(imageFilename)
local cppThread = cpp.loadImage(imageFilename);
local function threadFunc(cppThread)
if(cppThread:isFinished()) then
local data = cppThread:GetImage();
return data;
else
coroutine.yield();
end
end
local thread = coroutine.create(threadFunc);
local errors, data = assert(coroutine.resume(thread, cppThread));
if(coroutine.status(thread) == "dead") then
return data;
else
return thread;
end
end
Questa funzione restituisce una coroutine o i dati dell'immagine stessa.I chiamanti di questa funzione deve controllare il tipo;se il tipo è "filo", quindi il C++ thread non è ancora finito.In caso contrario, è l'immagine di dati.
I chiamanti di questa funzione è in grado di pompare la coroutine quanto si vuole con un equivalente di coroutine.resume
(se è luabind::resume_function o qualsiasi altra cosa).Ogni volta, controllare il valore di ritorno.Sarà nil
se il C++ thread non ha ancora finito, e non nil
altrimenti.