Войти
ПрограммированиеФорумОбщее

WinAPI, C++: шаблон для InterlockedCompareExchange.

#0
17:37, 10 янв. 2020

Привет.
Есть в WinAPI реализация InterlockedCompareExchange для 32-битных значений (volatile long).
Захотелось поддержку 8 бит (_InterlockedCompareExchange8).

Подскажите, как сделать в следующем шаблоне: пытаемся CompareExchange,
если неудачно, ждём, снова пытаемся.
Как разрулить InterlockedCompareExchange и _InterlockedCompareExchange8.

template< typename T >
class  MyLocker
{
  volatile T* pMutex_ = nullptr;

public:

  ~MyLocker()
  {
    Unlock();
  }


  HRES  Lock( volatile T* pMutex, DWORD sleepMs )
  {
if( sizeof(T) == 32 )
    while( InterlockedCompareExchange( pMutex, 1, 0 ) != 0 ) // Вот здесь выбрать один из вариантов InterlockedCompareExchange.
if( sizeof(T) == 8 )
    while( _InterlockedCompareExchange8( pMutex, 1, 0 ) != 0 ) // В идеале в compile time.
    {
      Sleep( sleepMs );

      if( WaitTimeOver() )
        return ErrorTimeout;
    }

    pMutex_ = pMutex;    return S_OK;
  }


  void  Unlock()
  {
    if( pMutex_ )  {  *pMutex_ = 0;  pMutex_ = null;  }
  }
};

typedef MyLocker<long>  Locker32;
typedef MyLocker<char>  Locker8;

Буду признателен за решение. Ну или за совет, как сделать по другому.


#1
19:42, 10 янв. 2020

Kroll
Вам товарищ тут не интерлок нужен, а событие.

#2
19:46, 10 янв. 2020

Для того чтобы ждать нужно использовать CONDITION_VARIABLE / SleepConditionVariableCS(...)
Interlocked функции сделаны для обеспечения атомарных операций (как раз для того чтобы не было необходимости использовать критическую секцию).

#3
(Правка: 12:40) 12:03, 11 янв. 2020

Интерлок испльзую для доступа к данным с нескольких потоков. Как мьютекс.

#4
13:13, 11 янв. 2020

std::atomic<>

А вообще зачем нужны 8 бит? Все равно при синхронизации кэша все передается блоками по 64 байта

#5
17:52, 11 янв. 2020

/A\
Для микроконтроллеров. Там памяти не очень много.

#6
18:03, 11 янв. 2020

/A\
> std::atomic<>
> А вообще зачем нужны 8 бит?

Скорее зачем нужны WinAPI, когда в std:: кроме <atomic> есть <thread> <mutex> <condition_variable>?
Можно на микроконтроллер скомпилять, там может 8бит и пригодится.  :-)

#7
18:13, 11 янв. 2020

Kroll
> Интерлок испльзую для доступа к данным с нескольких потоков. Как мьютекс.

Для этого интерлок не предназначен.

#8
18:18, 11 янв. 2020

gamedevfor
> Для этого интерлок не предназначен.
Это спинлок называется

#9
(Правка: 18:51) 18:34, 11 янв. 2020

Kroll
> Sleep( sleepMs );
Так только говноеды делают.

> Как разрулить InterlockedCompareExchange и _InterlockedCompareExchange8.
Очевидно, эти атомарные операции в голом виде для блокирования чего-либо не годятся, не даром алгоритмы с применением атомиков называют lock free. Если интересно как реализован механизм блокировки на низком уровне, смотри как реализован Low Level Lock в линуксах.

> Буду признателен за решение. Ну или за совет, как сделать по другому.
Вместо атомарных операций логичнее было бы использовать уже готовый спинлок

UPD.
https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-sy… waitonaddress

#10
18:34, 11 янв. 2020

/A\
> Это спинлок называется

возможно в недрах операционки такое и нужно, в юзерспейсе - это полная хрень.

#11
12:29, 12 янв. 2020

rcsim
спасибо

ПрограммированиеФорумОбщее