클래스 설명
*meta가 붙은 변수들은 ABA문제를 막기위해 실제 변수에 상위 17비트값을 추가함

nodePool_ : 락프리 스택으로 만들어진 오브젝트 풀
metaTail_ : tail의 meta주소
metaHead_ : head의 meta주소
metaCnt_ : 상위 17비트에 들어갈 값을 인터락으로 만들때 사용함
num_ : 큐가 보관중인 요소의 갯수

ENQ : 1번 CAS 성공후 2번 CAS 성공시 break;

DEQ : 비어있다면 나가고 비어있지 않으면 진입.
head의 next가 null이면 continue
metaHead_ == metaHead(지역변수) 이면 head의 next로 CAS
성공시 더미노드를 Free한다. 미리 복사해두엇던 값을 반환한다.
왜 ret으로 미리 복사해두엇나?
CAS 성공 후 ret에다가 data를 복사한다면 다른 스레드가 복사전에 반환하고 재활용되서 재활용 된 값이 반환될수도잇음.
메모리 로그 구조체

EVENT : 로그 찍는 상황을 분류한것
1. ENQ_FIRST_CAS_SUCCESS : 인큐 하려는 노드의 next == null일때 추가하고자 하는 노드의 meta주소를 next에 넣고자 한 CAS가 성공시 찍는 로그
2. WRITE_MEMORY_LOG_SECOND_CAS_SUCCESS : 1번 CAS가 성공하고 2번 CAS가 성공햇을때 찍은 로그
3. WRITE_MEMORY_LOG_SECOND_CAS_FAILED : 1번 CAS가 성공하고 2번 CAS가 실패시 찍는 로그
4. WRITE_MEMORY_LOG_DEQ_FREE : Dequeue에서 더미노드를 락프리 오브젝트풀에 반환시 찍는 로그
멤버변수 설명
1. localMetaTail_ : Enqeueue 혹은 Dequeue에서 큐의 멤버변수 metaTail_값을 저장하는 지역변수
2. pLocalRealTail_ : 위의 localMetaTail_에서 상위 17비트를 제거한 실제주소
3. actualMetaTail_ : 2번 CAS에서는 지역변수 metaTail과 실제 metaTail_을 비교하는데 이때 CAS가 반환하는 metaTail_의 초깃값 따라서 위의 2,3을 제외하고는 쓰이지 않는다.
4. metaNext_ : 1번 CAS가 실패햇을때 찍으려고 준비한것인데 사실상 핵심은 2번 CAS가 성공한것이라 1번 실패는 적지않으므로 사실상 의미가 없어짐.
5. newMetaTail_ : 1번 CAS 성공시 next에 2번 CAS성공시 metaTail_이 해당값으로 변하게 된다.
6. metaFreeDummy_ : DEQ에서 반환된 더미 노드의 상위 17비트가 조작된 meta주소
7. pRealFreeDummy_ : 위 metaFreeDummy_의 실제주소
메모리 로그 찍기 설명


ULONGLONG 카운터를 늘려가면서 배열상의 인덱스를 구해가며 메모리 로그를 찍는다.
아래 WRITE_MEMORY_LOG_SECOND_CAS_FAILED 함수는 로그를 찍은 인덱스를 반환하는데 이는
해당 함수가 찍은 로그가 논리적으로 확인해야하는 로그의 끝이기 때문에 빠르게 해당 위치를 찾기위함임



MemLogWriteToFile : 2번 CAS 실패시 로그 배열 , 인덱스를 만들기 위한 로그 카운터, 마지막 로그 인덱스값을 파일에 저장한다. 로그 카운터를 저장하는 이유는 배열에 원형방식으로 로그를 적기때문에 배열끝에 도달해서 다시적엇는지를 확인하기 위함임.
MemLogRead : 로그를 분석하는 프로젝트에서만 사용하는 함수임. ARRAY_SIZE 크기의 배열과 Counter, 마지막 인덱스를 받을 변수의 주소를 넣으면 담아준다.
'포폴' 카테고리의 다른 글
| 락프리큐 초기 로깅 - LogAnalyzer 및 디버깅로그 설명 (1) | 2024.11.09 |
|---|---|
| 락프리큐에 TlsPool 붙이기 - 문제 해결 (0) | 2024.10.18 |
| 락프리큐에 TlsPool 붙이기 - 코드설명 밑 문제제기 (0) | 2024.10.18 |