2

私はスレッド同期が初めてです。win32のboost::threadsやpthreadなど、条件変数の多くの実装を読んでいました。私は、wait/notify/noifyall を使用してこの非常に単純なモニターを実装しましたが、これには多くの隠れた問題があると思います。経験豊富な人から発見したいと思います。なにか提案を?

class ConditionVar
{

public :
    ConditionVar () : semaphore ( INVALID_HANDLE_VALUE ) , total_waiters (0)
    {
        semaphore = ::CreateSemaphoreA ( NULL , 0 /* initial count */ , LONG_MAX /* max count */ , NULL );
    }

    ~ConditionVar ()
    {
        ::CloseHandle ( semaphore ) ;       
    }


public :
    template <class P>
    void Wait ( P pred )
    {
        while ( !pred() ) Wait();
    }

public :

    void Wait ( void )
    {
        INTERLOCKED_WRITE_RELEASE(&total_waiters,total_waiters + 1 );
        ::WaitForSingleObject ( semaphore , INFINITE );
    }

    //! it will notify one waiter
    void Notify ( void )
    {
        if ( INTERLOCKED_READ_ACQUIRE(&total_waiters) )
        {
            Wake (1);
        }
    }

    void NotifyAll (void )
    {
        if ( INTERLOCKED_READ_ACQUIRE(&total_waiters) )
        {
            std::cout << "notifying " << total_waiters ;
            Wake ( total_waiters );
        }
    }

protected :
    void Wake ( int count )
    {
        INTERLOCKED_WRITE_RELEASE(&total_waiters,total_waiters - count );
        ::ReleaseSemaphore ( semaphore , count , NULL );
    }

private :
    HANDLE semaphore;
    long    total_waiters;
};
4

4 に答える 4

2

インスタンスをコピーすると、両方のコピーで同じセンパホアが使用されるため、悪いことが起こると思います。これは必ずしも悪いことではありませんが、セマンティクスが完全に明確でない場合、人々を混乱させる可能性があります。

これは、 boost :: noncopyableが使用する(またはboostを使用する)のと同様のアプローチで簡単に修正できます。

于 2010-01-27T17:14:48.717 に答える
0

WinAPI 関数を使用している場合は、それぞれ and の代わりに and を使用することをおInterlockedIncrement(...)勧めInterlockedDecrement(...)INTERLOCKED_WRITE_RELEASE(&total_waiters,total_waiters + 1 );ますINTERLOCKED_WRITE_RELEASE(&total_waiters,total_waiters - count );

于 2010-01-27T17:03:00.823 に答える