4

このコードは機能しているように見えますが、InterlockedIncrement 関数を正しく使用していますか? m_count の正しいメモリ アラインメントは、私の主な関心事です。x86-64 システムを使用していて、64 ビット アプリケーションをコンパイルするとします (問題がある場合)。ところで、私の実際の目的では、 m_count を volatile long として宣言してから InterlockedIncrement(&m_count); を使用することはできません。ただし、ヒープ内のデータへのポインターである必要があります。

#include <Windows.h>
#include <malloc.h>

class ThreadSafeCounter {
public:
    ThreadSafeCounter()
    {
        // Are those arguments for size and alignment correct?
        void* placement = _aligned_malloc( sizeof(long), sizeof(long) );
        m_count = new (placement) long(0);
    }
    ~ThreadSafeCounter()
    {
        _aligned_free( const_cast<long*>(m_count) );
    }

    void AddOne()
    {
        InterlockedIncrement(m_count);
    }

    long GetCount()
    {
        return *m_count;
    }

private:
    volatile long* m_count;
};
4

3 に答える 3

6

ヒープ アロケーターは、返されたアドレスをネイティブ プラットフォームのワード サイズに既に揃えています。x86 の場合は 4 バイト、x64 の場合は 8 バイト。MSVC のいずれかのプラットフォームでlong、32 ビットを使用しています。_aligned_malloc() フープをジャンプする必要はありません。

于 2010-12-01T13:27:10.413 に答える
3

これはプラットフォーム アーキテクチャの詳細ですが、アトミック操作にはアライメント以上のものがあることを覚えておく必要があります。プラットフォーム ABI は通常、デフォルトでプリミティブ データ型のアラインメントが確実に行われるようにして、あらゆる操作 (アトミックを含む) が機能するようにします。malloc() は、1 バイトを要求したとしても、整列されていないポインターを返すことはありません。

それに加えて、特にhttp://en.wikipedia.org/wiki/False_sharingに気をつけてください-アライメント(通常はa)の必要性を超えていることを意味しsizeof(long)ます。また、アトミックにアクセスされる変数を1つだけホストするようにする必要があります同じキャッシュライン内。

これらのカウンターの配列を使用/許可する予定がある場合、これは特に重要です。

Microsoft のコンパイラは__declspec(align(value))、特定の構造のアラインメントを保証するようにコンパイラに指示するために使用します。他の人が述べたように、そのようなデータ構造/クラスをヒープに割り当てる必要は特にないようですが、他の何かに pimpl が必要かどうかはわかりません。

于 2010-12-01T12:18:38.673 に答える
1

ユースケースで行う最も簡単な方法は、継承による侵入参照カウントを使用して、この必要性をなくすことです。

ただし、どうしようもない場合は、MSVC の shared_ptr の実装を確認してください。

    typename aligned_storage<sizeof(_Ty),
        alignment_of<_Ty>::value>::type _Storage;
    };
    _Ty *_Getptr() const {  // get pointer
        return ((_Ty *)&_Storage);
    }

そのCキャストはかなり厄介です。ただし、これは、このオブジェクトが型の特性を利用して、間違いなく正しいアライメントを持っていることを示唆しています。

于 2010-12-01T12:44:25.477 に答える