none
Shared memory - Singleton - Queue RRS feed

  • Frage

  • Hallo Forum

    ich schreibe zur Zeit an einer etwas aufwendigeren Anwendung. Diese beinhaltet mehrere Pools, welche u.a. fleißig Threads erzeugen, welche dann meine Arbeit erledigen sollen.
    Die Threads idlen suspended vor sich hin und werden von entsprechenden Threadshedulern verwaltet. All das funktioniert auch wunderbar.

    Um den Threads Arbeit zuzuteilen, benutze ich threadsafe queues.
    Diese queues sind alle im shared memory abgelegt, bzw. sollten.
    -> Ein Objekt von einem Singleton Template abgeleitet. Dieses Template ist ebenfalls threadsafe.
    Beim Zugriff auf dieses Template bekommen die Threads allerdings immer einen Pointer auf ein eigenes Objekt und damit auch keinen Zugriff auf abgelegte Arbeit.
    Ist mein Gedankengang völlig falsch? Wenn ein Singleton Objekt nur einmal erzeugt wird und ein Zeiger darauf global gehalten wird, dann kann doch jeder Thread des Prozesses, weil gleicher Adressraum, auf die Daten zugreifen?

    Ich dachte zuerst, es stimmt etwas mit der Intialisierung nicht, allerdings wird auch tatsächlich nur ein Objekt meiner Singleton erzeugt, dennoch greift jeder Thread auf eine andere Adresse zu, an der er keine Daten findet (allerdings greift er nicht ins Leere, er kann die nicht statischen Methoden der Singleton aufrufen).

    Würde mich über kurze Antwort freuen, kann auch gerne noch etwas Code posten.

    Grüße
    Mittwoch, 15. September 2010 12:40

Antworten

Alle Antworten

  • Jeder Thread  kann auf den gesamten Prozessraum zugreifen.
    Shared Memory brauchst Du nicht. Warum auch, der wäre nur notwendig, wenn Du zwischen Prozessen Daten austauscht.

    Suspended Threads, halte ich aber für einen falschen Weg. Einen Thread Suspenden kann schnell zu Deadlocks führen.

    Ich benutze hier Events in jedem Thread.
    - Ein Scheduler erzeugt n-Worker Threads.
    - Diese werden in einer Liste gespeichert
    - Gibt es Arbeit, holt der Scheduler den nächsten freien Worker aus der Liste, gibt ihm einen Zeiger auf die Arbeitsdaten und setzt ein Event "Start Work / Warte auf Arbeit".
    - Ansonsten wartet der Scheduler nur darauf, dass neue Arbeit anliegt, oder einer der Workerthreads die Arbeit beendet (wieder ein Event).
    - Der Thread geht bei beendeter Arbeit in den "Start Work / Warte auf Arbeit" zustand.
    - Der Scheduler nimmt das Ergebnis und schiebt den Thread in die Liste der freien Worker.

    HTH


    Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
    Mittwoch, 15. September 2010 13:17
    Moderator
  • Dann hast Du wohl noch ein Fehler in Deinem Code.
    Ohne den relevanten Teil zu zeigen, ist es schwer zu raten, was DU falsch gemacht hast.

    PS: Warum verwendest Du nicht die PPL? Die macht schon alles und das noch viel performanter, als Du es Dir je ausdenken könntest (Stichwort: WorkStealing)...

    http://msdn.microsoft.com/de-de/magazine/dd434652.aspx
    http://msdn.microsoft.com/en-us/library/dd492418.aspx
    http://blogs.msdn.com/b/somasegar/archive/2008/11/21/c-enhancements-in-vs-2010.aspx
    http://www.softwareknowhow.info/Buyers-Guide/VS2010:-Parallel-programming/80
    http://channel9.msdn.com/pdc2008/TL25/


    Jochen Kalmbach (MVP VC++)
    Mittwoch, 15. September 2010 13:25
  • Danke für die schnellen Antworten @Martin Richter Mein Pool macht nichts anderes, als die Threads eben so zu verwalten, bzw. der Pool hält die Threads, der Sheduler fordert sie an, oder gibt sie frei. Und dabei sorgt er dafür, dass nur Arbeitsfreie Threads supended werden, um deadlocks zu vermeiden. Auf das Event Konzept wollte ich bewusst verzichten, um möglichst einfach auf Unix porten zu können, weil das wohl über kurz oder lang ansteht. Würde deshalb gerne bei genannter Methode mit Singletons bleiben und vermeiden die Zeiger mitzugeben, sondern sie global zu speichern und abzufragen. Hier mal etwas Code:

    /*CriticalSectionLock ist ein OS abhängiges Macro*/

    template <typename C>
    class Singleton
    {
    public:
    
    	static C* instance ()
      {
    		CriticalSectionLock
    		if (!_instance)
    			_instance = new C ();
    		UnlockCriticalSection;		
    		return _instance;
      }
    
    	virtual
      ~Singleton ()
      {
        _instance = 0;
      }
    
     private:
      static C* _instance;
    	
     protected:
      Singleton () { };
     };
    
     template <typename C> C* Singleton <C>::_instance = 0;
    
    #endif
    
     /*** usage
    
     class Test : public Singleton <Test>
     {
     friend class Singleton <Test>;
     public:
      ~Test () { };
      void xyz () { }
     protected:
      Test () { }
     };
     Test::instance ()->xyz ();
    
    ***/

    Mittwoch, 15. September 2010 13:45
  • Habe das ganze jetzt doch über einen durchgereichten Pointer gelöst.
    Donnerstag, 16. September 2010 06:07