> Thread Synchronization Toolkit
 FrontPage|FindPage|TitleIndex|RecentChanges|UserPreferences U E D R S P I M H RSS

沥府/KernelObjects沥府/ThreadBasics沥府/ThreadPooling沥府/ThreadSchedulingAndPrioritiesAndAffinities沥府/ThreadSynchronizationInUserMode › 沥府/ThreadSynchronizationToolkit
<!> UnderConstruction

Contents:
1 Thread Synchronization Toolkit
2 Implementing a Critical Section: The Optex
3 Creating Thread-Safe Datatypes and Inverse Semaphores
4 The Single Writer/Multiple Reader Guard (SWMRG)
5 Implementing a WaitForMultipleExpressions Function


1 Thread Synchronization Toolkit #



2 Implementing a Critical Section: The Optex #



3 Creating Thread-Safe Datatypes and Inverse Semaphores #


struct SomeDataStruct
{
    ...
} g_SomeSharedData;

// Create a CResGuard object that protects g_SomeSharedData.
// Note: The constructor initializes the critical section and
//       the destructor deletes the critical section.
CResGuard g_rgSomeSharedData;

void AFunction()
{
    // This function touches the shared data.

    // Protect the resource from being accessed from multiple threads.
    CResGuard::CGuard gDummy( g_rgSomeSharedData );     //Enter critical section
    // Touch the g_SomeSharedData resource.
    ...

}   // Note: LeaveCriticalSection is called when gDummy goes out of scope.

CInterlockedScalar<BYTE> b = 5;     // A thread-safe BYTE
BYTE b2 = 10;                       // A non-thread-safe BYTE
b2 = b++;                           // b2=5, b=6
b *= 4;                             // b=24
b2 = b;                             // b2=24, b=24
b += b;                             // b=48
b %= 2;                             // b=0

CWhenZero<BYTE> b = 0;          // A thread-safe BYTE

// Returns immediately because b is 0
WaitForSingleObject( b, INFINITE );

b = 5;

// Returns only if another thread sets b to 0
WaitForSingleObject( b, INFINITE );

CWhenZero<BYTE> b = 5;          // A thread-safe BYTE

// Returns immediately because b is not 0
WaitForSingleObject( b.GetNotZeroHandle(), INFINITE );

b = 0;

// Returns only if another thread sets b to not 0
WaitForSingleObject( b.GetNotZeroHandle(), INFINITE );

IntLockTest.cpp

/******************************************************************************
Module:  IntLockTest.cpp
Notices: Copyright (c) 2000 Jeffrey Richter
******************************************************************************/


#include "..\CmnHdr.h"      /* See Appendix A. */
#include <tchar.h>
#include "Interlocked.h"


///////////////////////////////////////////////////////////////////////////////


// Set to TRUE when worker threads should terminate cleanly.
volatile BOOL g_fQuit = FALSE;


///////////////////////////////////////////////////////////////////////////////


DWORD WINAPI WorkerThread( PVOID pvParam )
{
    CWhenZero<BYTE>& bVal = * (CWhenZero<BYTE> *) pvParam;

    // Should worker thread terminate
    while( !g_fQuit )
    {
        // Wait for something to do
        WaitForSingleObject( bVal.GetNotZeroHandle(), INFINITE );

        // If we should quit, quit
        if( g_fQuit )
            continue;

        // Do something
        chMB( "Worker thread: We have something to do" );

        bVal--;         // We're done

        // Wait for all worker threads to stop
        WaitForSingleObject( bVal, INFINITE );
    }

    chMB( "Worker thread: terminating" );
    return ( 0 );
}


///////////////////////////////////////////////////////////////////////////////


int WINAPI _tWinMain( HINSTANCE hinstExe, HINSTANCE, PTSTR pszCmdLine, int )
{
    // Initialize to indicate that NO worker threads have anything to do
    CWhenZero<BYTE> bVal = 0;

    // Create the worker threads
    const int nMaxThreads = 2;
    HANDLE hThreads[ nMaxThreads ];
    for( int nThread = 0; nThread < nMaxThreads; nThread++ )
    {
        DWORD dwThreadId;
        hThreads[ nThread ] = CreateThread( NULL, 0,
            WorkerThread, (PVOID) &bVal, 0, &dwThreadId );
    }

    int n;
    do
    {
        // Do more work or stop running
        n = MessageBox( NULL,
            TEXT( "Yes: Give worker threads something to do\nNo: Quit" ),
            TEXT( "Primary thread" ), MB_YESNO );

        // Tell worker threads that we're quitting
        if( n == IDNO )
            InterlockedExchangePointer( (PVOID*) &g_fQuit, (PVOID) TRUE );

        bVal = nMaxThreads;     // Wake the worker threads

        if( n == IDYES )
        {
            // There is work to do, wait for the worker threads to finish
            WaitForSingleObject( bVal, INFINITE );
        }
    }
    while( n == IDYES );

    // There is no more work to do, the process wants to die.
    // Wait for the worker threads to terminate
    WaitForMultipleObjects( nMaxThreads, hThreads, TRUE, INFINITE );

    // Close the worker thread handles.
    for( nThread = 0; nThread < nMaxThreads; nThread++ )
        CloseHandle( hThreads[ nThread ] );

    // Tell the user that the process is dying
    chMB( "Primary thread: terminating" );

    return ( 0 );
}

//////////////////////////////// End of File //////////////////////////////////

Interlocked.h

/******************************************************************************
Module:  Interlocked.h
Notices: Copyright (c) 2000 Jeffrey Richter
******************************************************************************/


#pragma once

///////////////////////////////////////////////////////////////////////////////

// Instances of this class will be accessed by multiple threads. So,
// all members of this class (except the constructor and destructor)
// must be thread-safe.

class CResGuard
{
public:
    CResGuard()  { m_lGrdCnt = 0; InitializeCriticalSection( &m_cs ); }
    ~CResGuard() { DeleteCriticalSection( &m_cs ); }

    // IsGuarded is used for debugging
    BOOL IsGuarded() const { return ( m_lGrdCnt > 0 ); }

public:
    class CGuard
    {
    public:
        CGuard( CResGuard& rg ) : m_rg( rg ) { m_rg.Guard(); };
        ~CGuard() { m_rg.Unguard(); }

    private:
        CResGuard& m_rg;
    };

private:
    void Guard()   { EnterCriticalSection( &m_cs ); m_lGrdCnt++; }
    void Unguard() { m_lGrdCnt--; LeaveCriticalSection( &m_cs ); }

    // Guard/Unguard can only be accessed by the nested CGuard class.
    friend class CResGuard::CGuard;

private:
    CRITICAL_SECTION m_cs;
    long m_lGrdCnt;     // # of EnterCriticalSection calls
};


///////////////////////////////////////////////////////////////////////////////


// Instances of this class will be accessed by multiple threads. So,
// all members of this class (except the constructor and destructor)
// must be thread-safe.

template <class TYPE>
class CInterlockedType
{
public:     // Public member functions
    // Note: Constructors & destructors are always thread-safe
    CInterlockedType() {}
    CInterlockedType( const TYPE& TVal ) { m_TVal = TVal; }
    virtual ~CInterlockedType() {}

    // Cast operator to make writing code that uses
    // thread-safe data type easier
    operator TYPE() const
    {
        CResGuard::CGuard x( m_rg );
        return ( GetVal() );
    }

protected:  // Protected function to be called by derived class
    TYPE& GetVal()
    {
        chASSERT( m_rg.IsGuarded() );
        return ( m_TVal );
    }

    const TYPE& GetVal() const {
        assert( m_rg.IsGuarded() );
        return ( m_TVal );
    }

    TYPE SetVal( const TYPE& TNewVal )
    {
        chASSERT( m_rg.IsGuarded() );
        TYPE& TVal = GetVal();
        if( TVal != TNewVal ) {
            TYPE TPrevVal = TVal;
            TVal = TNewVal;
            OnValChanged( TNewVal, TPrevVal );
        }
        return ( TVal );
    }

protected:  // Overridable functions
    virtual void OnValChanged( const TYPE& TNewVal, const TYPE& TPrevVal ) const
    {
        // Nothing to do here
    }

protected:
    // Protected guard for use by derived class functions
        mutable CResGuard m_rg;

private:    // Private data members
    TYPE m_TVal;
};


///////////////////////////////////////////////////////////////////////////////


// Instances of this class will be accessed by multiple threads. So,
// all members of this class (except the constructor and destructor)
// must be thread-safe.

template <class TYPE>
class CInterlockedScalar : protected CInterlockedType<TYPE>
{
public:
    CInterlockedScalar( TYPE TVal = 0 ) : CInterlockedType<TYPE>( TVal ) {}

    ~CInterlockedScalar() { /* Nothing to do */ }

    // C++ does not allow operator cast to be inherited.
    operator TYPE() const
    {
        return ( CInterlockedType<TYPE>::operator TYPE() );
    }

    TYPE operator=( TYPE TVal )
    {
        CResGuard::CGuard x( m_rg );
        return ( SetVal( TVal ) );
    }

    TYPE operator++(int)        // Postfix increment operator
    {
        CResGuard::CGuard x( m_rg );
        TYPE TPrevVal = GetVal();
        SetVal( (TYPE) (TPrevVal + 1) );
        return ( TPrevVal );    // Return value BEFORE increment
    }

    TYPE operator--(int) {      // Postfix decrement operator.
        CResGuard::CGuard x( m_rg );
        TYPE TPrevVal = GetVal();
        SetVal( (TYPE) (TPrevVal - 1) );
        return ( TPrevVal );    // Return value BEFORE decrement
    }

    TYPE operator += ( TYPE op )
        { CResGuard::CGuard x( m_rg ); return( SetVal( GetVal() +  op ) ); }
    TYPE operator++()
        { CResGuard::CGuard x( m_rg ); return( SetVal( GetVal() +   1 ) ); }
    TYPE operator -= ( TYPE op )
        { CResGuard::CGuard x( m_rg ); return( SetVal( GetVal() -  op ) ); }
    TYPE operator--()
        { CResGuard::CGuard x( m_rg ); return( SetVal( GetVal() -   1 ) ); }
    TYPE operator *= ( TYPE op )
        { CResGuard::CGuard x( m_rg ); return( SetVal( GetVal() *  op ) ); }
    TYPE operator /= ( TYPE op )
        { CResGuard::CGuard x( m_rg ); return( SetVal( GetVal() /  op ) ); }
    TYPE operator %= ( TYPE op )
        { CResGuard::CGuard x( m_rg ); return( SetVal( GetVal() %  op ) ); }
    TYPE operator ^= ( TYPE op )
        { CResGuard::CGuard x( m_rg ); return( SetVal( GetVal() ^  op ) ); }
    TYPE operator &= ( TYPE op )
        { CResGuard::CGuard x( m_rg ); return( SetVal( GetVal() &  op ) ); }
    TYPE operator |= ( TYPE op )
        { CResGuard::CGuard x( m_rg ); return( SetVal( GetVal() |  op ) ); }
    TYPE operator <<=( TYPE op )
        { CResGuard::CGuard x( m_rg ); return( SetVal( GetVal() << op ) ); }
    TYPE operator >>=( TYPE op )
        { CResGuard::CGuard x( m_rg ); return( SetVal( GetVal() >> op ) ); }
};


///////////////////////////////////////////////////////////////////////////////


// Instances of this class will be accessed by multiple threads. So,
// all members of this class (except the constructor and destructor)
// must be thread-safe.

template <class TYPE>
class CWhenZero : public CInterlockedScalar<TYPE>
{
public:
    CWhenZero( TYPE TVal = 0, BOOL fManualReset = TRUE )
        : CInterlockedScalar<TYPE>( TVal )
    {
        // The event should be signaled if TVal is 0
        m_hevtZero    = CreateEvent( NULL, fManualReset, (TVal == 0), NULL );

        // The event should be signaled if TVal is NOT 0
        m_hevtNotZero = CreateEvent( NULL, fManualReset, (TVal != 0), NULL );
    }

    ~CWhenZero() {
        CloseHandle( m_hevtZero );
        CloseHandle( m_hevtNotZero );
    }

    // C++ does not allow operator= to be inherited.
    TYPE operator=( TYPE x )
    {
        return ( CInterlockedScalar<TYPE>::operator=( x ) );
    }

    // Return handle to event signaled when value is zero
    operator HANDLE() const { return ( m_hevtZero ); }

    // Return handle to event signaled when value is not zero
    HANDLE GetNotZeroHandle() const { return ( m_hevtNotZero ); }

    // C++ does not allow operator cast to be inherited.
    operator TYPE() const
    {
        return ( CInterlockedScalar<TYPE>::operator TYPE() );
    }

protected:
    void OnValChanged( const TYPE& TNewVal, const TYPE& TPrevVal ) const
    {
        // For best performance, avoid jumping to
        // kernel mode if we don't have to
        if( (TNewVal == 0) && (TPrevVal != 0) )
        {
            SetEvent( m_hevtZero );
            ResetEvent( m_hevtNotZero );
        }
        if( (TNewVal != 0) && (TPrevVal == 0) )
        {
            ResetEvent( m_hevtZero );
            SetEvent( m_hevtNotZero );
        }
    }

private:
    HANDLE m_hevtZero;      // Signaled when data value is 0
    HANDLE m_hevtNotZero;   // Signaled when data value is not 0
};


//////////////////////////////// End of File //////////////////////////////////

InterlockedType.rc

// Microsoft Developer Studio generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32

/////////////////////////////////////////////////////////////////////////////
//
// Icon
//

// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_INTERLOCKEDTYPE     ICON    DISCARDABLE     "InterLockedType.ICO"

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE DISCARDABLE
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE DISCARDABLE
BEGIN
    "#include ""afxres.h""\r\n"
    "\0"
END

3 TEXTINCLUDE DISCARDABLE
BEGIN
    "\r\n"
    "\0"
END

#endif  // APSTUDIO_INVOKED

#endif  // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif  // not APSTUDIO_INVOKED

4 The Single Writer/Multiple Reader Guard (SWMRG) #



5 Implementing a WaitForMultipleExpressions Function #




CategoryTranslation

EditText|FindPage|DeletePage|LikePages| Valid XHTML 1.0! Valid CSS! powered by MoniWiki