MMOServer

SList(C++) 불완전

이야기prog 2025. 3. 28. 19:50
#pragma once



//template<typename T>
//struct Node {
//	T data;
//	Node* node;
//};

__declspec(align(16))
struct SListEntry {
	SListEntry* next;
};


__declspec(align(16))
struct SListHeader {
	SListHeader() {
		alignment = 0;
		region = 0;
	}
	union {
		struct {
			uint64 alignment;
			uint64 region;
		}DUMMYSTRUCTNAME;

		struct {
			uint64 depth : 16;
			uint64 sequence : 48;
			uint64 reserved : 4;
			uint64 next : 60;
		}HeaderX64;
	};
};

void InitializeHeader(SListHeader* header);

void PushEntrySList(SListHeader* header, SListEntry* entry);

SListEntry* PopEntrySList(SListHeader* header);

 

#include "pch.h"
#include "LockFreeStack.h"

void InitializeHeader(SListHeader* header)
{
	header->alignment = 0;
	header->region = 0;
}

void PushEntrySList(SListHeader* header, SListEntry* entry)
{
	SListHeader expected = {};
	SListHeader desired = {};

	desired.HeaderX64.next = ((uint64)entry >> 4);

	while (true) {
		expected = *header;

		entry->next = (SListEntry*)(((uint64)expected.HeaderX64.next << 4));
		desired.HeaderX64.depth = expected.HeaderX64.depth + 1;
		desired.HeaderX64.sequence = expected.HeaderX64.sequence + 1;

		if (::InterlockedCompareExchange128((int64*)header, desired.region, desired.alignment, (int64*)&expected) == 1)
			break;

	}
}
SListEntry* PopEntrySList(SListHeader* header)
{
	SListHeader expected = {};
	SListHeader desired = {};
	SListEntry* entry = nullptr;

	// ABA Problem
	
	while (true) {
		expected = *header;

		entry = (SListEntry*)(((uint64)expected.HeaderX64.next) << 4);
		if (entry == nullptr) {
			break;
		}

		//use-after-free
		desired.HeaderX64.next = ((uint64)entry->next) >> 4;
		desired.HeaderX64.depth = expected.HeaderX64.depth - 1;
		desired.HeaderX64.sequence = expected.HeaderX64.sequence + 1;

		if (::InterlockedCompareExchange128((int64*)header, desired.region, desired.alignment, (int64*)&expected) == 1)
			break;

	}

	return entry;

}

ABA문제를 해결하기 위한 코드이나, user-after-free는 해결하지 못함.

 Microsoft에 SList를 쓰자!