Qt의 원자 조작

5838 단어 Qt
이른바 원자 조작이란 일련의 복잡한 조작이 단숨에 이루어져 중간에 다른 조작에 의해 끊어지지 않는다는 것이다.이것은 다중 루틴 프로그램에서 특히 흔히 볼 수 있지만 이런 기능을 실현하려면 프로그램의 양호한 설계를 고려해야 할 뿐만 아니라 특정 플랫폼의 체계 구조와 관련 컴파일러가 원자 특성에 대한 지원 정도도 고려해야 한다.그래서 이 과정을 간소화하기 위해 Qt는 우리에게 QAtomic Integer 템플릿 클래스를 제공했다. 이 클래스는 원자 조작과 관련된 대량의 세부 사항과 하부 특성을 봉하여 우리에게 편리하고 사용하기 쉬운 상부 인터페이스를 제공했다.비록 이 종류는 모든 원자 조작 문제를 해결할 수 없다. 예를 들어 서로 다른 메모리 모델에서 공유 변수에 대한 원자 접근을 어떻게 보장하는지는 우리의 인위적인 제어가 필요하지만 이것은 우리의 업무 복잡도를 크게 경감시켰다.
QAtomic Integer 템플릿 클래스는 주로 정수에 자주 사용되는 원자 조작을 제공합니다. 예를 들어reference counting,test-and-set,fetch-and-store,fetch-and-add입니다.QAtomicInteger는 말 그대로 이 종류는 정수 유형에만 적용될 수 있다. 그러면 Qt에서 어떤 정형이 이 종류를 사용하여 원자 조작을 할 수 있는지 살펴보자.다음 표는 다음과 같습니다.
자릿수
타입
8-bit
char, signed char, unsigned char, qint8, quint8
16-bit
short, unsigned short, qint16, quint16, char16_t(c++11)
32-bit
int, unsigned int, qint32, quint32, char32_t(c++11)
64-bit
long long, unsigned long long, qint64, quint64
platform-specific size
long, unsigned long
pointer size
qintptr, quintptr, qptrdiff
위 표에서 32-bit와pointer-sized의 실례만 모든 플랫폼에서 보장됩니다.그러나 다른 크기에 대한 지원은 특정한 컴파일러와 프로그램을 실행하는 프로세서를 보아야 한다.자신의 플랫폼이 특정 유형을 지원하는지 확인하기 위해 Qt에서 제공하는 매크로 QATOMIC_INT{nn}_IS_SUPPORTED, 여기nn은 당신이 테스트하고 싶은 유형의 자리수입니다.
다음은 QAtomicInteger가 제공하는 작업을 구체적으로 보기 전에 원자 작업과 관련된 메모리 순서(메모리 모델)를 살펴보겠습니다.
방금 우리가 말했듯이QAtomic Integer는 우리에게 몇 가지 원자 조작test-and-set,fetch-and-store,fetch-and-add를 제공했다.사실 이러한 함수의 실현은 모두 메모리 순서의 의미를 정의했다. 이 의미는 프로세서가 원자 문장을 실행할 때 이 원자 문장과 그 전후의 메모리에 어떻게 접근하는지를 설명한다.현대의 프로세서 구조는 메모리에 대한 임의의 접근을 허용하기 때문에 프로그램이 모든 프로세서에서 정확하게 실행될 수 있도록 적당한 메모리 접근의 의미를 사용하는 것이 중요하다.Qt에서는 4가지 메모리 모델을 제공합니다.
  • Relaxed - 메모리 액세스 순서를 구체적으로 지정하지 않고 컴파일러와 프로세서가 자유롭게 메모리 액세스를 순서재정리할 수 있습니다.
  • Acquire - 원자 작업 이후의 메모리 액세스(이미 프로그램의 순서)는 원자 작업 전에 순서를 재정리하지 않습니다.
  • Release - 원자 작업 이전의 메모리 접근(이미 프로그램의 순서)은 원자 작업 후에 다시 정렬되지 않습니다.
  • Ordered - Acquire와 Release의 조합

  • 다음은 관련 원자 작업 API를 살펴보겠습니다.
           Reference counting
    함수 ref()와 deref()는 효율적인 참조 계수 API를 제공합니다.이 함수들의 반환값은 마지막 인용이 언제 방출되었는지 보여 준다.이런 기능들은 우리 자신의 스텔스 공유 유형을 실현하는 데 쓸 수 있다.코드는 다음과 같습니다.
      MySharedType &MySharedType::operator=(const MySharedType &other)
      {
          (void) other.data->atomicInt.ref();
          if (!data->atomicInt.deref()) {
              // The last reference has been released
              delete d;
          }
          d = other.d;
          return *this;
      }
           
            Test-and-set
    이 함수들이 완성한 기능은 QAtomicInteger의 현재 값이 우리가 입력한 기대 값과 같으면test-and-set 함수가 새로운 값을 부여하고true로 되돌아오는 것입니다.현재 값이 들어오는 기대 값과 같지 않으면, 이 함수 성명도 하지 않고,false로 되돌아옵니다.코드 로직은 다음과 같습니다.
      if (currentValue == expectedValue) {
          currentValue = newValue;
          return true;
      }
      return false;

    QAtomic Integer에서 4개의test-and-set 함수를 제공했는데 그것이 바로testAndSetRelaxed(), testAndSetAcquire(), testAndSetRelease(), testAndSetOrdered()이다.사실은 서로 다른 메모리 모델로 조작하는 것이다.
             Fetch-and-store
    fetch-and-store 함수는 QAtomicInteger 대상의 현재 값을 읽고 우리가 입력한 새 값을 설정한 다음 읽은 옛 값을 되돌려줍니다.이 작업은 다음 코드 로직과 동일합니다.
      int originalValue = currentValue;
      currentValue = newValue;
      return originalValue;

    QAtomic Integer에는 4개의fetch-and-store 함수가있습니다:fetchAndStore Relaxed(),fetchAndStore Acquire(),fetchAndStore Release(),fetchAndStore Ordered().
             
             Fetch-and-add
    fetch-and-add 함수는 QAtomicInteger 대상의 현재 값을 읽고 우리가 전송한 값을 추가한 다음 원래의 값을 되돌려줍니다.실행 논리는 다음 코드와 유사합니다.
      int originalValue = currentValue;
      currentValue += valueToAdd;
      return originalValue;

    QAtomic Integer 중에는 4개의fetch-and-add 방법이 있는데 그것이 바로fetchAndAddRelaxed(),fetchAndAddAcquire(),fetchAndAddRelease(),fetchAndAddOrdered()이다.
           
    특성 테스트 관련 API
    플랫폼과 상관없이 프로세서에 적용될 수 있는 원자 조작 API를 제공하는 것은 도전적이다.따라서 QAtomic Integer 클래스가 제공하는 API는 모든 프로세서의 원자 조작을 보장할 수 있지만, 이 프로세서가 QAtomic Integer가 제공하는 이러한 조작을 모두 지원하는 것은 아니다.따라서 이 작업을 사용하기 전에 현재 프로세서가 어떤 API를 지원하는지 확인하는 것이 중요하다.
    그래서 Qt는 대량의 매크로를 제공합니다. 이 매크로를 사용하면 컴파일러에서 하드웨어가 어떤 기능을 지원하는지 확인할 수 있습니다.이 매크로들은 하드웨어가 이 조작을 지원하고, 때로는 이 조작을 지원하며, 이 조작을 지원하지 않는다는 것을 알려 줍니다.또한, 이러한 매크로는 대체적으로 같은 형식을 가지고 있어 기억하기 편리하다. Q 와 유사하다ATOMIC_INTnn_OPERATION_IS_HOW_NATIVE.그중,nn은 당신이 테스트할 성형의 위치,operation은 REFERENCECOUNTING、TEST_AND_SET、FETCH_AND_STORE、FETCH_AND_ADD 중 하나이고 how는 ALWAYS, SOMETIMES, NOT 중 하나입니다.그리고 각 조합에 대응하는 것은 하나의 확실한 매크로만 있다.예를 들어, QATOMIC_INT32_REFERENCE_COUNTING_IS_ALWAYS_NATIVE가 정의되었으니 QATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE 및 QATOMIC_INT32_REFERENCE_COUNTING_IS_NOT_NATIVE는 정의되지 않습니다.
    만약 하나의 조작이 상수 시간 안에 완성될 수 있다면, 우리는 그것이wait-free라고 말한다.이런 조작의 실현은 자물쇠나 어떤 순환을 필요로 하지 않는다.그리고 Qt에서 플랫폼에서 지원되는 원자 조작은 모두 웨이트-free이다.또한 Qt는 매크로 Q 를 정의합니다.ATOMIC_INTnn_OPERATION_IS_WAIT_FREE는 원자 조작이 wait-free인지 검사합니다.
    이외에 일부 원자 조작은 비교적 새로운 프로세서에서만 지원할 수 있기 때문에, 우리는 컴파일할 때 특정한 특성이 지원되는지 검사해야 하는 것 외에 프로그램이 실행될 때도 이런 검사가 필요하다.따라서 Qt는 위의 매크로를 컴파일할 때 검출하는 것 외에 몇 개의 API 사용자가 코드에서 실행할 때 검출하는 것도 제공한다. 예를 들어 isReference Counting Native (), isTest And SetNative (), isFetchAndStore Native (), isFetchAnd And Native ().이와 함께 isReference Counting WaitFree(), isTest And SetWaitFree(), isFetchAndStore WaitFree(), isFetchAnd AddWaitFree() 등 wait-free 특성에 대한 감지 함수도 제공했다.
    Qt의 원자 조작은 서로 다른 버전에서 다르기 때문에 Qt는 오래된 버전에 대한 호환성에 있다. nn이 없는 매크로는 32-bit의 매크로와 같다.예를 들어, QATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE는 Q 와 같습니다.ATOMIC_INT32_REFERENCE_COUNTING_IS_WAIT_FREE.
    마지막으로 위에서 큰 측면에서 QAtomic Integer류의 기능을 설명했을 뿐 그 중의 모든 함수의 구체적인 사용도 모두 이름만 알고 뜻을 알 수 있다. 예를 들어++,--,load,store 등이다. 여기서 일일이 설명하지 않고 여러분이 사용할 때 Qt 도움말 문서를 참고하면 된다.또한 Qt는 QAtomicInt와 QAtomicPointer 클래스를 제공하는데 사용법은 이와 유사하다.

    좋은 웹페이지 즐겨찾기