Aiuto - Cerca - Utenti - Calendario
Versione completa: Spiegazione codice
.: GBArl.it :. News sulle Console Nintendo - Emulazione - Flash Cards - Trainer > Discussioni Console Nintendo > Programmazione & ROM Hacking (Nintendo)
Ciozun
Salve,

starei cercando di capire come implementare dei thread in un homebrew 3DS, ma nell'esempio di devkitPRO ho trovato diverse cose che non mi sono chiare. Ecco qui il codice con dei commenti riportanti i miei dubbi:

CODICE
#include <string.h>
#include <stdio.h>
#include <3ds.h>

#define NUMTHREADS 3
#define STACKSIZE (4 * 1024)

volatile bool runThreads = true; // perché l'ha creata volatile?

void threadMain(void *arg) // è un puntatore... non mi sembra. "arg" sta per? E' una variabile normale (che poi void???) o è una parola riservata?
{
    u64 sleepDuration = 1000000ULL * (u32)arg;  // 1000000ULL??? (u32)arg che vuol dire? (so per cosa sta u32)
    int i = 0;
    while (runThreads)
    {
        printf("thread%d says %d\n", (int)arg, i++);
        svcSleepThread(sleepDuration);
    }
}

int main(int argc, char** argv)
{
    gfxInitDefault();
    consoleInit(GFX_TOP, NULL);

    Thread threads[NUMTHREADS];
    int i;
    s32 prio = 0;
    svcGetThreadPriority(&prio, CUR_THREAD_HANDLE); // tutta la linea
    printf("Main thread prio: 0x%lx\n", prio);

    for (i = 0; i < NUMTHREADS; i ++)
    {
        // The priority of these child threads must be higher (aka the value is lower) than that
        // of the main thread, otherwise there is thread starvation due to stdio being locked.
        threads[i] = threadCreate(threadMain, (void*)((i+1)*250), STACKSIZE, prio-1, -2, false); // tutta la linea
        printf("created thread %d: %p\n", i, threads[i]);
    }

    // Main loop
    while (aptMainLoop())
    {
        gspWaitForVBlank();
        hidScanInput();

        u32 kDown = hidKeysDown();
        if (kDown & KEY_START)
            break; // break in order to return to hbmenu

        // Flush and swap framebuffers
        gfxFlushBuffers();
        gfxSwapBuffers();
    }

    // tell threads to exit & wait for them to exit
    runThreads = false;
    for (i = 0; i < NUMTHREADS; i ++)
    {
        threadJoin(threads[i], U64_MAX); // Join dovrebbe interrompere il thread, giusto? U64_MAX??
        threadFree(threads[i]); // Sarebbe?
    }

    gfxExit();
    return 0;
}


Grazie!
Cusy
ULL = Unsigned Long Long, ovvero almeno 64 bit.
void* è un puntatore senza specifica di tipo, ergo a threadMain può essere passata una qualsiasi zona di memoria.
Join non è una funzione di terminazione di un thread (quella sarebbe stop o interrupt, in base al tipo di linguaggio usato), quanto di attesa di terminazione di quel thread per poi processarne il risultato.
Non sono pratico della programmazione 3DS (che per quanto posti sembra una cosa C-Like) quindi provo ad indovinare il resto:
- La prima funzione ti ritorna la priority di un thread, per capire con che priorità andrà in esecuzione sulla CPU
- La seconda istanzia un thread nella memoria allocandolo (probabilmente con una malloc o qualcosa di simile)
- La terza libera la memoria una volta che il thread è finito (altrimenti rimarrebbe occupata e andresti presto out of memory).

Per il resto sto vedendo che ultimamente posti tanta roba in ambito programmazione. Se non sei pratico di linguaggi non ad oggetti forse ti conviene dare prima una occhiata al funzionamento di qualcosa di basilare come C/C++ per capire le dinamiche di malloc-free, le direttive al compilatore, i define e cose simili wink.gif

EDIT: Quasi dimenticavo, volatile indica al compilatore che quella variabile può essere cambiata tra un accesso e l'altro e lo costringe a controllarla di volta in volta (es: un thread secondario la modifica e il thread principale deve controllarla per essere sicuro di leggere il valore corretto, non può asserire non sia stata modificata giusto perché lui non l'ha toccata).
Rinnegatamante
Trovo il wrapper thread recentemente introdotto nelle ctrulib abbastanza dispersivo (preferisco di gran lunga utilizzare direttamente le syscall relative al servizio svc [ https://github.com/smealum/ctrulib/blob/mas...clude/3ds/svc.h ] ) comunque sia, come consigliato da Cusy, prima di guardare a thread secondari e programmazione concorrenziale sarebbe buona norma partire da roba ben più basilare.

Che genere di homebrew staresti sviluppando che richiede l'utilizzo di un thread secondario?
Ciozun
CITAZIONE (Rinnegatamante @ Monday 25 January 2016 - 02:31) *
Trovo il wrapper thread recentemente introdotto nelle ctrulib abbastanza dispersivo (preferisco di gran lunga utilizzare direttamente le syscall relative al servizio svc [ https://github.com/smealum/ctrulib/blob/mas...clude/3ds/svc.h ] ) comunque sia, come consigliato da Cusy, prima di guardare a thread secondari e programmazione concorrenziale sarebbe buona norma partire da roba ben più basilare.

Che genere di homebrew staresti sviluppando che richiede l'utilizzo di un thread secondario?


L'anno scorso creai un giochino per Windows in Pascal, che utilizzando il prompt, simulava una navicella la quale doveva evitare una serie di asteroidi e totalizzare un punteggio.
"All'epoca" non conoscevo i thread (ed i sottoprogrammi), neanche concettualmente, e feci un casino assurdo per creare l'avanzamento simultaneo degli astreoidi ed il movimento della navetta.
Ora, sapendo l'esistenza dei thread, vorrei implementarli per rendermi il lavoro di conversione più facile, dato che si, il codice è mio, ma non avendo scritto mezzo commento, non capisco tutto.
DaG
CITAZIONE (Ciozun @ Monday 25 January 2016 - 14:13) *
CITAZIONE (Rinnegatamante @ Monday 25 January 2016 - 02:31) *
Trovo il wrapper thread recentemente introdotto nelle ctrulib abbastanza dispersivo (preferisco di gran lunga utilizzare direttamente le syscall relative al servizio svc [ https://github.com/smealum/ctrulib/blob/mas...clude/3ds/svc.h ] ) comunque sia, come consigliato da Cusy, prima di guardare a thread secondari e programmazione concorrenziale sarebbe buona norma partire da roba ben più basilare.

Che genere di homebrew staresti sviluppando che richiede l'utilizzo di un thread secondario?


L'anno scorso creai un giochino per Windows in Pascal, che utilizzando il prompt, simulava una navicella la quale doveva evitare una serie di asteroidi e totalizzare un punteggio.
"All'epoca" non conoscevo i thread (ed i sottoprogrammi), neanche concettualmente, e feci un casino assurdo per creare l'avanzamento simultaneo degli astreoidi ed il movimento della navetta.
Ora, sapendo l'esistenza dei thread, vorrei implementarli per rendermi il lavoro di conversione più facile, dato che si, il codice è mio, ma non avendo scritto mezzo commento, non capisco tutto.


Beh, così al volo mi pare di capire che in realtà "quel casino assurdo" è più giusto di quello che hai intenzione di fare adesso. In un gioco di solito è presente un loop principale in cui vengono aggiornate prima tutte le posizioni degli oggetti presenti sulla scena e poi renderizzati solo quelli presenti su schermo.
Mi pare di aver capito che tu, adesso, vorresti fare un thread per ogni asteroide presente su schermo, ma te lo sconsiglio vivamente, anche perché questo non ti faciliterebbe per nulla la vita visto che ti imbatteresti nella programmazione concorrente; probabilmente ti troveresti anche nella situazione che qualche asteroide avanza più velocemente di qualcun altro, in maniera non voluta.
Ciozun
CITAZIONE (DaG @ Monday 25 January 2016 - 14:19) *
CITAZIONE (Ciozun @ Monday 25 January 2016 - 14:13) *
CITAZIONE (Rinnegatamante @ Monday 25 January 2016 - 02:31) *
Trovo il wrapper thread recentemente introdotto nelle ctrulib abbastanza dispersivo (preferisco di gran lunga utilizzare direttamente le syscall relative al servizio svc [ https://github.com/smealum/ctrulib/blob/mas...clude/3ds/svc.h ] ) comunque sia, come consigliato da Cusy, prima di guardare a thread secondari e programmazione concorrenziale sarebbe buona norma partire da roba ben più basilare.

Che genere di homebrew staresti sviluppando che richiede l'utilizzo di un thread secondario?


L'anno scorso creai un giochino per Windows in Pascal, che utilizzando il prompt, simulava una navicella la quale doveva evitare una serie di asteroidi e totalizzare un punteggio.
"All'epoca" non conoscevo i thread (ed i sottoprogrammi), neanche concettualmente, e feci un casino assurdo per creare l'avanzamento simultaneo degli astreoidi ed il movimento della navetta.
Ora, sapendo l'esistenza dei thread, vorrei implementarli per rendermi il lavoro di conversione più facile, dato che si, il codice è mio, ma non avendo scritto mezzo commento, non capisco tutto.


Beh, così al volo mi pare di capire che in realtà "quel casino assurdo" è più giusto di quello che hai intenzione di fare adesso. In un gioco di solito è presente un loop principale in cui vengono aggiornate prima tutte le posizioni degli oggetti presenti sulla scena e poi renderizzati solo quelli presenti su schermo.
Mi pare di aver capito che tu, adesso, vorresti fare un thread per ogni asteroide presente su schermo, ma te lo sconsiglio vivamente, anche perché questo non ti faciliterebbe per nulla la vita visto che ti imbatteresti nella programmazione concorrente; probabilmente ti troveresti anche nella situazione che qualche asteroide avanza più velocemente di qualcun altro, in maniera non voluta.



Beh allora seguii il concetto che stai enunciando tu adesso. linguetta.gif
Quindi mi consigli di creare un unico loop enorme dove mettere tutto dentro? Non verrà troppo intricato?
Aurelio
CITAZIONE (Ciozun @ Monday 25 January 2016 - 14:36) *
Beh allora seguii il concetto che stai enunciando tu adesso. linguetta.gif
Quindi mi consigli di creare un unico loop enorme dove mettere tutto dentro? Non verrà troppo intricato?


Il multithreading è bene usarlo quando vuoi eseguire diverse operazioni totalmente indipendenti. Nel tuo caso col multithreading avresti problemi di desincronizzazione tra i vari asteroidi...
DaG
CITAZIONE (Ciozun @ Monday 25 January 2016 - 14:36) *
Beh allora seguii il concetto che stai enunciando tu adesso. linguetta.gif
Quindi mi consigli di creare un unico loop enorme dove mettere tutto dentro? Non verrà troppo intricato?


Alla fine non è così intricato se utilizzi bene il polimorfismo, in fondo è così che vengono fatti tutti i giochi attualmente. Ovvio che i giochi moderni siano tutti multithreading, ma per altri motivi (ad esempio un thread per i calcoli fisici, un thread per il rendering, ecc...).

Io ti consiglio di fare un'interfaccia "IUpdatable" con un metodo update() che verrà poi implementata da ogni oggetto che ha bisogno di muoversi sullo schermo. Poi ti crei una lista di questi oggetti di tipo IUpdatable e dal loop principale richiami il relativo metodo update() in cui ci saranno tutti gli aggiornamenti da fare per l'oggetto in questione.
Questa è la versione 'lo-fi' del forum. Per visualizzare la versione completa con molte più informazioni, formattazione ed immagini, per favore clicca qui.
Invision Power Board © 2001-2024 Invision Power Services, Inc.