이 글을 먼저 참고한 이후 보시면 됩니다
https://3dmpengines.tistory.com/2237
MemoryPool 2 (포인터와 인덱스 값으로 ABA 문제 해결방안 128bit)
interlockedCompareExchange128 의 동작은 아래 글을 참고 https://3dmpengines.tistory.com/2236 InterlockedCompareExchange128 vs InterlockedCompareExchange64 주요 차이점 리턴 값이 다르다 128 비트를 사..
3dmpengines.tistory.com
위 글하고 같은건데 이것은 MS 에서 제공하는 내장 함수를 사용하는 안전한 방식 입니다
(이전 코드에는 약간의 테스트코드에서 하자가 있음) => 기본 제공 하는 MS 방식이 검증된것으로 안전한 방식이기도..
제공되는 SLIST_HEADER 는 아래와 같습니다 (이전 코드와 같은 걸 알 수 있습니다)
typedef union DECLSPEC_ALIGN(16) _SLIST_HEADER {
struct { // original struct
ULONGLONG Alignment;
ULONGLONG Region;
} DUMMYSTRUCTNAME;
struct { // x64 16-byte header
ULONGLONG Depth:16;
ULONGLONG Sequence:48;
ULONGLONG Reserved:4;
ULONGLONG NextEntry:60; // last 4 bits are always 0's
} HeaderX64;
} SLIST_HEADER, *PSLIST_HEADER;
SLIST_ENTRY 또한 다음 노드만 가리키는 형태입니다
typedef struct DECLSPEC_ALIGN(16) _SLIST_ENTRY {
struct _SLIST_ENTRY *Next;
} SLIST_ENTRY, *PSLIST_ENTRY;
아래는 MS 것을 사용한 테스크 코드입니다
헤더(SLIST_HEADER)가 있고 그 이후로 SLIST_ENTRY 를 추가하거나 삭제 할수 있습니다, 멀티스레드 환경에서, 스택처럼
lock-free stack 은 다음 처럼 사용하면 됩니다
DECLSPEC_ALIGN(16)
class Data // : public SListEntry
{
public:
SLIST_ENTRY _entry;
int64 _rand = rand() % 1000;
};
SLIST_HEADER* GHeader;
int main()
{
GHeader = new SLIST_HEADER();
ASSERT_CRASH(((uint64)GHeader % 16) == 0);
//헤드 초기화
InitializeSListHead(GHeader);
for (int32 i = 0; i < 3; i++)
{
GThreadManager->Launch([]()
{
while (true)
{
Data* data = new Data();
ASSERT_CRASH(((uint64)data % 16) == 0);
//헤드에 다음 노드 추가
::InterlockedPushEntrySList(GHeader, (SLIST_ENTRY*)data);
this_thread::sleep_for(10ms);
}
});
}
for (int32 i = 0; i < 2; i++)
{
GThreadManager->Launch([]()
{
while (true)
{
Data* pop = nullptr;
pop = (Data*)::InterlockedPopEntrySList(GHeader);
if (pop)
{
cout << pop->_rand << endl;
delete pop;
}
else
{
cout << "NONE" << endl;
}
}
});
}
GThreadManager->Join();
}
추가적으로
DECLSPEC_ALIGN(16)
class Data // : public SLIST_ENTRY
{
public:
SLIST_ENTRY _entry;
int64 _rand = rand() % 1000;
}
Data 부분은 SLIST_ENTRY 를 상속 받거나 멤버변수에 첫번째로 넣어 16 바이트 정렬을 맞춰 준 다음
포인터 연산을 가능하게 해주면 됩니다
'운영체제 & 병렬처리 > Multithread' 카테고리의 다른 글
atomic 과 가시성, 메모리 재배치의 해결 (0) | 2022.11.27 |
---|---|
MemoryPool 4 : 기존 메모리풀을 MS 로 변경 (0) | 2022.10.13 |
MemoryPool 2 (포인터와 인덱스 값으로 ABA 문제 해결방안 128bit) (0) | 2022.10.11 |
InterlockedCompareExchange128 vs InterlockedCompareExchange64 (0) | 2022.10.11 |
lock-free aba problem (0) | 2022.10.10 |