пример cmpxchg для целого числа на 64 бита

РЕДАКТИРОВАТЬ

Некоторый ваш код кажется мне немного странным:

export const LoggedInHOC = WrapperComponent => props => class

// Later
export default compose(
  LoggedInHOC(FeedScreen)
)(FeedScreen)

LoggedInHOC здесь есть функция, которая принимает компонент и возвращает функция, которая возвращает компонент, когда она, вероятно, должна быть только функцией, которая принимает компонент и возвращает компонент.

Я собираюсь предположить, что ваша роль LoggedInHOC состоит в том, чтобы проверить, подключен ли пользователь каким-либо образом, отобразить упакованный компонент, если это так, и перенаправить пользователя / показать форму входа в систему в противном случае.

Вы могли бы написать это так:

export const LoggedInHOC = Component => class extends React.Component {
  render () {
    // Check if the user is connected
    if (connected) {
      return (
        
      );
    }

    return 

User not connected

; } };

И вы бы обернули свой компонент таким образом

export default LoggedInHOC(Component);

// Or if you want to chain multiple hocs:
export default compose(
  LoggedInHOC,
  AnotherHOC
)(Component);

Теперь вернемся к вашему первоначальному вопросу о связывании нескольких HOC и componentDidUpdate жизненный цикл. Я не уверен, что именно является проблемой в вашем случае, но написание:

export default compose(
  HOC1,
  HOC2
)(Component);

эквивалентно HOC1(HOC2(Component)). Итак, с точки зрения композиции у вас есть:

HOC1
  HOC2
    Component

И вы должны иметь в виду, что когда обновляется ваша HOC1 оболочка, это вызовет обновление в вашем HOC2 и в Component но если вы обновите HOC2, это не приведет к обновлению вашего HOC1.

Я создал пример codepen, который отображает компонент, заключенный в несколько HOC, каждый из которых реализует ловушку componentDidUpdate

5
задан Peter Cordes 15 April 2018 в 05:45
поделиться

3 ответа

The x86_64 instruction set has the cmpxchgq (q for quadword) instruction for 8-byte (64 bit) compare and swap.

There's also a cmpxchg8b instruction which will work on 8-byte quantities but it's more complex to set up, needing you to use edx:eax and ecx:ebx rather than the more natural 64-bit rax. The reason this exists almost certainly has to do with the fact Intel needed 64-bit compare-and-swap operations long before x86_64 came along. It still exists in 64-bit mode, but is no longer the only option.

But, as stated, cmpxchgq is probably the better option for 64-bit code.


If you need to cmpxchg a 16 byte object, the 64-bit version of cmpxchg8b is cmpxchg16b. It was missing from the very earliest AMD64 CPUs, so compilers won't generate it for std::atomic::compare_exchange on 16B objects unless you enable -mcx16 (for gcc). Assemblers will assemble it, though, but beware that your binary won't run on the earliest K8 CPUs. (This only applies to cmpxchg16b, not to cmpxchg8b in 64-bit mode, or to cmpxchgq).

7
ответ дан 14 December 2019 в 01:16
поделиться

The x64 architecture supports a 64-bit compare-exchange using the good, old cmpexch instruction. Or you could also use the somewhat more complicated cmpexch8b instruction (from the "AMD64 Architecture Programmer's Manual Volume 1: Application Programming"):

The CMPXCHG instruction compares a value in the AL or rAX register with the first (destination) operand, and sets the arithmetic flags (ZF, OF, SF, AF, CF, PF) according to the result. If the compared values are equal, the source operand is loaded into the destination operand. If they are not equal, the first operand is loaded into the accumulator. CMPXCHG can be used to try to intercept a semaphore, i.e. test if its state is free, and if so, load a new value into the semaphore, making its state busy. The test and load are performed atomically, so that concurrent processes or threads which use the semaphore to access a shared object will not conflict.

The CMPXCHG8B instruction compares the 64-bit values in the EDX:EAX registers with a 64-bit memory location. If the values are equal, the zero flag (ZF) is set, and the ECX:EBX value is copied to the memory location. Otherwise, the ZF flag is cleared, and the memory value is copied to EDX:EAX.

The CMPXCHG16B instruction compares the 128-bit value in the RDX:RAX and RCX:RBX registers with a 128-bit memory location. If the values are equal, the zero flag (ZF) is set, and the RCX:RBX value is copied to the memory location. Otherwise, the ZF flag is cleared, and the memory value is copied to rDX:rAX.

Different assembler syntaxes may need to have the length of the operations specified in the instruction mnemonic if the size of the operands can't be inferred. This may be the case for GCC's inline assembler - I don't know.

1
ответ дан 14 December 2019 в 01:16
поделиться

cmpxchg8b

__forceinline int64_t interlockedCompareExchange(volatile int64_t & v,int64_t exValue,int64_t cmpValue)
{
  __asm {
    mov         esi,v
    mov         ebx,dword ptr exValue
    mov         ecx,dword ptr exValue + 4
    mov         eax,dword ptr cmpValue
    mov         edx,dword ptr cmpValue + 4
    lock cmpxchg8b qword ptr [esi]
  }
}
2
ответ дан 14 December 2019 в 01:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: