Feb 10, 2011

Coding simplified with Guard Classes

With the introduction of exceptions, writing code has become increasingly complex. Any resource acquired has to be released when no longer in use. If not handled properly will lead to handle leaks, memory leaks and in some cases deadlocks which are very difficult to debug.
Guard classes takes advantage of the fact that the destructor is always called for an object on the stack regardless of how you exit from the function scope.

Key Idea

unsigned __stdcall func(void *args)
{
static Lock lock;
Guard guard(lock);
// operations
return 0;
}

#ifndef _Guard_H_
#define _Guard_H_

#include "Lock.h"

namespace examples
{
    class Guard
    {
    public:
        Guard(Lock &lock) : m_lock(lock)
        {
            m_lock.acquire();
        }

        ~Guard()
        {
            m_lock.release();
        }

    private:
        Guard();
        Guard(const Guard&);
        Guard& operator=(const Guard&);

        Lock &m_lock;
    };

}

#endif //_Guard_H_
The program demonstrates the use of Guard class to acquire() and release() the lock

The Complete Code
#include <windows.h>
#include <process.h>
#include <iostream>
#include <assert.h>
#include "Lock.h"
#include "Guard.h"

using namespace examples;

static bool alive = true;
static int current = 0;

unsigned __stdcall put(void *args)
{
    static Lock lock;
    while(alive)
    {
        Guard guard(lock);
        current = current + 10;
        ::Sleep(500);
        std::cout << current << std::endl;
    }
    return 0;
}

int main()
{
    // create threads
    unsigned t1;
    HANDLE h1 = (HANDLE) ::_beginthreadex(0, 0, &put, 0, CREATE_SUSPENDED, &t1);
    assert(h1 != 0);

    unsigned t2;
    HANDLE h2 = (HANDLE) ::_beginthreadex(0, 0, &put, 0, CREATE_SUSPENDED, &t2);
    assert(h2 != 0);

    // start threads
    ::ResumeThread(h1);
    ::ResumeThread(h2);

    ::Sleep(10000);
    alive = false;

    ::WaitForSingleObjectEx(h1, INFINITE, false);
    ::WaitForSingleObjectEx(h2, INFINITE, false);

    ::CloseHandle(h1);
    ::CloseHandle(h2);

    return 0;
}

References:
Exception Safe Code
Thinking in C++ Practical Programming

No comments :

Post a Comment