Reputation: 735
I'm trying to implement single thread writing, multiple thread reading mechanism for shared resource management using interlock in C++, windows environment.
Q1. The result code seems to work as what I intend, but I'd like to ask for your wisdom if I am missing something.
Q2. If there is a real life or good active open source code example I can refer to, it will be really appreciated.
Following are the objectives I've taken into account.
#include <iostream>
#include <Windows.h>
char g_c = 0i8;
char g_pReadChar[3]{};
void* g_pThreads[4]{};
unsigned long g_pThreadIDs[4]{};
long long g_llLock = 0ULL; // 0 : Not locked / 1 : Locked (Writing) / 2 : Locked (Reading)
long long g_llEntryCount = 0ULL; // Thread entry count
__forceinline void Read()
{
// <- if a thread execution is here (case 0)
InterlockedIncrement64(&g_llEntryCount);
// <- if a thread execution is here (case 1)
for (unsigned long long i = 0ULL; i < 100000ULL; ++i)
{
if (InterlockedCompareExchange64(&g_llLock, 2LL, 0LL) == 1LL)
{
continue;
}
// <- if a thread execution is here (case 2)
// --------------------------------------------------
// Read data
std::cout << g_c;
// --------------------------------------------------
InterlockedExchange64(&g_llLock, 1LL); // Lock is needed in order to block case 0
if (InterlockedDecrement64(&g_llEntryCount) == 0LL)
{
InterlockedExchange64(&g_llLock, 0LL);
}
else
{
InterlockedExchange64(&g_llLock, 2LL);
}
return;
}
InterlockedDecrement64(&g_llEntryCount);
}
__forceinline unsigned long __stdcall ReadLoop(void* _pParam)
{
while (true)
{
Read();
Sleep(1);
}
}
__forceinline void Write(const unsigned long long _ullKey)
{
for (unsigned long long i = 0ULL; i < 100000ULL; ++i)
{
if (InterlockedCompareExchange64(&g_llLock, 1LL, 0LL) != 0LL)
{
continue;
}
// --------------------------------------------------
// Write data
if (_ullKey == 0ULL)
{
g_c = 'A';
}
else if (_ullKey == 1ULL)
{
g_c = 'B';
}
else
{
g_c = 'C';
}
// --------------------------------------------------
InterlockedExchange64(&g_llLock, 0LL);
return;
}
}
__forceinline unsigned long __stdcall WriteLoop(void* _pParam)
{
unsigned long long ullCount = 0ULL;
unsigned long long ullKey = 0ULL;
while (true)
{
if (ullCount > 10000ULL)
{
++ullKey;
if (ullKey >= 3ULL)
{
ullKey = 0ULL;
}
ullCount = 0ULL;
}
Write(ullKey);
++ullCount;
}
}
int main()
{
g_pThreads[0] = CreateThread(nullptr, 0ULL, ReadLoop, nullptr, 0UL, &g_pThreadIDs[0]);
g_pThreads[1] = CreateThread(nullptr, 0ULL, ReadLoop, nullptr, 0UL, &g_pThreadIDs[1]);
g_pThreads[2] = CreateThread(nullptr, 0ULL, ReadLoop, nullptr, 0UL, &g_pThreadIDs[2]);
g_pThreads[3] = CreateThread(nullptr, 0ULL, WriteLoop, nullptr, 0UL, &g_pThreadIDs[3]);
Sleep(100000);
return 0;
}
Upvotes: 0
Views: 71