Boost logo

Boost :

From: Adal Chiriliuc (adal_at_[hidden])
Date: 2004-03-22 06:37:59


Hello.

try_mutex uses a Mutex instead of a CRITICAL_SECTION because on
Windows 9x and Me it's impossible to try the aquisition of a
CRITICAL_SECTION.

On Windows NT/2000/XP this is possible, using the function
TryEnterCriticalSection.

So I suggest this: choose at runtime what syncronization primitive to
use based on the running OS. CRITICAL_SECTIONS are much faster and
since Windows NT is gradually replacing Windows 9x systems I think it
is good to use this feature.

A sketch follows.

---------- mutex.cpp -----------

namespace
{
bool g_Init = false;
bool g_UseTryCritical;
TryCriticalProcType g_TryCritical;

void TryCriticalInit()
{
    g_Init = true;
    g_UseTryCritical = false;
    get windows version;
    if (!windows nt)
       return;
    lib = load library (kernel32.dll);
    g_TryCritical = get proc address (lib, TryEnterCriticalSection);
    g_UseTryCritical = true;
}

}

try_mutex::try_mutex()
{
    if (!g_Init)
        TryCriticalInit();
    if (g_UseTryCritical)
    {
        try
        {
            m_mutex = reinterpret_cast<void*>(new CRITICAL_SECTION);
        }
        catch (...)
        {
        }
    }
    else
    {
        m_mutex = reinterpret_cast<void*>(CreateMutex(0, 0, 0));
    }
    if (!m_mutex)
        throw thread_resource_error();
    if (g_UseTryCritical)
        InitializeCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(m_mutex));
}

bool try_mutex::do_trylock()
{
    if (g_UseTryCritical)
    {
        return g_TryCritical(reinterpret_cast<LPCRITICAL_SECTION>(m_mutex)) != 0;
    }
    else
    {
        unsigned int res = 0;
        res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), 0);
        assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
        return res == WAIT_OBJECT_0;
    }
}

---------- mutex.cpp -----------

There is only one potential problem:
    if (!g_Init)
        TryCriticalInit();
might not be thread safe.

Something like a thread safe singleton might be needed.
Or maybe we could use InterlockedExchange & co.

I'm not sure if timed_mutex could also benefit from this.

In the docs you should explain what joining means. I worked a lot with
threads in the past, but I've never heard of such a concept. I had to
look through the source codes to understand what join means. Many
Win32 developers will not know of concepts not covered by the Platform
SDK. You do explain that conditions are some sort of events, but you
use joining in sample code without explaining what it does.

Regards,
Adal Chiriliuc


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk