Click here to Skip to main content
15,886,199 members
Articles / Programming Languages / C++

A heap or shared memory based mutex pool manager

Rate me:
Please Sign up or sign in to vote.
3.41/5 (14 votes)
24 Sep 2006CPOL3 min read 35.4K   482   19  
An article on a mutex pool manager based on heap or shared memory.
// testsharemutex.cpp : Defines the entry point for the console application.
//
#include "common.h"
#include "MutexManager.h"
#include "Mutex.h"

#define PAGE_NUMBER   100
#define VALUE_NUMBER  10
#define THREAD_NUMBER  3

typedef struct
{
    DWORD dwMutexIndex;
    DWORD arrayValue[VALUE_NUMBER];
} Page;

typedef struct 
{
    DWORD dwPageNumber;
    Page  arrayPage[1];
} Buffer;

typedef struct 
{
    Buffer *pBuffer;
    STK::CMutexManager *pMutexManager;
    DWORD dwMutexIndex;
} ThreadData;

bool PrintPage(bool bNormal, Page *pPage, DWORD dwPageNumber, 
               STK::CMutexManager *pMutexManager, DWORD dwMutexIndex)
{
    //Valide the parameters
    if ((pPage == NULL)         ||
        (pMutexManager == NULL) ||
        (dwMutexIndex == INVALID_MUTEX_ID))
    {
        return false;
    }

    //Synchronize the printing
    STK::CMutex objMutex(pMutexManager, dwMutexIndex);
    objMutex.Lock(); 

    //Print the page number
    std::cout<<"-----------------------------------------------------------------"<<std::endl;
    if (bNormal)
    {
        std::cout<< "Normal page:"<< dwPageNumber;
    }
    else
    {
        std::cout<< "Abnormal page:"<< dwPageNumber;
    }

    //Print teh process and thread IDs
    std::cout<< " Process ID:"<< GetCurrentProcessId();
    std::cout<< " Thread ID:"<< GetCurrentThreadId()<<std::endl;

    //Print the values
    std::cout<<" value: ";
    for (DWORD dwValueIndex = 0; dwValueIndex < VALUE_NUMBER; dwValueIndex++)
    {
        std::cout<< pPage->arrayValue[dwValueIndex] <<" ";  
    }
    std::cout<<std::endl;
    std::cout<<"-----------------------------------------------------------------"<<std::endl<<std::endl;
    //Unlock the printing
    objMutex.Unlock(); 

    return true;
}

DWORD WINAPI ReadWritePages(LPVOID lpParam ) 
{ 
    //Check if the parameter is NULL
    if (lpParam == NULL)
    {
        return 1;
    }

    ThreadData* pData = (ThreadData*)lpParam;
    //Get the buffer
    Buffer* pBuffer = pData->pBuffer; 
    //Get the mutex manager
    STK::CMutexManager* pMutexManager = pData->pMutexManager;
    //Get the mutex for printing
    DWORD dwMutexIndex = pData->dwMutexIndex;

    //Check if the buffer or mutex manager is NULL
    if ((pBuffer == NULL) ||
        (pMutexManager == NULL))
    {
        return 1;
    }

    //The return value
    int iRet = 0;
    //Sets a random starting point.
    srand(GetTickCount());
    //Access the page randomly
    for (DWORD dwIndex = 0; dwIndex < pBuffer->dwPageNumber * 1000; dwIndex++)
    {
        //Get the random number
        DWORD dwRand = rand();
        //Get the page number
        DWORD dwPageNumber = dwRand % pBuffer->dwPageNumber;
        //Get the page pointer
        Page *pPage = pBuffer->arrayPage + dwPageNumber;
        //Lock the page
        STK::CMutex objMutex (pMutexManager, pPage->dwMutexIndex);
        if (!objMutex.Lock())
        {
            iRet = 1;
            break;
        }

        //Lock the page again
        if (!objMutex.Lock())
        {
            iRet = 1;
            break;
        }

        //Check the data integrity
        bool bNormal = true;
        for (DWORD dwValueIndex = 0; dwValueIndex < VALUE_NUMBER; dwValueIndex++)
        {
            if ((dwValueIndex < (VALUE_NUMBER - 1)) &&
                (pPage->arrayValue[dwValueIndex] != pPage->arrayValue[dwValueIndex+1]))
            {
                bNormal = false;
                break;
            }
        }
        //Print out the page values
        PrintPage (bNormal, pPage, dwPageNumber, pMutexManager, dwMutexIndex);

        //Modify the page value
        for (dwValueIndex = 0; dwValueIndex < VALUE_NUMBER; dwValueIndex++)
        {
            SwitchToThread();
            pPage->arrayValue[dwValueIndex] = dwRand;
        }

        //Unlock the page
        if (!objMutex.Unlock())
        {
            iRet = 1;
            break;
        }

        //Unlock the page again
        if (!objMutex.Unlock())
        {
            iRet = 1;
            break;
        }
    }

    return iRet;
}

int main(int argc, char* argv[])
{
    //Create the mutex for the application
    STK::CSysMutex objSysMutex(false, L"TestSharedMutex.Applicaiton", NULL);
    //Synchronize the instances of the applicaiton
    if (!objSysMutex.Lock (INFINITE))
    {
        return 1;
    }
    //Create the shared memory for the buffer
    DWORD dwSize = sizeof (Buffer) + PAGE_NUMBER * sizeof (Page);
    STK::CSysMemory objSysMemory (dwSize, L"TestSharedMutex.Buffer");
    //Get the buffer
    Buffer *pBuffer;
    if (!objSysMemory.GetMemory ((void**)&pBuffer))
    {
        objSysMutex.Unlock(); 
        return 1;
    }

    //Create the named mutex manager, the initial and incremental mutex counts are 10
    STK::CMutexManager objMutexManager (10, 10, L"TestSharedMutex");
    
    //If it's not opened shared memory, initialize it
    if (objSysMemory.GetMemoryType() != STK::eMemoryShareOpen)
    {
        //Set the page number
        pBuffer->dwPageNumber = PAGE_NUMBER;
        //For each page, create the mutex 
        for (DWORD dwPageIndex = 0; dwPageIndex < pBuffer->dwPageNumber; dwPageIndex++)
        {
            DWORD dwMutexIndex = INVALID_MUTEX_ID;
            //Create the mutex
            if (!objMutexManager.CreateMutex (dwMutexIndex))
            {
                objSysMutex.Unlock(); 
                return 1;
            }
            //Get the page
            Page* pPage = pBuffer->arrayPage + dwPageIndex;
            //Set the mutex index to the page
            pPage->dwMutexIndex = dwMutexIndex;
        }
    }
    else
    {
        //For each page, open the mutex
        for (DWORD dwPageIndex = 0; dwPageIndex < pBuffer->dwPageNumber; dwPageIndex++)
        {
            //Get the page
            Page* pPage = pBuffer->arrayPage + dwPageIndex;
            //Open the mutex
            if (!objMutexManager.OpenMutex (pPage->dwMutexIndex))
            {
                objSysMutex.Unlock(); 
                return 1;
            }
        }
    }
    //Unlock the applicaiton mutex
    objSysMutex.Unlock(); 

    //Create the mutex to synchronize the printing 
    DWORD dwMutexIndex = INVALID_MUTEX_ID;
    if (!objMutexManager.CreateMutex (dwMutexIndex))
    {
        return 1;
    }

    //Construct the paramater for the worker threads
    ThreadData tData;
    tData.pBuffer = pBuffer;
    tData.pMutexManager = &objMutexManager;
    tData.dwMutexIndex = dwMutexIndex;

    //Create the worker threads
    DWORD dwThreadId[THREAD_NUMBER];
    HANDLE hThread[THREAD_NUMBER]; 
    for( DWORD dwIndex = 0; dwIndex < THREAD_NUMBER; dwIndex++)
    {
        hThread[dwIndex] = CreateThread(NULL, 0, ReadWritePages, &tData, 0, 
                                        &dwThreadId[dwIndex]);
    }

    //Wait until all threads have terminated.
    WaitForMultipleObjects(THREAD_NUMBER, hThread, TRUE, INFINITE);

    // Close all thread handles
    for(dwIndex = 0; dwIndex< THREAD_NUMBER; dwIndex++)
    {
        CloseHandle(hThread[dwIndex]);
    }

    //Release the mutex for the printing synchronization
    int iRet = 0;
    if (!objMutexManager.CloseMutex (dwMutexIndex))
    {
        iRet = 1;
    }

    //For each page, Release the mutex
    for (DWORD dwPageIndex = 0; dwPageIndex < pBuffer->dwPageNumber; dwPageIndex++)
    {
        Page* pPage = pBuffer->arrayPage + dwPageIndex;
        if (!objMutexManager.CloseMutex (pPage->dwMutexIndex))
        {
            iRet = 1;
        }
    }

    return iRet;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
Email: fxu_36@hotmail.com

Comments and Discussions