std::map threadsafe verwenden?



  • Hey!

    Ich möchte unter Windows eine std::map threadsafe verwenden.

    struct Data
    {
    	LPWSABUF lpBuffer;
    	DWORD timeStamp;
    };
    
    Data tempQueueEntry;
    map<LPOVERLAPPED, Data> queue;
    map<LPOVERLAPPED, Data>::iterator queueIterator;
    

    Folgender code könnte mehrmals gleichzeitig aufgerufen werden:

    tempQueueEntry.lpBuffer = lpBuffer;
    tempQueueEntry.timeStamp = timeGetTime();
    
    queue.insert(pair<LPOVERLAPPED, Data>(lpOverlapped, tempQueueEntry));
    

    und

    queueIterator = queue.find(lpOverlapped);
    if(queueIterator != queue.end())
    {
    	// Manipulate buffer
    	// ...
    
    	queue.erase(queueIterator);
    }
    
    // Delete expired entries
    for(queueIterator = queue.begin(); queueIterator != queue.end(); )
    {
    	if(timeGetTime() - queueIterator->second.timeStamp > 5000)
    		queue.erase(queueIterator++);
    	else
    		++queueIterator;
    }
    

    Aber wie mache ich das richtig? Müsste ich mich da mit den ganzen Thread-Techniken beschäftigen? Ist das sehr kompliziert? Oder gibt es für mein Problem eine einfache Lösung?

    Danke!
    MfG



  • Aber wie mache ich das richtig?

    Ein Möglichkeit (unter Windows) ist die Map mit Critical Sections zu schützen.

    Müsste ich mich da mit den ganzen Thread-Techniken beschäftigen?

    Auf jedenfall.

    Ist das sehr kompliziert?

    Nein.

    Simon



  • Was für eine STL Library verwendest Du?



  • C++ STL

    Ich werd mir mal critical sections ansehen.
    Jedoch ist da so ne Sache:
    Ein Thread darf keinesfalls lange angehalten werden, da dieser Thread mit einem Netzwerkstrom zusammenhängt (Ein Durchgang eines jeden Threads ist schnell genug).
    Sind critical sections schnell, oder gibt es ne schnellere Möglichkeit?

    Danke!
    MfG



  • Für Windows sind Critical Section (soweit cih weiss) die schnellsten Lock's.

    Ich meinte die Implementierung der STL, z.B. die von Microsoft.
    Ich denke nach dem Erase aus der Map wird der Iterator ungültig. Und die MS STL Impl. hat bei Erase einen nicht Standardkonformen Rückgabewert.

    Simon



  • Aha, okay.

    Achso, danke für den Tipp, aber wenn du genau hinsiehst, mache ich es so:

    queue.erase(queueIterator++);

    Dabei wird doch zuerst ein temporäres Objekt, welches queueIterator darstellt, dem erase() übergeben und anschließend wird queueIterator inkrementiert. Sollte also hinhauen.

    MfG



  • Öh und pro thread braucht man ein eigenes CRITICAL_SECTION- Objekt, richtig? Scheint sehr logisch, frage aber halt zur Sicherheit nach.



  • ceplusplus@loggedoff schrieb:

    Öh und pro thread braucht man ein eigenes CRITICAL_SECTION- Objekt, richtig? Scheint sehr logisch, frage aber halt zur Sicherheit nach.

    Nein, nicht pro Thread, sondern pro Objekt welches geschützt werden soll.



  • Ist es denn so richtig?

    // Codeblock 1
    
    // criticalSection1  schützt  tempQueueEntry
    EnterCriticalSection(&criticalSection1);
    tempQueueEntry.lpBuffer = lpBuffer;
    tempQueueEntry.timeStamp = timeGetTime();
    LeaveCriticalSection(&criticalSection1);
    
    // criticalSection2  schützt  queue
    EnterCriticalSection(&criticalSection2);
    queue.insert(pair<LPOVERLAPPED, Data>(lpOverlapped, tempQueueEntry));
    LeaveCriticalSection(&criticalSection2);
    
    // Codeblock 2
    
    // criticalSection2  schützt  queue
    EnterCriticalSection(&criticalSection2);
    
    queueIterator = queue.find(lpOverlapped);
    if(queueIterator != queue.end())
    {
        // Blubb
        // ...
    
    	queue.erase(queueIterator);
    }
    
    for(queueIterator = queue.begin(); queueIterator != queue.end(); )
    {
    	if(timeGetTime() - queueIterator->second.timeStamp > 5000)
    		queue.erase(queueIterator++);
    	else
    		++queueIterator;
    }
    
    LeaveCriticalSection(&criticalSection2);
    

    Beide Codeblocks könnten mehrfach gleichzeitig laufen, also zB. 2x Codeblock1 und 3x Codeblock2 gleichzeitig.
    Kommt es da nicht zu Problemen?

    Im zweiten Codeblock muss queueIterator nicht geschützt werden, dafür aber queue, welches auch in Codeblock1 geschützt ist.

    MfG



  • Oh mist, sorry.
    Im zweiten Codeblock muss queueIterator natürlich auch geschützt werden, da dieser Block auch mehrfach ausgeführt werden könnte.

    Kann ich das so lassen oder muss ich noch eine weitere CS erstellen?

    zB.

    // criticalSection2  schützt  queue
    EnterCriticalSection(&criticalSection2);
    // criticalSection3  schützt  queueIterator
    EnterCriticalSection(&criticalSection3);
    
    ...
    

    😕


Anmelden zum Antworten