Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

11

03.10.2007, 13:25

@rewb0rn: Einen simplen Counter mit einer Critical Section abzusichern, ist übertrieben. Dafür gibt es spezielle Befehle wie InterlockedIncrement & Co..

@Nox: Vielleicht lässt es sich gar nicht lösen, ohne eigene Container-Templates zu schreiben oder die der STL umzuschreiben. Feststellen, ob ein Container gerade benutzt wird, könnte man dadurch, dass man darauf aufpasst, wie viele Iteratoren (normale für lesen/schreiben und konstante für nur lesen) gerade existieren.

rewb0rn

Supermoderator

Beiträge: 2 773

Wohnort: Berlin

Beruf: Indie Game Dev

  • Private Nachricht senden

12

03.10.2007, 13:30

aso das wusste ich nicht, das konzept habe ich aus der uni und da haben wir nur mit c an unserem eigenen betriebssystem gearbeitet ;) viel anders werden die das aber intern auch nicht machen denke ich.

kannst du ein beispiel dafür geben wie das dann aussehn würde? man muss ja den eintritt in criticalsection auch noch absichern.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

13

03.10.2007, 14:01

Zitat von »"rewb0rn"«

aso das wusste ich nicht, das konzept habe ich aus der uni und da haben wir nur mit c an unserem eigenen betriebssystem gearbeitet ;) viel anders werden die das aber intern auch nicht machen denke ich.

Soweit ich weiß, gibt es bei x86-Prozessoren spezielle Instruktionen für sowas, das sollte also deutlich schneller sein als eine Critical Section.

Zitat von »"rewb0rn"«

kannst du ein beispiel dafür geben wie das dann aussehn würde? man muss ja den eintritt in criticalsection auch noch absichern.


So:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
void readlock()
{
    if(InterlockedIncrement(&Readers)) EnterCriticalSection(CriticalSection);
}

void readunlock()
{
    if(!InterlockedDecrement(&Readers)) LeaveCriticalSection(CriticalSection);
}

rewb0rn

Supermoderator

Beiträge: 2 773

Wohnort: Berlin

Beruf: Indie Game Dev

  • Private Nachricht senden

14

03.10.2007, 14:09

okay danke, sieht natürlich auch deutlich übersichtlicher aus.

Nox

Supermoderator

  • »Nox« ist der Autor dieses Themas

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

15

03.10.2007, 15:47

Hmm jetzt stellt sich nur noch die Frage ob es etwas vergleichbares für Linux gibt, weil auf Anhieb habe ich keine "einfache" Funktion gefunden. Wer also einen Tipp hat, ich bin für jede Hilfe offen :) .

Also das implizite lock werde ich wohl beibehalten. Eine Option wäre natürlich das lock explizit zu machen und dafür das begin durch etwas zu ersetzen, was man per Suche schnell findet um zu checken ob gelockt wurde oder nicht.


EDIT: atomic_incr scheint die Lösung zu sein...
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

16

03.10.2007, 16:01

atomicity.h

C-/C++-Quelltext

1
2
__atomic_add
__exchange_and_add


Ich hab übrigens meine Quellcodes mal durchforstet und ein paar Codesnippets gefunden die zum Thema passen. Zum Beispiel ein abgespeckter Auszug meiner Threadsynchro Klassen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
struct ScopedLock;

struct Lockable
{
    friend struct ScopedLock;

    virtual ~Lockable() {}

private:
    virtual void Lock() = 0;
    virtual void Unlock() = 0;
};

struct ScopedLock : private Uncopyable
{
    ScopedLock( Lockable& obj ) : locked( obj )
    {
        locked.Lock();
    }

    ~ScopedLock()
    {
        locked.Unlock();
    }

private:
    Lockable& locked;
};

class LockPolicyMutex : Uncopyable
{
public:
    LockPolicyMutex()
    {
        hMutex = CreateMutex( 0, false, 0 );
    }

    ~LockPolicyMutex()
    {
        CloseHandle( hMutex );
    }

    void Lock()
    {
        WaitForSingleObject( hMutex, INFINITE );
    }

    void Unlock()
    {
        ReleaseMutex( hMutex );
    }

private:
    HANDLE hMutex;
};

class LockPolicyCriticalSection : Uncopyable
{
public:
    LockPolicyCriticalSection()
    {
        InitializeCriticalSection( &cs );
    }

    ~LockPolicyCriticalSection()
    {
        DeleteCriticalSection( &cs );
    }

    void DoLock()
    {
        EnterCriticalSection( &cs );
    }

    void DoUnlock()
    {
        LeaveCriticalSection( &cs );
    }

private:
    CRITICAL_SECTION cs;
};

template< class LockPolicy = LockPolicyCriticalSection >
class Mutex 
    : Uncopyable, public Lockable
{
public:
    Mutex()
    {}

private:
    void Lock()
    {
        locker.DoLock();
    }

    void Unlock()
    {
        locker.DoUnlock();
    }

    LockPolicy locker;
};


Das Ganze ist Policybasiert, d.h. das Verhalten des Mutex lässt sich ggf recht einfach ändern. Ich hab mal zwei Möglichkeiten mitgesendet (Mutex und Critical Section). Die Klasse "ScopedLock" wird verwendet um einen bestimmten "Scope" zu sichern. Das ganze sollte auch Ausnahmesicher sein, dank des Destruktors.

Die ominöse Klasse Uncopyable gibts hier:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
/*
    utility
 */
struct Uncopyable
{
protected:
    Uncopyable() {}

private:
    Uncopyable( const Uncopyable& );
    Uncopyable& operator=( const Uncopyable& );
};


Das ganze verwendet sich dann so:

C-/C++-Quelltext

1
2
3
Mutex<> x;

ScopedLock lock( x );


Edit: Achja, atomic_inc und atomic_dec für den x86 mit M$ Syntax:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
inline void atomic_add( int* p )
{
    _asm mov esi, [p]
    _asm lock inc dword ptr[esi]
}

inline void atomic_dec( int* p )
{
    _asm mov esi, [p]
    _asm lock dec dword ptr[esi]
}
@D13_Dreinig

Nox

Supermoderator

  • »Nox« ist der Autor dieses Themas

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

17

09.10.2007, 16:10

Nachtrag:

Davids Idee, von wegen mitzuzählen wieviele Iteratoren vorhanden sind ist sehr gut. Denn wenn man die Iteratoren nochmal kapselt und mit der writelock()/readlock() Idee verbindet, ist sichergestellt, dass die Liste gelockt ist, wenn sie benutzt wird und dass sie auch per unlock() wieder freigegeben wird.

Und dank InterlockedIncrement/atomic_inc und InterlockedDecrement/atomic_dec (bzw. atomic_dec_and_test) dürfte die readlock() verkraftbar mehr an Zyklen verbrauchen.
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

18

20.10.2007, 19:56

Hey,

ich hab nur mal ne kleine Anmerkung:
Wenn ich Scott Meyers Buch richtig in Erinngerung habe sollte man unter allen Umständen vermeiden von Containerklassen wie list und co. zu erben! ( siehe Effektiv C++ Programmieren S. 60 )

mfg
TheProgrammer
Das Böse ist des Menschensbeste Kraft - Friedrich Nietzsche

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

19

20.10.2007, 20:32

Zitat von »"Theprogrammer"«

Hey,

ich hab nur mal ne kleine Anmerkung:
Wenn ich Scott Meyers Buch richtig in Erinngerung habe sollte man unter allen Umständen vermeiden von Containerklassen wie list und co. zu erben! ( siehe Effektiv C++ Programmieren S. 60 )

mfg
TheProgrammer


Hier wird privat geerbt. Da ist das ganz egal. Scott's Regel gilt für öffentliche Vererbung (Ist-Ein-Beziehung).
@D13_Dreinig

Sicaine

unregistriert

20

20.10.2007, 20:57

Kennt Ihr Threading Building Blocks von Intel?

Damit wurde unteranderem auch Maya(10Millionen Codezeilen) und zwar effectiv, schnell und gut.

Werbeanzeige