2010-12-21 2 views
6

좋아, 나는 this deleted question과 같은 것을 요구하고있다. 그러나 나는 그것을 더 직접적으로 묻고있다.Windows에서 원자 적으로 두 개의 포인터를 어떻게 바꿀 수 있습니까?

동일한 클래스의 두 인스턴스에서 두 개의 포인터 변수가 있습니다. 나는 그 변수의 내용을 바꾸고 싶다. (POINT가 아니라 변수 그 자체) 원자 적으로 바꾸고 싶다.

가능하면 잠금을 피하고 싶습니다.

어떻게하면됩니까?

EDIT : 세 개의 "InterlockedExchangePointer"답변에 먼저 MSDN docs을 읽어주십시오. InterlockedExchangePointer는 스택 레지스터의 값을 가진 포인터 대상 값을 교환합니다. 그것은 (그 자체로) 메모리 위치에서 두 개의 포인터를 교환하지 않습니다.

+7

두 개의 메모리 주소 내용을 바꾸는 비 잠금 X86 명령이 있다고 생각하지 않습니다. CPU를 지원하지 않으면 이러한 기능을 구현하기 어려울 것입니다. 포인터에 대한 보증이 있습니까? (예 : 항상 메모리에 인접 해 있습니까? 그렇다면 루프에서 8 바이트 또는 16 바이트 비교/교환을 사용할 수 있습니다.) –

+0

@James : 모든 사람의 의견에 똑같은 내용을 올린 후 : 'int * p1 = somevalue; int * p2 = someothervalue; p2 = InterlockedExchangePointer (p1, p2);'그냥 그렇게 할 것입니다. 그 밑에는 중요한 섹션이 있으므로 잠금을 완전히 피할 필요가 있는지 잘 모르겠습니다. –

+1

와우, 많은 사람들이 잘못된 대답을하고 있습니다 ...이것은 인터뷰 질문 ':-)이되어야합니다. – rubenvb

답변

13

저는 사지에 나가서 자물쇠가 필요하며 일반적인 문제가없는 자물쇠가 없다고 말합니다.

두 주소에서 읽은 다음 두 주소 모두에 모두 원자 적으로 다시 써야합니다. 내가 아는 한, X86은 단일 메모리 주소와 레지스터의 데이터를 원자 적으로 교환 할 수 있습니다. 나는 두 개의 메모리 주소의 내용을 교환 할 수 있다고 생각하지 않는다.

포인터가있는 위치에 제약 조건을 넣을 수 있다면 이것을 할 수 있습니다. 예를 들어, 포인터가 메모리에서 인접하도록 보장 할 수 있다면 루프에서 64 비트 또는 128 비트 비교/교환을 사용할 수 있습니다.

다른 간단한 경우에 대한 해결책이있을 수 있지만 일반적인 경우에 대해 잠금없는 해결책을 찾지 않을 것이라고 생각합니다.

+0

+1 - 나에게 'WindowsApi :: AutoArray :: Swap'스레드 안전성이없는 것처럼 보입니다. (왜냐하면 각 포인터가 중요한 섹션을 유지하는 오버 헤드를 정당화하지 않기 때문입니다!) –

+1

+1 나는 이것이 옳다고 생각합니다. –

+0

제한된 범위의 프로세서에는 두 번의 비교 및 ​​스왑 연산 (DCAS/CAS2)이 있습니다. 비슷한 효과를 내기 위해 CMPXCHG16B (두 배 폭)를 사용할 수도 있습니다. 이것은 많은 CPU가이 지침을 지원하지 않는다는 점에서 "일반적인"것이 아니지만이를 수행하는 CPU에서는 수행 할 수 있습니다. DCAS는 motorola 68k에, CMPXCHG16B는 64 비트 Intel 및 * 최신 * 64 비트 AMD에 있지만 이전 버전에는 없습니다. _InterlockedCompareExchange128은 이것을 원자 128 비트 필드로 평가 된 64 비트 포인터의 배열로 구현하지만 프로세서가 명령을 지원하지 않으면 분해합니다. – Lisa

-2

x86 프로세서 xchg 명령이 원하는 작업인지 확인한 다음 인라인 어셈블리 기능으로 래핑 할 수 있습니다. 모든 프로세서 단일 명령어는 원자 적으로 보장됩니다.

+0

이 대답은 InterlockedExchangePointer 답변과 동일한 문제가 있습니다. –

+0

+1 왜냐하면 * if *가 * 원하는대로 처리하기 때문에 * false를 반환하기 때문에 간단한 방법을 찾지 못할 것입니다. –

+0

@Pete : * "if"가 false를 반환하면 this 비록 그것이 사실이 아니라고하더라도 제 질문에 답하지 않습니다. –

2

swap의 원자 단위 연동 버전을 찾고 있습니다.

내 지식으로는 Windows API 프리미티브 만 사용하고 명시 적 잠금을 사용하지 않는 방법은 없습니다. 전달 된 매개 변수 중 하나만 변경되므로 다른 사람들이 권장하는 다양한 Interlocked 함수가 작동하지 않습니다. 둘 다 변경하려고합니다.

또한 Interlocked 함수는 서로에 대해서만 연동되어 있다는 점을 지적 할 수 있습니다. 이 포인터 중 하나를 업데이트하지만 Interlocked을 사용하지 않는 다른 코드가 있으면 코드가 더 이상 안전하지 않습니다. 나는 당신이 이것을 깨달을 것이라고 확신하지만, 나는 그것을 언급 할 것이라고 생각했다.

아는 한 라이브러리를 사용하거나이 코드를 직접 작성해야합니다.

관련 문제