Pattern di mailbox con argomenti variabili in C ++

1

In un gioco che sto sviluppando, il thread della GUI sta catturando le azioni degli utenti e il thread della simulazione è responsabile della gestione e della risposta ad essi.

Per ridurre al minimo la complessità e il ritardo, ho predefinito tutti i possibili tipi di azione che l'utente può attivare e ho creato una serie di "opcodes". Il thread GUI imposta "successo" al array[opcode] relativo in tempo reale e il thread di simulazione, nella posizione corretta nel codice, campiona array[opcode] e agisce su array[opcode].data se array[opcode].happened == true .

Il problema è che ogni opcode ha un diverso set (dimensioni, tipi) di argomenti. Attualmente sto solo permettendo argomenti di stringa, e li analizzo nel thread di simulazione - non molto efficiente. Un'altra soluzione che mi viene in mente è la classe di codice operativo polimorfo e che si fonde dinamicamente nel thread di simulazione - brutto.

Ho chiamato questo "modello di mailbox", ma sono sicuro che qualcuno più intelligente l'ha già risolto (e nominato). Un puntatore a una soluzione più elegante sarebbe fantastico.

    
posta liorda 30.12.2014 - 19:34
fonte

3 risposte

1

Invece di usare un array, potresti usare vector<EventClass> (dove EventClass è qualunque sia il tuo attuale array). Quindi puoi semplicemente scorrere il vettore ed elaborare ogni evento finché non è vuoto, supponendo che il thread della GUI non aggiungerà eventi mentre il thread di simulazione li sta processando (questo potrebbe essere ottenuto con mutex di qualche tipo) ... quindi devi solo elaborare gli eventi attivi, dal momento che il vettore conterrà solo eventi che sono accaduti. Potrebbe funzionare così:

class EventClass {
    EventClass(int _o, string _d) : opcode(_o), data(_d) {}
    int opcode;
    string data;
}
//somewhere available to both threads, declare the vector:
vector<EventClass> ActiveEvents;

void GUI_Process_Events(){
    //...
    ActiveEvents.push_back(The_Event_That_Just_Happened);
}

void Simulation_Process_Events(){
    //this will iterate through all the active events and
    //act on each of them
    for(int i = 0; i < ActiveEvents.size(); i++){
        //this gets the item at the back of the vector
        EventClass Current_Event = ActiveEvents.back();

        //assuming Process(EventClass e) will process the event
        Process(Current_Event);

        //this will then remove the event from the vector
        ActiveEvents.pop_back();
    }
}

Se necessario, puoi usare un vettore di puntatori sugli oggetti EventClass (ma ovviamente devi anche distruggerli):

class EventClass {
    EventClass(int _o, string _d) : opcode(_o), data(_d) {}
    int opcode;
    string data;
}
//somewhere available to both threads, declare the vector:
vector<EventClass*> ActiveEvents;

void GUI_Process_Events(){
    //...
    ActiveEvents.push_back(PointerTo_The_Event_That_Just_Happened);
}

void Simulation_Process_Events(){
    //this will iterate through all the active events and
    //act on each of them
    for(int i = 0; i < ActiveEvents.size(); i++){
        //this gets the item at the back of the vector
        EventClass* Current_Event = ActiveEvents.back();

        //assuming Process(EventClass e) will process the event
        Process(Current_Event);

        //delete the object pointed to by the element in the vector
        delete Current_Event;

        //this will then remove the event from the vector
        ActiveEvents.pop_back();
    }
}
    
risposta data 22.08.2017 - 22:35
fonte
0

I predefined all possible action types the user may trigger, and created an array of "opcodes".

Utilizza un struct o class invece di un array. Quindi puoi memorizzare diversi tipi per ogni azione della GUI.

Se si desidera preservare la ricerca basata su indici, è possibile utilizzare a std::tuple invece.

Ricorda che una matrice memorizza una raccolta omogenea di dimensioni fisse (cioè nota al momento della compilazione), mentre una struttura memorizza una raccolta eterogenea di dimensioni fisse.

    
risposta data 21.06.2017 - 05:19
fonte
0

La prima cosa che mi viene in mente è di fare

struct Data
{
   //enter the common data here
};

struct OpcodeData: public Data
{
   //enter opcode specific data here
};

e quindi il tuo array[opcode].data sarebbe un puntatore di tipo Data * effettivamente assegnato a un'istanza di OpcodeData * .

Ma poi di nuovo - hai davvero bisogno di avere i dati in un array? Perché non avere solo variabili opcode1Data, opcode2Data ecc.?

O ancora meglio: i dati potrebbero essere raggruppati in base al loro significato (fisicaDato, movimentoData, ecc.) anziché dall'opcode?

    
risposta data 20.06.2017 - 12:40
fonte

Leggi altre domande sui tag