CRITICAL_SECTION g_csSingletonX; X * g_px = NULL; X * GetSingletonX () { EnterCriticalSection (& g_csSingletonX); if (g_px == NULL) { g_px = new (nothrow) X (); } LeaveCriticalSection (& g_csSingletonX); return g_px; }
X()
constructor itself uses locks: then, in order to prevent deadlocks, the program must define a hierarchy of locks , and lock locks strictly in that order. (Moreover, if the constructor code is not written by you, and you cannot influence the order of locks in it, then at this stage you will have to admit defeat.)g_csSingletonX
needs to be combined with locks of all singleton constructors, as well as locks of all methods of class X.CRITICAL_SECTION g_csCommon; X * GetSingletonX () { EnterCriticalSection (& g_csCommon); if (g_px == NULL) { g_px = new (nothrow) X (); } LeaveCriticalSection (& g_csCommon); return g_px; } Y * GetSingletonY () { EnterCriticalSection (& g_csCommon); if (g_py == NULL) { g_py = new (nothrow) Y (); } LeaveCriticalSection (& g_csCommon); return g_py; } void X :: DoSomething () { EnterCriticalSection (& g_csCommon); .. something .. LeaveCriticalSection (& g_csCommon); }
WAIT_ABANDONED
. The protected data remains correct all the time, and atomic moves from one correct state to the next.CRITICAL_SECTION g_cs; GORILLADATA g_data; void PokeGorilla (double intensity) { EnterCriticalSection (& g_cs); DeformGorilla (intensity, & g_data); Reticulate (& g_data.spline); int stress = CalculateTension (& g_data.spline); if (stress <25) g_data.mood = RELAXED; else if (stress <50) g_data.mood = ANNOYED; else g_data.mood = ANGRY; DeleteObject (g_data.hbmGorilla); g_data.hbmGorilla = RenderGorilla (& g_data); LeaveCriticalSection (& g_cs); }
Reticulate()
function may require a lock protecting geometric operations; and it may turn out that, according to the hierarchy, this lock needs to be captured before g_cs
.g_cs
, then we would have to reduce the time during which PokeGorilla()
holds the lock. RenderGorilla()
is probably a difficult and slow operation. (You know how hard it is to depict realistic fur.) Then during the RenderGorilla()
call, the RenderGorilla()
lock g_cs
held in vain.void PokeGorilla(double intensity)
{
//
EnterCriticalSection(&g_cs);
GORILLADATA data = g_data;
LeaveCriticalSection(&g_cs);
//
DeformGorilla(intensity, &data);
Reticulate(&data.spline);
int stress = CalculateTension(&data.spline);
if (stress < 25) data.mood = RELAXED;
else if (stress < 50) data.mood = ANNOYED;
else data.mood = ANGRY;
data.hbmGorilla = RenderGorilla(&data);
//
EnterCriticalSection(&g_cs);
HBITMAP hbmToDelete = g_data.hbmGorilla;
g_data = data;
LeaveCriticalSection(&g_cs);
DeleteObject(hbmToDelete);
}
LONG g_lCounter;
void PokeGorilla(double intensity)
{
BOOL fSuccess;
do {
//
EnterCriticalSection(&g_cs);
GORILLADATA data = g_data;
LONG lCounter = g_lCounter;
LeaveCriticalSection(&g_cs);
//
DeformGorilla(intensity, &data);
Reticulate(&data.spline);
int stress = CalculateTension(&data.spline);
if (stress < 25) data.mood = RELAXED;
else if (stress < 50) data.mood = ANNOYED;
else data.mood = ANGRY;
data.hbmGorilla = RenderGorilla(&data);
//
EnterCriticalSection(&g_cs);
HBITMAP hbmToDelete;
if (lCounter == g_lCounter)
{
hbmToDelete = g_data.hbmGorilla;
g_data = data;
g_lCounter++;
fSuccess = TRUE;
} else {
hbmToDelete = data.hbmGorilla;
fSuccess = FALSE;
}
LeaveCriticalSection(&g_cs);
DeleteObject(hbmToDelete);
} while (!fSuccess);
}
GORILLADATA
, this number would be better stored in the structure of GORILLADATA
. (No, it would be really better not to poke a gorilla!) In a non-blocking algorithm, we would check the value of the version number by using InterlockedCompareExchangeRelease
; but the structure of GORILLADATA
impossible to update atomically, so we use the critical section to check it and simultaneously update it. Nevertheless, the model remains the same as before: if the gorilla was poked behind our back, we are forced to throw out all the results we have received, and start the calculations in a new way, to reflect both pokes in the final result.Source: https://habr.com/ru/post/118917/
All Articles