A Developer's Diary

Showing posts with label Windows. Show all posts
Showing posts with label Windows. Show all posts

Mar 23, 2012

Configuring CMIS Consumer in Sharepoint 2010 server

In our previous post, we have configured SharePoint 2010 Server with CMIS Connector Services Producer. This post talks about adding and configuring CMIS Connector Services Consumer Web Part to a Web Page. We will also be testing the CMIS Consumer service by listing down all the documents uploaded to a particular sharepoint document repository.

Read more ...

Configuring CMIS in Sharepoint 2010 server

Content Management Interoperability Services a.k.a CMIS is a standard defined for Enterprise Content Management (ECM) systems such as SharePoint server, Documentum, Alfresco and others. The standard defines a domain model plus Web Services and Restful AtomPub bindings that can be used by other applications.

Installing the SharePoint CMIS Connector
1. Install Microsoft SharePoint Server 2010

2. Complete the SharePoint 2010 Products configuration wizard
3. Download Microsoft SharePoint 2010 Administration Toolkit from here and save the file to hard disk
SharePoint 2010 Administration Toolkit installs two components:
CMIS Producer Services
This allows CMIS client applications to interact with the SharePoint document libraries by using interfaces defined in the CMIS standard

CMIS Consumer Services Web Part
The Consumer Web part can be added to any SharePoint page and allows users to connect with any CMIS compliant repository
4. Double click SharePoint2010AdministrationToolkit.exe file to start the installation.
5. Accept the license agreement and click next. Make sure CMIS connectors are selected for the install. Click Next
6. Use the default installation directory. Click Next and Finish. CMIS Connector is successfully installed


Read more ...

Mar 16, 2012

Installing And Configuring SSH server on Windows

We will be making use of Cygwin utilities to configure and run ssh as service on windows machine. Installing Cygwin on a windows machine is pretty straight forward. Download the latest Cygwin installation setup.exe from the Cygwin site and follow the below instructions.

1. Installing Cygwin
Step 1. Double click setup.exe


Step 2. Choose the download source

Step 3. Select the root directory of the Cygwin. This directory is synonymous to / in linux

Step 4. Select the directory where you want to keep the installation files. You can save this directory and use at a later point to install Cygwin on any windows machine using this directory.

Click 'OK' if prompted to create the directory if it does not exists

Step 5. Select the type of connection you are using to connect to internet.

Step 6. Choose a download site.

Step 7. Clicking next opens up the 'Select Packages' screen.

Step 8. Select the Open SSH server and client programs from the 'Select Packages' screen.

Step 9. Click next to start the installation.

This will install the following utilities in your Cygwin's /usr/bin directory
ssh-add.exe
ssh-agent.exe
ssh-host-config
ssh-keygen.exe
ssh-keyscan.exe
ssh-user-config
ssh.exe

2. Configuring ssh as Windows service

Run ssh-host-config utility to configure sshd server on windows. Select 'no' when prompted for 'Should privilege separation be used? (yes/no)'. Select 'yes' when prompted for 'Do you want to install sshd as service?'. Choose default options for other options.
The above will install CYGWIN sshd service on Windows. To start the service execute
net start sshd

3. Connecting using Cygwin ssh client (ssh.exe)
ssh.exe user@ssh-server

4. Connecting through putty

Add the server's host key to registry. This will add an entry into the ~/.ssh/known_hosts file

Login using windows user and password

Read more ...

Mar 20, 2011

Command prompt and setting environment variable properties

Working on multiple projects which require different compiler versions can be a daunting task especially if you are using windows command prompt cmd.exe to build the projects. You need to export the compiler specific environment variables and set the PATH variable appropriately each time you launch the command window to build each project. Here is a small tip that can help save some time

Tip
Write a batch file which will set the necessary environment variables and the path variable before launching the command window
A simple batch script which sets JAVA_HOME to jdk1.6.0_21 and launches the command prompt window
set JAVA_HOME=
set JAVA_HOME=c:\Program Files\Java\jdk1.6.0_21

set PATH=%JAVA_HOME%\bin;%PATH%
start cmd /k

On executing the batch file, command prompt window is launched with the JAVA_HOME environment variable set to the desired version (jdk1.6.0_21)

Read more ...

Mar 4, 2011

Makefile tutorial for beginners

The purpose of the make utility is to determine automatically which pieces of your large program needs to be re-compiled, and issue the commands to recompile them. The make program uses the makefile instructions and the last modified time of the files to decide which of the files needs to be updated.
A makefile tells make what to do. The make utility executes commands in the makefile to update one or more targets. If -f option is not provided, make looks for the makefiles GNUmakefile, makefile, and Makefile, in that order.

Key Points
1. Make is a software engineering tool which helps simplifies the process of software development
2. Makefiles can be used to automate the build process (Generation of binary from source files)
3. The programmer does not need to type the complex compiler commands and flags to be used during compilation

1. Variables
1. A variable in a makefile can be a recursively expanded variable NAME = value or a simply expanded variable NAME := value
2. The variable's value can be accessed using $(NAME) or ${NAME}
3. As a convention, the variable names are always written in uppercase.
4. Variable names are case-sensitive and should not contain other than letters, numbers and underscores as they may have a special meaning
5. Setting a variable if not already set use ?= e.g. NAME ?= value

Note: You cannot append a value at the end of the recursively expanded variable using CC = $(CC) -O2. This will end up in an infinite loop as make will continue expanding this variable until it cannot be expanded anymore. To overcome this problem, we use simply expanded variables to append values at the end as shown

CC := g++ -o
CC += $(CC) -O2

2. Explicit Rules
Explicit rules tell make which files depend on the compilation of other files and the commands required to compile those files. They take the following form:

targetfile : dependentfiles
[TAB]commands
...
[TAB]commands 

3. Implicit Rules or Suffix Rules
Implicit rules are similar to explicit rules except that they are listed without commands. The make utility makes uses of the file suffixes to determine what commands to execute on the source files

hello.o : hello.c
Running make will cause the following command to be executed cc -c -o hello.o hello.c

Common variables used by implicit rules:

AR  : archive program, default ar
CC  : compiling c program, default cc
CXX : compiling c++ program, default g++
CPP : c preprocessor, default $(CC) -E
RM  : remove, default rm -f

Flags used by the programs above

ARFLAGS  : flags for the archive program, default rv
CFLAGS   : flags for the c compiler
CXXFLAGS : flags for the c++ compiler
CPPFLAGS : flags for the c preprocessor
LDFLAGS  : flags for the linker

Some of the old fashioned suffix rules for C and C++ are:

Compiling C Programs
file.o is automatically built from file.c. $(CC) -c $(CPPFLAGS) $(CFLAGS)

Compiling C++ Programs
file.o is automatically built from file.cc. $(CXX) -c $(CPPFLAGS) $(CXXFLAGS)

Linking Object Files
file is automatically generated from file.o by running the linker (ld). $(CC) $(LDFLAGS) file.o $(LOADLIBS) $(LDLIBS)

The default suffix list for common C and C++ programs include .out, .a, .o, .c, .cc, .C, .def, .h. The complete list can be found out here

The above catalogue of implicit rules are always available unless makefile explicitely overrides them. Running make with -r or --no-builtin-rules option cancels all predefined rules

Implicit rules can also be disabled by disabling default suffixes and having only the suffixes you need

.SUFFIXES:    # Delete the default suffixes
.SUFFIXES: .c .cpp .o .h       # Define our suffix list

Inference Rules: Inference rules are rules distinguished by the use of the character “%” in the dependency line. The “%” (rule character) is a wild card, matching zero or more characters. As an example, here is an inference rule for building .obj files from .c files:
%.obj : %.c
        $(CC) $(CFLAGS) –c $(.SOURCE) 

4. Phony Targets
A phony target is one that is not really the name of the target file. It is a request for executing a set of commands that should not create the target file name. As the target file will never exist, the commands will be executed always e.g.

clean:
        rm *.o temp

You can also explicitely declare a target as phony using the special target .PHONY

.PHONY = clean

5. Comments
A comment starts with # character in a makefile

6. Substitution References
A substitution reference has the form $(file:.c=.o). The below example sets OBJFILES to a.o b.o c.o

SRCFILES = a.c b.c c.c
OBJFILES = $(SRCFILES:.c=.o)
SRCFILES = a.c b.c c.c
OBJFILES = $(SRCFILES:%.c=%.o)

Read more ...

Mar 2, 2011

Producer and Consumer Problem revisited with Events

The producer and consumer problem we visited earlier used CRITICAL_SECTION for synchronization and the threads were spinning and checking over the queue size to add or remove the elements. In this post, we are going to use Windows Event objects for synchronizing the Producer and Consumer threads.

Key Points
1. Events are kernel objects which contain an usage count, flag indicating the type of event (manual-reset or auto-reset) and another flag indicating the state (signaled or non-signaled)
2. Applications use Event Objects to notify the waiting threads that an operation has been completed
3. An event is signaled using the call
SetEvent(Handle hEvent)

4. When a manual-reset event is signaled, all threads waiting on the event become schedulable. When an auto-reset event is signaled, only one of the threads waiting on the event becomes schedulable

Event uses five functions CreateEvent, OpenEvent, SetEvent, ResetEvent, and PulseEvent. The functions I will be using in my examples are:

HANDLE CreateEvent(
  LPSECURITY_ATTRIBUTES lpEventAttributes,
  BOOL bManualReset,
  BOOL bInitialState,
  LPCTSTR lpName
);
BOOL SetEvent(
  HANDLE hEvent
);
BOOL ResetEvent(
  HANDLE hEvent
);

The Event class below is a wrapper over windows manual-reset Event Object, provides easy interface to use and also takes care of the cleanup activities for the event handles.
#ifndef _Event_H_
#define _Event_H_

//File: Event.h

#include <windows.h>
#include <process.h>
#include <iostream>

namespace examples
{
    class Event : public NonCopyable
    {
    public:
        Event()
        {
            m_evt = (HANDLE) ::CreateEvent(0, true, false, 0);
            if(NULL == m_evt)
            {
                std::cout <<  "ERROR: Cannot create event" << std::endl;
            }
        }

        ~Event()
        {
            ::CloseHandle(m_evt);
        }

        bool wait(size_t timeout)
        {
            bool retval = false;

            switch(::WaitForSingleObjectEx(m_evt, timeout == 0 ? INFINITE : timeout, false))
            {
            case WAIT_OBJECT_0:
                retval = true;
                break;
            default:
                std::cout << "ERROR: Wait Failed " << ::GetLastError() << std::endl;
                break;
            }
            ::ResetEvent(m_evt);

            return retval;
        }

        bool signal()
        {
            return ::SetEvent(m_evt);
        }

    private:
        HANDLE m_evt;
    };
}

#endif //_Event_H_
The Shared Message Queue Class
#ifndef _MQ_H_
#define _MQ_H_

//File: MQ.h

#include <iostream>
#include <deque>
#include "Lock.h"
#include "Event.h"

using namespace std;

namespace examples
{
    class MQ
    {
    public:
        MQ(size_t size = 10) : m_max_size(size){}

        ~MQ()
        {
            m_q.clear();
        }

        void add(const string& elem)
        {
            m_qlock.acquire();
            while(isFull())
            {
                m_qlock.release();
                m_evtProducer.wait(0);
                m_qlock.acquire();
            }
            m_q.push_back(elem);
            debug_print("Producer");
            m_evtConsumer.signal();
            m_qlock.release();
        }

        void remove()
        {
            m_qlock.acquire();
            while(isEmpty())
            {
                m_qlock.release();
                m_evtConsumer.wait(0);
                m_qlock.acquire();
            }
            m_q.pop_front();
            debug_print("Consumer");
            m_evtProducer.signal();
            m_qlock.release();
        }

        bool isEmpty() const
        {
            return m_q.size() == 0;
        }

        bool isFull() const
        {
            return m_q.size() >= m_max_size - 1;
        }

    private:

        void debug_print(const std::string& str) const
        {
            std::cout << str.c_str() << "  [" << ::GetCurrentThreadId() << "] Size=[" << m_q.size() << "]";
            std::cout << endl;
        }

        const size_t   m_max_size;
        deque<const string>   m_q;
        Lock           m_qlock;
        Event          m_evtProducer;
        Event          m_evtConsumer;
    };

}

#endif //_MQ_H_

Read more ...

Feb 24, 2011

Orphan Users in SQL Server 2005

All Sql Server logins are stored in a system base table in master database. Whenever a new user is created, a corresponding entry is added in the system base table. There is a associated login entry for every user in system base table which also stores an associated SID (security identifier).

Key Idea

1. An orphan user is one which does not have an associated login entry in the System Base Tables (syslogins for sql server 2000 and sys.server_principals for sql server 2005+)
2. A user is also rendered orphan if the security identifier of the user does not match with the one stored in the system base tables in the master database

Orphaned users are generally created when you do either of the following:
1. Restore a database backup from one server to another
2. Restore an old copy of master database
3. Accidently remove a login belonging to a user

Reporting Orphaned Users
To see all the orphaned users in the database, execute the following query

EXEC sp_change_users_login 'report'

The orphan users if present will be shown as:

OrphanUser1 0x296D8B7BC71BA7459884FE8C17BFC32B
OrphanUser2 0x5F8AD799262298479F6F15FB07E9B0C6

Fixing Orphaned Users
To fix these orphaned users we have to relink the security identifier of the users with the security identifiers of the logins in the system base table. The below query helps fix and reset the password for the orphaned users

EXEC sp_change_users_login 'auto_fix', 'OrphanUser1', null, 'OrphanUser1'
EXEC sp_change_users_login 'auto_fix', 'OrphanUser2', null, 'OrphanUser2'

The above queries will add the login entries if not already present with the given password. In case the login entries are already present, you can use the shorter version of the above queries to fix the problem

EXEC sp_change_users_login 'auto_fix', 'OrphanUser1'
EXEC sp_change_users_login 'auto_fix', 'OrphanUser2'


Note: You may observe the following error: An invalid parameter or option was specified for procedure 'sys.sp_change_users_login' if you are using 'Auto_Fix' as the action instead of 'auto_fix'

References:
Troubleshooting Orphaned Users
MSDN: System Base Tables
Fixing Orphaned Users

Read more ...

Feb 16, 2011

Thread Synchronization using Windows Mutex

In my earlier post Thread Synchronization in Windows using Critical Section, I have used Windows Critical Section as Locks for synchronizing the threads. This post talks about using Windows Mutex as synchronization objects and demonstrates it's use with a simple example. Windows functions related with Mutexes are CreateMutex, ReleaseMutex and OpenMutex

HANDLE CreateMutex(
  LPSECURITY_ATTRIBUTES lpMutexAttributes,
  BOOL bInitialOwner,
  LPCTSTR lpName
);
BOOL ReleaseMutex(
  HANDLE hMutex
);
HANDLE WINAPI OpenMutex(
  DWORD dwDesiredAccess,
  BOOL bInheritHandle,
  LPCTSTR lpName
);

Key Points

1. A thread acquires a mutex by calling WaitForSingleObject(HANDLE hMutex, DWORD dwMilliseconds);
2. A thread releases mutes by calling ReleaseMutex(HANDLE hMutex);
3. The WaitForSingleObject call returns when the specified object is in the signaled state or when the time out interval has lapsed

The MutexLock class implementation using Windows Mutex synchronization Object
#ifndef _MutexLock_H_
#define _MutexLock_H_

//File: MutexLock.h

#include <windows.h>
#include <process.h>
#include <iostream>
#include "NonCopyable.h"

namespace examples
{
    class MutexLock : public NonCopyable
    {
    public:
        MutexLock()
        {
            m_hMutex = (HANDLE) ::CreateMutex(0, 0, 0);
            if(NULL == m_hMutex)
            {
                std::cout << "ERROR: Cannot create mutex" << std::endl;
            }
        }

        ~MutexLock()
        {
            ::CloseHandle(m_hMutex);
        }

        void acquire()
        {
            if(::WaitForSingleObject(m_hMutex, INFINITE) != WAIT_OBJECT_0)
            {
                std::cout << "ERROR: Cannot acquire mutex" << std::endl;
            }
        }

        bool tryAcquire(size_t timeOut)
        {
            bool retval = false;
            switch(::WaitForSingleObject(m_hMutex, timeOut))
            {
            case WAIT_OBJECT_0:
                retval = true;
                break;
            case WAIT_TIMEOUT:
                std::cout << "ERROR: Cannot acquire mutex" << std::endl;
                break;
            default:
                std::cout << "ERROR: Cannot acquire mutex" << std::endl;
                break;
            }

            return retval;
        }

        void release()
        {
            if(::ReleaseMutex(m_hMutex) == 0)
            {
                std::cout << "ERROR: Cannot release mutex" << std::endl;
            }
        }

    private:
        HANDLE m_hMutex;
    };

}

#endif //_MutexLock_H_

Read more ...

Feb 14, 2011

Producer and Consumer Problem using Windows Threads

Above is class diagram for a simple producer/consumer problem
#include <iostream>
#include "MQ.h"
#include "Thread.h"
#include "Runnable.h"
#include "ProductionTask.h"
#include "ConsumptionTask.h"

//File: Main.cpp

using namespace examples;

int main()
{
    try
    {
        MQ q(10);
        ProductionTask producerTask(q);
        ConsumptionTask consumerTask(q);
        Thread t[2] = { producerTask, consumerTask };

        //start the producer and consumer threads
        t[0].start();
        t[1].start();

        //wait 50000 ms before terminating the threads
        t[0].join(50000);
        t[1].join(50000);
        std::cout << std::endl
            << "Threads timed out!!" << std::endl;

    }catch(std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }catch(...)
    {
        std::cerr << "Unknown Exception" << std::endl;
    }
    return 0;
}
Key Features

1. Threads are Tasks are decoupled. A thread can execute any task provided it implements the Runnable interface.
2. Windows threads are encapsulated using the technique demonstrated in the earlier blog post Encapsulating Windows Threads in C++ Objects
3. Two Tasks ProductionTask and ConsumptionTask share the common MQ instance q and try to execute add and remove operations on q concurrently. Synchronization is achieved here by means of Lock implemented using Windows CRITICAL_SECTION
4. The threads are allowed to run for 50 seconds before they are terminated. This is not a graceful termination and in real world applications may lead to unexpected results
#ifndef _Runnable_H_
#define _Runnable_H_

//File: Runnable.h

#include <iostream>
#include "NonCopyable.h"

namespace examples
{
    class Runnable
    {
    public:
        virtual ~Runnable(){}
        virtual void run() = 0;
    };

}

#endif //_Runnable_H_
#ifndef _ConsumptionTask_H_
#define _ConsumptionTask_H_

//File: ConsumptionTask.h

#include "Runnable.h"
#include "MQ.h"

namespace examples
{
    class ConsumptionTask : public Runnable
    {
    public:
        ConsumptionTask(MQ &q);
        ~ConsumptionTask();
        virtual void run();

    private:
        MQ&  m_queue;
    };

}

#endif //_ConsumptionTask_H_
#include "ConsumptionTask.h"

//File: ConsumptionTask.cpp

using namespace examples;

ConsumptionTask::ConsumptionTask(MQ &q) : m_queue(q)
{}

ConsumptionTask::~ConsumptionTask()
{}

void ConsumptionTask::run()
{
    while(true)
    {
        m_queue.remove();
        ::Sleep(550);
    }
}
#ifndef _ProductionTask_H_
#define _ProductionTask_H_

//File: ProductionTask.h

#include "Runnable.h"
#include "MQ.h"

namespace examples
{
    class ProductionTask : public Runnable
    {
    public:
        ProductionTask(MQ &q);
        ~ProductionTask();
        virtual void run();

    private:
        MQ&  m_queue;
    };

}

#endif //_ProductionTask_H_
#include "ProductionTask.h"

//File: ProductionTask.cpp

using namespace examples;

ProductionTask::ProductionTask(MQ &q) : m_queue(q)
{}

ProductionTask::~ProductionTask()
{}

void ProductionTask::run()
{
    while(true)
    {
        m_queue.add("Object");
        ::Sleep(500);
    }
}

Read more ...

Feb 11, 2011

Encapsulating Windows Threads in C++ Objects

Threads in Windows can be created using the following three routines

HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpsa,
DWORD cbStack,
LPTHREAD_START_ROUTINE lpStartAddr,
LPVOID lpvThreadParam,
DWORD fdwCreate,
LPDWORD lpIDThread
);
uintptr_t _beginthread( 
void( *start_address )( void * ),
unsigned stack_size,
void *arglist 
);
uintptr_t _beginthreadex( 
void *security,
unsigned stack_size,
unsigned ( *start_address )( void * ),
void *arglist,
unsigned initflag,
unsigned *thrdaddr 
);
//start_address: is the starting address of a routine that begins the execution of a new thread.

Key Points

1. The above routines expects a pointer to the application defined function which would be the entry point or starting address of the thread.
2. A static member function does not have access to the this pointer of the class whereas the member functions have an implicit parameter which points to the object (the this pointer)
3. A static member function is same as an ordinary C function
4. You should not pass pointer to a member function to a system call that starts a thread. A member function is meaning less without an object to invoke it

The threads in windows can be encapsulated using a static member function which acts as the entry point of the thread and passing the this pointer as the function argument. The ThreadImpl class shown below uses static unsigned __stdcall dispatch(void *); method as the thread start address.

#ifndef _Thread_H_
#define _Thread_H_

//File: Thread.h

#include "NonCopyable.h"

namespace examples
{
    class Thread : public NonCopyable
    {
    public:
        Thread();
        Thread(const char *);
        ~Thread();

        bool join();
        bool join(size_t ms);
        void start();
        void setName(const std::string&);
        const char* getName() const;

    private:
        class ThreadImpl *m_impl;
    };

}
#endif //_Thread_H_
#ifndef _ThreadImpl_H_
#define _ThreadImpl_H_

//File: ThreadImpl.h

#include <windows.h>
#include <process.h>
#include <iostream>
#include <string>
#include "NonCopyable.h"

namespace examples
{
    class ThreadImpl : public NonCopyable
    {
    public:
        ThreadImpl();
        ThreadImpl(const std::string&);
        ~ThreadImpl();

        bool join() const;
        bool join(size_t) const;
        void start() const;
        void setName(const std::string&);
        const char* getName() const;

    private:
        // thread entry point
        static unsigned __stdcall dispatch(void *);
        void run();
        bool spawn();

        HANDLE       m_hthread;
        unsigned     m_thrdid;
        std::string m_thrName;
    };

}
#endif //_ThreadImpl_H_

Read more ...

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

Read more ...

Feb 9, 2011

Debug the Code : Thread synchronization

The program is supposed to print multiples of 10 in a new line in increasing order. Although, the program appears to be correct, it is not. It is giving me duplicate values in the output. Locate the problem?

#include <windows.h>
#include <process.h>
#include <iostream>
#include <assert.h>
#include "Lock.h"

using namespace examples;

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

unsigned __stdcall put(void *args)
{
    Lock lock;
    while(alive)
    {
        lock.acquire();
        current = current + 10;
        ::Sleep(500);
        std::cout << current << std::endl;
        lock.release();
    }
    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;
}

Read more ...

Thread Synchronization in Windows using Critical Section

In multi threaded environments, where more than one thread operates on the shared data (global variables, collections) the results can be unpredictable due to race conditions. Critical Section is a mechanism that ensures that only one thread executes a particular piece of the code. A thread, once it enters a critical section should not be interrupted. Critical Sections have the advantage of not being kernel objects and are maintained in user space. This usually, but not always, provides performance improvements. The CRITICAL_SECTION data type is basically a structure whose fields are used only internally to Windows

Windows provide four functions for using critical sections. To use these functions, you must define an object of type CRITICAL_SECTION.

Key Points

1. Define a CRITICAL_SECTION object cs
2. Initialize a Critical section using InitializeCriticalSection (&cs);
3. After the critical section object has been initialized, a thread enters the critical section by calling EnterCriticalSection(&cs); No two threads can own the critical section at the same time
4. A thread leaves the critical section by calling LeaveCriticalSection (&cs);
5. When the critical section object is no longer needed, it can be deleted by the program by calling DeleteCriticalSection (&cs);
#ifndef _Lock_H_
#define _Lock_H_

#include <windows.h>

/**
*@description: A simple Lock implementation using windows critical section object
*/

namespace examples
{
    class Lock
    {
    public:
        Lock()
        {
            ::InitializeCriticalSection(&m_cs);
        }

        ~Lock()
        {
            ::DeleteCriticalSection(&m_cs);
        }

        void acquire()
        {
            ::EnterCriticalSection(&m_cs);
        }

        void release()
        {
            ::LeaveCriticalSection(&m_cs);
        }

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

        CRITICAL_SECTION m_cs;
    };

}

#endif //_Lock_H_


Read more ...

Feb 2, 2011

Multithreading in Windows - A simple example

A thread is an independent unit of execution within a process. Threads under windows can be created/terminated using the following Win API functions:

1. CreateThread()/ExitThread() system calls.
2. _beginthread()/_endthread() OR _beginthreadex()/_endthreadex() CRT functions.

Key Points

1. Using CreateThread() in a program that uses the CRT functions (for example, links with LIBCMT.LIB) may cause a memory leak of about 70-80 bytes each time a thread is terminated.
2. _beginthread()/_endthread() CRT functions provide a simpler interface but should be avoided. _beginthread() does not have a security attribute, and does not return a thread id. More importantly, it closes the handle of the thread it creates, and the returned thread handle may be invalid by the time the parent thread stores it. If the thread spawned by _beginthread() exits quickly, the handle returned to the caller of _beginthread() may be invalid or, worse, point to another thread. Also avoid _endthread() it does not allow for a return value.
3. With _beginthreadex(), you can use security information, set the initial state of the thread (running or suspended), and get the thread identifier of the newly created thread. You are also able to use the thread handle returned by _beginthreadex() with the synchronization APIs.
4. _endthread() or _endthreadex() is called automatically when the thread returns from the routine passed as a parameter

The example code creates three independent threads using _beginthreadex() in suspended state scheduled to run for 10, 20 & 30 seconds. The threads resume execution after the call to ResumeThread(). The WaitForSingleObject() waits for the given thread for passed slice of time. The function returns with value 0 if the thread terminates by self and by value 258 if a thread's execution is timed out

Read more ...