QT 4.5 containers vom Type "QReadWriteLock" (linux)



  • Hallo Zusammen,

    derzeit versuche ich einen Container der Klasse QReadWriteLock
    anzulegen. Hier schmeisst mich aber der Compiler (gcc) mit Meldungen
    zu, welche ich nicht verstehe.

    Hier erstmal nur der Code, welcher nicht will:

    void	DataBlocks::add( DataBlock Entry)
    {
    QReadWriteLock		Pointer;
    
    	DataLockEntries.push_back ( Pointer );      <- Will nicht.
    }
    

    Hat jemand eine Idee wieso ?

    Gruss R.



  • Koennte was damit zu tun haben, dass QReadWriteLock nicht kopierbar ist.
    Warum postest Du die Fehlermeldung nicht?



  • Erscheint mir logisch.
    Leider habe ich die Fehlermeldungen jetzt nicht zur Hand. Der Compiler wirft aber Seitenweise Fehler aus.

    Der Hintergrund ist, das ich dynamisch eine Klasse anlege, welche Daten von einer Schnittstelle ( Seriell/ TCPIP) über mehrer Threads bekommt/gibt. Hierbei benötige ich einen "Lock" um die Sache zu synchronisieren.

    Gibt es eine Variante, welche dynamisch arbeitet ?

    Was macht QMutex in diesem Fall.
    Leider sagt die Doku. hier nichts darüber aus, ob QReadWriteLock kopierbar ist oder nicht (oder ich habs überlesen).

    Gruss R.



  • Hier noch die Fehlermeldung

    from /usr/include/c++/4.4/bits/allocator.h:48,
    from /usr/include/c++/4.4/vector:62,
    from include/datablocks.h:15,
    from source/datablocks.cpp:13:
    /usr/include/qt4/QtCore/qreadwritelock.h: In member function 'void __gnu_cxx::new_allocator<_Tp>::construct(_Tp*, const _Tp&) [with _Tp = QReadWriteLock]':
    /usr/include/c++/4.4/bits/stl_vector.h:737: instantiated from 'void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = QReadWriteLock, _Alloc = std::allocator<QReadWriteLock>]'
    source/datablocks.cpp:147: instantiated from here
    /usr/include/qt4/QtCore/qreadwritelock.h:78: error: 'QReadWriteLock::QReadWriteLock(const QReadWriteLock&)' is private
    /usr/include/c++/4.4/ext/new_allocator.h:105: error: within this context
    In file included from /usr/include/c++/4.4/vector:69,
    from include/datablocks.h:15,
    from source/datablocks.cpp:13:
    /usr/include/qt4/QtCore/qreadwritelock.h: In member function 'void std::vector<_Tp, _Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp = QReadWriteLock, _Alloc = std::allocator<QReadWriteLock>]':
    /usr/include/c++/4.4/bits/stl_vector.h:741: instantiated from 'void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = QReadWriteLock, _Alloc = std::allocator<QReadWriteLock>]'
    source/datablocks.cpp:147: instantiated from here
    /usr/include/qt4/QtCore/qreadwritelock.h:78: error: 'QReadWriteLock::QReadWriteLock(const QReadWriteLock&)' is private
    /usr/include/c++/4.4/bits/vector.tcc:306: error: within this context
    /usr/include/c++/4.4/bits/stl_vector.h:741: instantiated from 'void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = QReadWriteLock, _Alloc = std::allocator<QReadWriteLock>]'
    source/datablocks.cpp:147: instantiated from here
    /usr/include/qt4/QtCore/qreadwritelock.h:78: error: 'QReadWriteLock& QReadWriteLock::operator=(const QReadWriteLock&)' is private
    /usr/include/c++/4.4/bits/vector.tcc:312: error: within this context
    In file included from /usr/include/c++/4.4/vector:61,
    from include/datablocks.h:15,
    from source/datablocks.cpp:13:
    /usr/include/qt4/QtCore/qreadwritelock.h: In static member function 'static _BI2 std::__copy_move_backward<false, false, std::random_access_iterator_tag>::__copy_move_b(_BI1, _BI1, _BI2) [with _BI1 = QReadWriteLock*, _BI2 = QReadWriteLock*]':
    /usr/include/c++/4.4/bits/stl_algobase.h:595: instantiated from '_BI2 std::__copy_move_backward_a(_BI1, _BI1, _BI2) [with bool _IsMove = false, _BI1 = QReadWriteLock*, _BI2 = QReadWriteLock*]'
    /usr/include/c++/4.4/bits/stl_algobase.h:605: instantiated from '_BI2 std::__copy_move_backward_a2(_BI1, _BI1, _BI2) [with bool _IsMove = false, _BI1 = QReadWriteLock*, _BI2 = QReadWriteLock*]'
    /usr/include/c++/4.4/bits/stl_algobase.h:640: instantiated from '_BI2 std::copy_backward(_BI1, _BI1, _BI2) [with _BI1 = QReadWriteLock*, _BI2 = QReadWriteLock*]'
    /usr/include/c++/4.4/bits/vector.tcc:308: instantiated from 'void std::vector<_Tp, _Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp = QReadWriteLock, _Alloc = std::allocator<QReadWriteLock>]'
    /usr/include/c++/4.4/bits/stl_vector.h:741: instantiated from 'void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = QReadWriteLock, _Alloc = std::allocator<QReadWriteLock>]'
    source/datablocks.cpp:147: instantiated from here
    /usr/include/qt4/QtCore/qreadwritelock.h:78: error: 'QReadWriteLock& QReadWriteLock::operator=(const QReadWriteLock&)' is private
    /usr/include/c++/4.4/bits/stl_algobase.h:546: error: within this context
    In file included from /usr/include/c++/4.4/vector:64,
    from include/datablocks.h:15,
    from source/datablocks.cpp:13:
    /usr/include/qt4/QtCore/qreadwritelock.h: In static member function 'static _ForwardIterator std::__uninitialized_copy<<anonymous> >::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = QReadWriteLock*, _ForwardIterator = QReadWriteLock*, bool <anonymous> = false]':
    /usr/include/c++/4.4/bits/stl_uninitialized.h:117: instantiated from '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = QReadWriteLock*, _ForwardIterator = QReadWriteLock*]'
    /usr/include/c++/4.4/bits/stl_uninitialized.h:257: instantiated from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = QReadWriteLock*, _ForwardIterator = QReadWriteLock*, _Tp = QReadWriteLock]'
    /usr/include/c++/4.4/bits/stl_uninitialized.h:267: instantiated from '_ForwardIterator std::__uninitialized_move_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = QReadWriteLock*, _ForwardIterator = QReadWriteLock*, _Allocator = std::allocator<QReadWriteLock>]'
    /usr/include/c++/4.4/bits/vector.tcc:338: instantiated from 'void std::vector<_Tp, _Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp = QReadWriteLock, _Alloc = std::allocator<QReadWriteLock>]'
    /usr/include/c++/4.4/bits/stl_vector.h:741: instantiated from 'void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = QReadWriteLock, _Alloc = std::allocator<QReadWriteLock>]'
    source/datablocks.cpp:147: instantiated from here
    /usr/include/qt4/QtCore/qreadwritelock.h:78: error: 'QReadWriteLock::QReadWriteLock(const QReadWriteLock&)' is private
    /usr/include/c++/4.4/bits/stl_uninitialized.h:74: error: within this context
    make: *** [obj/datablocks.o] Error 1
    *** Exited with status: 2 ***
    

    Ich bin da ganz ehrlich, hier hat QT richtig Ärger und ich muss eine andere Lösung suchen.

    Gruss R.



  • /usr/include/qt4/QtCore/qreadwritelock.h:78: error: 'QReadWriteLock::QReadWriteLock(const QReadWriteLock&)' is private
    

    Das ist doch äußerst problemlos verständlich!
    Wenn eine Klasse nicht kopierbar sein soll, macht man operator= und Copy-CTor private.
    QReadWriteLock und QMutex sollen Objekte etc. vor gleichzeitigem Zugriff aus mehreren Threads heraus schützen, es macht also wenig Sinn ein Kopieren zu erlauben, oder?

    Der Unterschied zwischen QMutex und QReadWriteLock geht wunderbar aus der Doku hervor:

    (Zu QReadWriteLock) This type of lock is useful if you want to allow multiple threads to have simultaneous read-only access, but as soon as one thread wants to write to the resource, all other threads must be blocked until the writing is complete.
    ///
    (Zu QMutex) The purpose of a QMutex is to protect an object, data structure or section of code so that only one thread can access it at a time.

    Ein Mutex blockiert immer, QReadWriteLock erlaubt gleichzeitigen lesenden Zugriff aus mehreren Threads heraus, blockiert aber sobald geschrieben werden soll.

    Die Lösung ist eigentlich recht leicht:
    Wenn du tatsächlich mehrere QReadWriteLocks (oder QMutex) in einer Liste ablegen willst, machst du das mit Pointern. Da wird beim Einfügen keine Kopie des Objekts durchgeführt, sondern nur die eines Pointers, und dafür braucht man keinen Kopierkonstruktor/op=.

    Was du damit allerdings bezwecken willst weiß ich nicht so ganz.
    Und synchronisiert sind die Zugriffe auf den Vector auch nicht, da hab ich keine Ahnung wie das Programm reagiert.


  • Mod

    l'abra d'or schrieb:

    Die Lösung ist eigentlich recht leicht:
    Wenn du tatsächlich mehrere QReadWriteLocks (oder QMutex) in einer Liste ablegen willst, machst du das mit Pointern. Da wird beim Einfügen keine Kopie des Objekts durchgeführt, sondern nur die eines Pointers, und dafür braucht man keinen Kopierkonstruktor/op=.

    Was du damit allerdings bezwecken willst weiß ich nicht so ganz.
    Und synchronisiert sind die Zugriffe auf den Vector auch nicht, da hab ich keine Ahnung wie das Programm reagiert.

    In dem gezeigten Beispiel wäre aber auch dass sinnlos, weil die Instanz ja nach dem Methoden Aufruf nicht mehr existiert.
    Der Sinn der ganzen Sache überhaupt würde mich aber auch interessieren 🤡



  • Hi,

    der Sinn ist eigentlich ebenso einfach.

    Es werden aus mehreren Threads auf einen Datenbereich zugegriffen. Bis jetzt hatte ich das Locking ausserhalb der Klasse durchgeführt, will es aber jetzt in die Klasse übernehmen.

    Der Lock ist so gestaltet, das mehrere Thread den Datenbereich gleichzeitig lesen dürfen, aber nur einer Schreiben darf.

    Daher die besagt Klasse, welche das eigentlich sehr gut steuert.

    Gruss R.

    P.S.: Vorher war es übrigens ein globales Array von dieser Klasse.



  • Du verstehst uns falsch! Es geht nicht um den Sinn des Lockings an sich, sondern warum du unbedingt die ganzen Locker in einer Liste abspeichern musst! Bringt doch nix, vor allem wenn du eh Klassen hast, dann hau den Mutex/ReadWriteLock doch als Member in die Klasse.
    Du willst ja die Member dieser Klasse schützen, und nicht irgendwelche! Wenn du einen Lock in eine Funktion einbaust und in einer anderen unabhängigen auch mit diesem Lock arbeiten willst blockieren die sich ja unsinnigerweise gegenseitig.

    Oder warum müssen die alle in eine Liste? Und wir reden hier schon von den Locks die in eine Liste kommen und nicht von eigenen Klassen? Wenn doch -> eigener Kopier-Konstruktor/Zuweisungsoperator, der eben den Lock nicht kopiert sondern neu erstellt.



  • Denn Ansatz hatte ich schon mal,
    ich werde diese Idee nochmals aufnehmen, da sie mir logisch erscheint. Schliesslich ist das "locken" ja eine Eigenschaft die sich auf die jeweilige Datenblock Klasse bezieht.

    Danke



  • Ach ja,

    jetzt fällt mir wieder ein, warum ich das Teil nicht in
    meine Datenblock Klasse anlegen kann.

    Q_DISABLE_COPY(QReadWriteLock)

    Die Klasse wird dynamisch angelegt.

    Das geht ja nun mal nicht. Und jede Instanz der Klasse benötigt einen eigenen Lock, da der Zugriff auf verschiedene Instanzen "gleichzeitig" statt finden kann.

    Gruss



  • Wo ist dabei das Problem?
    Wie gesagt, eigener Copy-CTor und op=, der alle Member kopiert, nur halt den Lock nicht. Da gibt es ja nix zu initialisieren.



  • Hi,

    Und jede Instanz der Klasse benötigt einen eigenen Lock, da der Zugriff auf verschiedene Instanzen "gleichzeitig" statt finden kann.

    Es wird gleichzeitig auf mehrere Datenbereiche zugegriffen,
    da benötigt jeder Datenbereich seinen eigenen Lock.

    Einer für alle geht da nicht .

    Oder wie meinst Du das ?

    Gruss



  • Ritchie schrieb:

    Es wird gleichzeitig auf mehrere Datenbereiche zugegriffen,
    da benötigt jeder Datenbereich seinen eigenen Lock.

    Einer für alle geht da nicht .

    Oder wie meinst Du das ?

    Gruss Ritchie

    Kannst du ein konkretes Beispiel liefern, wie du dir das gedacht hast?
    Ich nehme ja an, du willst sowas:

    class Test
    {
        QString m_string;
        int m_counter;
        QReadWriteLock stringLock;
        QReadWriteLock counterLock;
        ///usw.
    };
    

    Oder sehe ich das falsch?
    Und willst du diese beiden Locks jetzt in ne Liste pushen? Oder war das für Klassen-ungebundene Locks?
    Wie gesagt: konkretes Beispiel und mankann mehr sagen.

    Grüßle



  • Nein,

    ich habe eine Klassen,

    class Test
    {
        QString m_string;
        int m_counter;
        ///usw.
    };
    

    welche über eine zweite Klasse zu einer Collection

    class Tests
    {
         ....
        Test    *find( QString );
        ....
        private:
    vector<Test>    TextEntries;	
        ///usw.
    };
    

    Das Laden der Collection erfolgt über eine externe Datei, damit die
    Information beliebig erweitert werden können.

    Hierbei wird "Test" immer dynamisch angelegt und kann somit kein
    QReadWriteLock beinhalten.

    Derzeit versuche ich es mit einem static von QReadWriteLock [255] in der
    Klasse Tests. Hier habe ich nur den Nachteil, das eine zahlenmäßige
    Begrenzung der Element vorhanden ist.
    Ebenso die Resourcenverschwendung, wenn ich nur zwei Element lade.

    Gruss


  • Mod

    Hallo, sag mal weisst du was du da tust?
    Verstehst du überhaupt was von C++?

    Es wurde dir doch schon gesagt, das die Klasse einen eigenen Copy Construktor braucht, damit sie kopierbar ist, auch wenn sie nicht kopierbare Elemente enthält.
    Lerne bitte erstmal die fundamentalen Grundlagen von C++ bevor du mit GUI und Multithreading anfängst!



  • Mach ich.

    Nur nicht mehr hier 🙂

    Gruss


Anmelden zum Antworten