Ressourcen-Manager und Operator overloading



  • Ich bastle momentan an einem Spiel und möchte eine Klasse schreiben, deren Objekte aus einer Datei geladene Ressourcen (z.B. Sound, Grafik etc.) speichern. Beim Erstellen des Objekts sollte geprüft werden, ob die angefragte Ressource schon im RAM ist und dann gegebenenfalls einen pointer auf die bestehende Ressource zurückgeben, ansonsten sollte ein neues Objekt erstellt werden.

    Ich habe mich gefragt, ob man so etwas möglicherweise mit einem überladenen new-operator machen könnte, falls ja, vielleicht kann mich jemand in die richtige Richtung dirigieren?



  • Vermutlich sind smart pointers und eine getObject-Funktion je Ressource-Typ mit einer map dahinter das Mittel der Wahl.



  • Das hört sich an als ob du sowas Proxies für deine Ressourcen haben möchtest. operator new brauchst du dazu aber nicht zu überladen.



  • volkard schrieb:

    Vermutlich sind smart pointers und eine getObject-Funktion je Ressource-Typ mit einer map dahinter das Mittel der Wahl.

    An sowas hatte ich auch zuerst gedacht. Allerdings muss ich dann bei jeder Ressourcenanforderung zuerst mit getObject prüfen, obs schon geladen ist und falls nicht dann erst laden. Hatte halt gedacht es wäre eleganter wenn sich das Objekt darum selbst kümmern würde, in etwa so (Pseudocode):

    class Resource {
    	string pfad; // pfad zum file
    	int ref_count; // anzahl der referenzen aufs objekt
    	static list<Resource *> liste; // liste mit allen objekten
    
    	operator new(string pfad) {
    		Resource *tmp = suche element aus liste mit element.pfad == pfad;
    		if (!tmp) {
    			allociere speicher und rufe constructor auf;
    			füge neues objekt zur liste hinzu;
    		} else
    		{
    			tmp.ref_count++;
    			return tmp;
    		}
    	}
    
    	operator delete {
    		ref_count--;
    		if (ref_count == 0) {
    			entferne objekt aud liste;
    			rufe destructor auf;
    			gib speicher für objekt frei;
    		}
    	}
    
    	Resource(string pfad) {
    		lade ressource aus pfad datei;
    		ref_count = 1;
    	}
    
    	~Resource() {
    		gib die geladenen daten frei;
    	}
    
    };
    
    // irgendwo später
    Resource *res = new Resource(pfad_zum_file);
    

    Allerdings ist das warscheinlich nicht möglich...?! Bin leider nicht sehr bewandert mit dem Thema C++ Speicheranforderung/op overloading.



  • Avantarius schrieb:

    volkard schrieb:

    Vermutlich sind smart pointers und eine getObject-Funktion je Ressource-Typ mit einer map dahinter das Mittel der Wahl.

    An sowas hatte ich auch zuerst gedacht. Allerdings muss ich dann bei jeder Ressourcenanforderung zuerst mit getObject prüfen, obs schon geladen ist und falls nicht dann erst laden.

    Oh. Ja, hast recht. map ist zwar sehr schnell, aber es dem Compiler zu geben ist natürlich schneller und sicherer auch noch.



  • du hast die Funktionalität von operator new und delete offenbar nicht verstanden. Die sind einzig und allein dazu da um Speicher zu reservieren, nicht um dir deine selbstdefinierten Ressourcen zu beschaffen.
    Wenn die Klasse Resource einen op new überlädt, ist der dazu da um Speicher für neue Resource-Objekte zu beschaffen - nicht für die Ressourcen die von den jeweilgen Resource-Objekten verwaltet werden.



  • pumuckl schrieb:

    du hast die Funktionalität von operator new und delete offenbar nicht verstanden. Die sind einzig und allein dazu da um Speicher zu reservieren, nicht um dir deine selbstdefinierten Ressourcen zu beschaffen.
    Wenn die Klasse Resource einen op new überlädt, ist der dazu da um Speicher für neue Resource-Objekte zu beschaffen - nicht für die Ressourcen die von den jeweilgen Resource-Objekten verwaltet werden.

    Wie gesagt, bin nicht recht bewandert in der ganzen Sache (bin erst vor kurzem "zwangsläufig" auf C++ umgestiegen) 😃 . Auf jeden Fall danke für die Info, war genau das was ich wissen wollte.
    Gibts vielleicht eine andre Möglichkeit, um das ähnlich elegant zu lösen wie von mir (theorethisch) vorgeschlagen, oder sollte ich es doch besser mit volkard's Vorschlag probieren?



  • Keine Ahnung, ob's was hilft.

    class ResourceProvider {
      string pfad; // pfad zum file
      int ref_count; // anzahl der referenzen aufs objekt
      ResourceImp* data;
      //static list<Resource *> liste; //braucht keiner
      void lock() {
        if(refcount==0)
          data=ladeResource(pfad);
        ++refcount;
      }
      void unlock(){
        --refcount;
        //if(refcount==0)
        //  delete data;
      }
    };
    class Resource {
      RessourceProvider* prp;
      Resource(ResourceProvider& rp)
      :prp(&rp) {
        rp->lock();
      }
      ~Resource() {
        rp->unlock();
      }
      void tuwas(){
        pr->data->tuwas();
      }
    };
    
    // irgendwo später
    ResourceProvider hintergrundbildHalter("higru.png");
    
    //immer wieder mal
    Resource hg(hintergrundbildHalter);
    hg.tuwas();
    


  • volkard schrieb:

    Keine Ahnung, ob's was hilft.

    Schaut auf den ersten Blick ganz gut aus. Werde deinen Code jetzt mal austesten.

    Danke an alle für die schnelle Hilfe! 👍


Anmelden zum Antworten