_InterlockedCompareExchange
iç işlevler
Microsoft'a Özgü
Birbirine bağlı karşılaştırma ve değiştirme işlemi yapar.
Sözdizimi
long _InterlockedCompareExchange(
long volatile * Destination,
long Exchange,
long Comparand
);
long _InterlockedCompareExchange_acq(
long volatile * Destination,
long Exchange,
long Comparand
);
long _InterlockedCompareExchange_HLEAcquire(
long volatile * Destination,
long Exchange,
long Comparand
);
long _InterlockedCompareExchange_HLERelease(
long volatile * Destination,
long Exchange,
long Comparand
);
long _InterlockedCompareExchange_nf(
long volatile * Destination,
long Exchange,
long Comparand
);
long _InterlockedCompareExchange_np(
long volatile * Destination,
long Exchange,
long Comparand
);
long _InterlockedCompareExchange_rel(
long volatile * Destination,
long Exchange,
long Comparand
);
char _InterlockedCompareExchange8(
char volatile * Destination,
char Exchange,
char Comparand
);
char _InterlockedCompareExchange8_acq(
char volatile * Destination,
char Exchange,
char Comparand
);
char _InterlockedCompareExchange8_nf(
char volatile * Destination,
char Exchange,
char Comparand
);
char _InterlockedCompareExchange8_rel(
char volatile * Destination,
char Exchange,
char Comparand
);
short _InterlockedCompareExchange16(
short volatile * Destination,
short Exchange,
short Comparand
);
short _InterlockedCompareExchange16_acq(
short volatile * Destination,
short Exchange,
short Comparand
);
short _InterlockedCompareExchange16_nf(
short volatile * Destination,
short Exchange,
short Comparand
);
short _InterlockedCompareExchange16_np(
short volatile * Destination,
short Exchange,
short Comparand
);
short _InterlockedCompareExchange16_rel(
short volatile * Destination,
short Exchange,
short Comparand
);
__int64 _InterlockedCompareExchange64(
__int64 volatile * Destination,
__int64 Exchange,
__int64 Comparand
);
__int64 _InterlockedCompareExchange64_acq(
__int64 volatile * Destination,
__int64 Exchange,
__int64 Comparand
);
__int64 _InterlockedCompareExchange64_HLEAcquire (
__int64 volatile * Destination,
__int64 Exchange,
__int64 Comparand
);
__int64 _InterlockedCompareExchange64_HLERelease(
__int64 volatile * Destination,
__int64 Exchange,
__int64 Comparand
);
__int64 _InterlockedCompareExchange64_nf(
__int64 volatile * Destination,
__int64 Exchange,
__int64 Comparand
);
__int64 _InterlockedCompareExchange64_np(
__int64 volatile * Destination,
__int64 Exchange,
__int64 Comparand
);
__int64 _InterlockedCompareExchange64_rel(
__int64 volatile * Destination,
__int64 Exchange,
__int64 Comparand
);
Parametreler
Destination
[in, out] Hedef değerin işaretçisi. İşaret yoksayılır.
Exchange
[in] Exchange değeri. İşaret yoksayılır.
Comparand
[in] ile işaret edilen Destination
değerle karşılaştırılan değer. İşaret yoksayılır.
Dönüş değeri
Dönüş değeri, işaretçinin işaret ettiği Destination
ilk değerdir.
Gereksinimler
Içsel | Mimari | Üst bilgi |
---|---|---|
_InterlockedCompareExchange , _InterlockedCompareExchange8 , _InterlockedCompareExchange16 , _InterlockedCompareExchange64 |
x86, ARM, x64, ARM64 | <intrin.h> |
_InterlockedCompareExchange_acq , _InterlockedCompareExchange_nf , , _InterlockedCompareExchange_rel , _InterlockedCompareExchange8_acq , _InterlockedCompareExchange8_nf , _InterlockedCompareExchange8_rel , , _InterlockedCompareExchange16_acq , _InterlockedCompareExchange16_nf , _InterlockedCompareExchange16_rel _InterlockedCompareExchange64_acq , _InterlockedCompareExchange64_nf ,_InterlockedCompareExchange64_rel |
ARM, ARM64 | <intrin.h> |
_InterlockedCompareExchange_np , _InterlockedCompareExchange16_np , _InterlockedCompareExchange64_np |
x64 | <intrin.h> |
_InterlockedCompareExchange_HLEAcquire , _InterlockedCompareExchange_HLERelease , _InterlockedCompareExchange64_HLEAcquire , _InterlockedCompareExchange64_HLERelease |
x86, x64 | <immintrin.h> |
Açıklamalar
_InterlockedCompareExchange
değeriyle işaret edilen Destination
değerin atomik karşılaştırmasını Comparand
yapar. Destination
Değer değere Comparand
eşitse, Exchange
değeri tarafından Destination
belirtilen adreste depolanır. Aksi takdirde, hiçbir işlem yapmaz.
_InterlockedCompareExchange
Win32 Windows SDK InterlockedCompareExchange
işlevi için derleyici iç desteği sağlar.
İçerdikleri veri türlerine ve işlemciye özgü alma veya yayın semantiği kullanılıp kullanılmadığına bağlı olarak değişen çeşitli varyasyonlar _InterlockedCompareExchange
vardır.
_InterlockedCompareExchange
İşlev 32 bit long
tamsayı değerleri üzerinde çalışırken, _InterlockedCompareExchange8
8 bit tamsayı değerlerinde_InterlockedCompareExchange16
, 16 bit short
tamsayı değerlerinde ve _InterlockedCompareExchange64
64 bit tamsayı değerlerinde çalışır. 128 bit değerler için benzer iç bilgiler hakkında daha fazla bilgi için bkz _InterlockedCompareExchange128
. .
Tüm ARM platformlarında, kritik bir bölümün _acq
başında ve _rel
sonunda olduğu gibi alma ve yayın semantiği için iç bilgileri ve soneklerini kullanın. Bir ("çit yok") soneki olan _nf
ARM iç bilgileri bellek engeli görevi görmez.
Bir ("ön ek yok") soneki olan _np
içler, olası bir ön işlem derleyici tarafından eklenmesini engeller.
Donanım Kilidi Elision (HLE) yönergelerini destekleyen Intel platformlarında, ve _HLERelease
sonekleri ile _HLEAcquire
iç bilgiler, donanımda kilit yazma adımını ortadan kaldırarak performansı hızlandırabilecek işlemciye yönelik bir ipucu içerir. Bu iç öğeler HLE'yi desteklemeyen platformlarda çağrılırsa ipucu yoksayılır.
Bu yordamlar yalnızca iç yordamlar olarak kullanılabilir.
Örnek
Aşağıdaki örnekte, _InterlockedCompareExchange
basit alt düzey iş parçacığı eşitlemesi için kullanılır. Yaklaşımın çok iş parçacıklı programlama için temel olarak sınırlamaları vardır; birbirine kenetlenmiş içsellerin tipik kullanımını göstermek için sunulur. En iyi sonuçlar için Windows API'sini kullanın. Çok iş parçacıklı programlama hakkında daha fazla bilgi için bkz . Çok İş Parçacıklı Win32 Programı Yazma.
// intrinExample.cpp
// compile with: /EHsc /O2
// Simple example of using _Interlocked* intrinsics to
// do manual synchronization
//
// Add [-DSKIP_LOCKING] to the command line to disable
// the locking. This will cause the threads to execute out
// of sequence.
#define _CRT_RAND_S
#include "windows.h"
#include <iostream>
#include <queue>
#include <intrin.h>
using namespace std;
// --------------------------------------------------------------------
// if defined, will not do any locking on shared data
//#define SKIP_LOCKING
// A common way of locking using _InterlockedCompareExchange.
// Refer to other sources for a discussion of the many issues
// involved. For example, this particular locking scheme performs well
// when lock contention is low, as the while loop overhead is small and
// locks are acquired very quickly, but degrades as many callers want
// the lock and most threads are doing a lot of interlocked spinning.
// There are also no guarantees that a caller will ever acquire the
// lock.
namespace MyInterlockedIntrinsicLock
{
typedef unsigned LOCK, *PLOCK;
#pragma intrinsic(_InterlockedCompareExchange, _InterlockedExchange)
enum {LOCK_IS_FREE = 0, LOCK_IS_TAKEN = 1};
void Lock(PLOCK pl)
{
#if !defined(SKIP_LOCKING)
// If *pl == LOCK_IS_FREE, it is set to LOCK_IS_TAKEN
// atomically, so only 1 caller gets the lock.
// If *pl == LOCK_IS_TAKEN,
// the result is LOCK_IS_TAKEN, and the while loop keeps spinning.
while (_InterlockedCompareExchange((long *)pl,
LOCK_IS_TAKEN, // exchange
LOCK_IS_FREE) // comparand
== LOCK_IS_TAKEN)
{
// spin!
}
// This will also work.
//while (_InterlockedExchange(pl, LOCK_IS_TAKEN) ==
// LOCK_IS_TAKEN)
//{
// // spin!
//}
// At this point, the lock is acquired.
#endif
}
void Unlock(PLOCK pl) {
#if !defined(SKIP_LOCKING)
_InterlockedExchange((long *)pl, LOCK_IS_FREE);
#endif
}
}
// ------------------------------------------------------------------
// Data shared by threads
queue<int> SharedQueue;
MyInterlockedIntrinsicLock::LOCK SharedLock;
int TicketNumber;
// ------------------------------------------------------------------
DWORD WINAPI
ProducerThread(
LPVOID unused
)
{
unsigned int randValue;
while (1) {
// Acquire shared data. Enter critical section.
MyInterlockedIntrinsicLock::Lock(&SharedLock);
//cout << ">" << TicketNumber << endl;
SharedQueue.push(TicketNumber++);
// Release shared data. Leave critical section.
MyInterlockedIntrinsicLock::Unlock(&SharedLock);
rand_s(&randValue);
Sleep(randValue % 20);
}
return 0;
}
DWORD WINAPI
ConsumerThread(
LPVOID unused
)
{
while (1) {
// Acquire shared data. Enter critical section
MyInterlockedIntrinsicLock::Lock(&SharedLock);
if (!SharedQueue.empty()) {
int x = SharedQueue.front();
cout << "<" << x << endl;
SharedQueue.pop();
}
// Release shared data. Leave critical section
MyInterlockedIntrinsicLock::Unlock(&SharedLock);
unsigned int randValue;
rand_s(&randValue);
Sleep(randValue % 20);
}
return 0;
}
int main(
void
)
{
const int timeoutTime = 500;
int unused1, unused2;
HANDLE threads[4];
// The program creates 4 threads:
// two producer threads adding to the queue
// and two consumers taking data out and printing it.
threads[0] = CreateThread(NULL,
0,
ProducerThread,
&unused1,
0,
(LPDWORD)&unused2);
threads[1] = CreateThread(NULL,
0,
ConsumerThread,
&unused1,
0,
(LPDWORD)&unused2);
threads[2] = CreateThread(NULL,
0,
ProducerThread,
&unused1,
0,
(LPDWORD)&unused2);
threads[3] = CreateThread(NULL,
0,
ConsumerThread,
&unused1,
0,
(LPDWORD)&unused2);
WaitForMultipleObjects(4, threads, TRUE, timeoutTime);
return 0;
}
<0
<1
<2
<3
<4
<5
<6
<7
<8
<9
<10
<11
<12
<13
<14
<15
<16
<17
<18
<19
<20
<21
<22
<23
<24
<25
<26
<27
<28
<29
END Microsoft'a Özgü
Ayrıca bkz.
_InterlockedCompareExchange128
_InterlockedCompareExchangePointer
iç işlevler
Derleyici iç bilgileri
Anahtar Sözcükler
x86 Derleyicisi ile Çakışma