Tuesday, October 22, 2013

Programming: Windows Threading Vs Linux Threading (Part 6)

A thread cleanup handler in Linux and Windows thread cancellation:

A cleanup handler is a measure, used to deallocate a resource only if the thread exits or canceled. To register a cleanup handler, need to call pthread_cleanup_push() and
pass a pointer to cleanup function and the void * argument. The pthread_cleanup_pop() function removes the routine at the top of the calling thread's cancellation cleanup
stack and optionally invokes it (if execute is non-zero).

The following sample code shows how a dynamically allocated buffer from a thread can be deallocated on canceling the thread in Linux.

#include < pthread.h >
#include < stdio.h >
#include < string.h >
#include < unistd.h > 

char *pgArray = 0;

/* Buffer allocation */
char * allocate_array (size_t size)
{
    return new char[size];
}

void release_array (void *pArg)
{
    if(pgArray)
    {
        printf("release_array() called..\n");
        delete []pgArray;
    }
}

void *Print_Details(void *param)
{
    printf("This is secondary thread's entry...\n");
    printf("Allocating a buffer of size 20...\n");

    pgArray = allocate_array(20);
    strcpy(pgArray, "This is a test");
   
    /*Registering the cleanup handler in case thread cancelled/exit*/
    pthread_cleanup_push(release_array, NULL);

    size_t sIndex = 0;

    // An infinite loop to keep the thread busy until thread cancel gets called...   
    while (pgArray[sIndex] != '\0')
    {
        printf ("%c\n", pgArray[sIndex]);
        sIndex++;
        if(pgArray[sIndex] == '\0')
        {
            sleep(1);
            sIndex = 0;
        }   
    }
   
    printf("This is secondary thread's exit...\n");
    /*Unregister the cleanup handler by passing a nonzero value,
    this actually calls the release_array()*/
    pthread_cleanup_pop(1);
   
    return NULL;
}

/* Main program */

int main()
{
    pthread_t thread;
    int thread_ret;
    void *status;

    printf("This is main... Creating thread with default param\n");   
    pthread_create(&thread, NULL, &Print_Details, NULL);

    sleep(1);   
    // Called secondary thread cancellation....
    printf("Called secondary thread cancellation...\n");
    pthread_cancel(thread);
   
    sleep(2);
    printf("Main exited\n");
   
    return 0;
}

In Windows, as per Microsoft we should call TerminateThread only when there is no other go. Then the question comes what's the way in Windows, a thread/threads can be
canceled/stopped as required. Microsoft provided a way to do this by implementing following steps:

a.    Create an event object using the CreateEvent function.
b.    Create the threads.
c.    Each thread monitors the event state by calling the WaitForSingleObject function. Use a wait time-out interval of zero.
d.    Each thread terminates its own execution when the event is set to the signaled state (WaitForSingleObject returns WAIT_OBJECT_0).

Sunday, September 29, 2013

Programming: Windows Threading Vs Linux Threading (Part 5)

Thread Cancellation in GNU/Linux:

Today, I'm interested to explore how we can prepare thread in GNU/Linux to ignore thread cancellation. This is acvhieved with pthread_setcancelstate().

The signature of the function is:
int pthread_setcancelstate(int state, int *oldstate); 

The function is thread and signal safe. The function sets the cancel  state to one of PTHREAD_CANCEL_ENABLE or  PTHREAD_CANCEL_DISABLE and returns the old cancel state.
Please see the second parameter.
void *Print_Details(void *param)
{
     printf("This is secondary thread's entry...\n");
     int oldState;
     pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState);
     sleep(1);
     for(int i = 0; i < 10; ++i)
     {
          printf("Inside the secondary thread...\n");
     }

     pthread_setcancelstate(oldState, NULL);

     printf("This is secondary thread's exit...\n");
     return NULL;
}
/* Main program */
int main()
{
     pthread_t thread;
     int thread_ret;
     void *status;
     printf("This is main... Creating thread with default param\n");
     pthread_create(&thread, NULL, &Print_Details, NULL);

     sleep (1);

     // Called secondary thread cancellation....
     printf("Called secondary thread cancellation...\n");
     pthread_cancel(thread);
     printf("Thread Cancel ignored...\n");
     sleep(2);
     printf("Main exited\n");

     return 0;
}

Output:
This is main... Creating thread with default param
This is secondary thread's entry...
Called secondary thread cancellation...
Thread Cancel ignored...
Inside the secondary thread...
Inside the secondary thread...
Inside the secondary thread...
Inside the secondary thread...
Inside the secondary thread...
Inside the secondary thread...
Inside the secondary thread...
Inside the secondary thread...
Inside the secondary thread...
Inside the secondary thread...
This is secondary thread's exit...
Main exited

Tuesday, September 17, 2013

Programming: Windows Threading Vs. Linux Threading (Part 4)

Thread Cancellation is a way where it's necessary sometime to terminate a thread explicitly from another thread.
In Windows we've a Function, it's TerminateThread()
The function signature:
BOOL WINAPI TerminateThread(
  _Inout_  HANDLE hThread,
  _In_     DWORD dwExitCode
);

This function is always asynchronous. It never guarantees that the thread will always terminate by the time function returns. This function never cleans up stack of the destroyed thread. So, it's not recommended to use this function until it's absolutely necessary.

Note: As mentioned by Jeffrey Richter, Microsoft designed this API purposely implemented this way to terminate thread(s). This ensures that other threads are still running and accessing the terminated threads stack will not get access violation. So, by leaving the terminated threads stack in memory, other threads which are accessing killed threads stack can continue to execute.

In Linux we've a function, it's pthread_cancel()
The function signature:
int pthread_cancel(pthread_t thread);

A thread may be in one of the three states with respect to cancellation.
a. Asynchronously cancellable - It can be cancelled at any point of time in its execution. pthread_setcanceltype() is used to set thread cancellation asynchronous through PTHREAD_CANCEL_ASYNCHRONOUS. However, this is not recommended.

b. Synchronously cancellable - In this case cancellation occurs when it reaches a specific points in its execution. This places are called cancellation points.

c. Thread also can be uncancellable by setting PTHREAD_CANCEL_DISABLE through pthread_setcancelstate(). Attempt to cancel the thread is ignored.

Thread cancellation in Linux this way may lead to resource leak if cancellation occurs in between but before resource de-allocation. We'll see how this can be handled in pthread to avoid resource leak in next article. However, destructors for automatic objects on the stack are run when a thread is cancelled. The stack is unwound and the destructors are run in reverse order.

Sunday, September 15, 2013

Programming: Windows Threading Vs Linux Threading (Part 3)

Continued from Part 2:

In Linux, normally (when we use default pthread_attribute, aka sending null to pthread_create()), we're creating joinable thread. There is another type of thread named detached thread, which We'll see later.

A joinable thread is like a process, isn't automatically cleaned up by GNU/Linux when it terminates. Instead it's exit states hangs around the system (like zombie process) until the thread called pthread_join() obtain its return value.

Let's see what happens in Windows world:

When thread terminates (the normal way, aka the thread function returns), it ensures the following :

1. All C++ objects created in the thread function will be destroyed properly via their destructor.
2. The OS will clean-up memory owned by threads stack.
3. The system will decrement threads kernel objects usage count.

The following code snippet (GNU/Linux) to show thread created using pthread_create() with default pthread_attr_t (aka null) is joinable thread.

void *Print_Details(void *param)
{
     /*Cast the pointer to right type */
      int    status;
      int       state;
      struct mystruct* p = (struct mystruct*) param;
      printf("Name: %s\n", p->name);
      printf("Thread: %s\n", p->thread);
      printf("+++++++++++++++++++\n");
      pthread_attr_t        pta;
      status = pthread_attr_init(&pta);

      // Get the thread state, Joinable or Detached
      status = pthread_attr_getdetachstate(&pta, &state);
      switch (state)
      {
       case PTHREAD_CREATE_DETACHED:
             printf("The thread is Detached\n");
       break;
       case PTHREAD_CREATE_JOINABLE:
             printf("The thread is Joinable\n");
       break;
      }

      // Destroys thread attributes object and allows system to reclaim resources
      // associated (if any) with attribute object.
      status = pthread_attr_destroy(&pta);
      return NULL;
}

Programming: Windows Threading Vs Linux Threading (Part 2)

This is in continuation of the previous article 'Windows Threading Vs. Linux Threading', here we'll see a subtle but significant difference in thread start routine which gets call from CreateThread() API in Windows world or pthread_create() function call in Linux world.

The ThreadProc function in Windows:

DWORD WINAPI ThreadProc(
  _In_  LPVOID lpParameter
);


This is an application-defined function that serves as the starting address for a thread.

Note: As per MSDN, Do not declare this callback function with a void return type and cast the function pointer to LPTHREAD_START_ROUTINE when creating the thread.
Code that does this is common, but it can crash on 64-bit Windows.

The return value indicates the success or failure of this function. The return value should never be set to STILL_ACTIVE (259).

In Linux: The function passed as start_routine in pthread_create() function should correspond to the following C function prototype: 
void *threadStartRoutinName(void *);

This is one of the difference we need to take care, while writing thread start routine between Windows and Linux.

Thursday, September 12, 2013

Programming: Windows Threading Vs Linux Threading

In this article, I'm trying to show some differences between Windows and Linux thread creation and their respective usage.

Creating Threads:

1.
    a. In Windows: CreateThread() API is used to create a thread to execute within the virtual address space of the calling process.
    b. In Linux: pthread_create() function creates a thread.

    Function Signature:
    // Windows
    HANDLE WINAPI CreateThread(
          _In_opt_   LPSECURITY_ATTRIBUTES lpThreadAttributes,
          _In_       SIZE_T dwStackSize,
          _In_       LPTHREAD_START_ROUTINE lpStartAddress,
          _In_opt_   LPVOID lpParameter,
          _In_       DWORD dwCreationFlags,
          _Out_opt_  LPDWORD lpThreadId
    );

    Function Signature:
    // Linux
    int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
         void *(*start_routine)(void *), void *arg);

    In Windows: We can pass stack size in bytes if required to same CreateThread() API.
    In Linux:  The stack size is set in the pthread attributes object; that is, the parameter attr of type pthread_attr_t is passed to the library call pthread_create().
        This object needs to be initialized by the call pthread_attr_init() before any attributes are set.
        The attribute object is destroyed using the call pthread_attr_destroy().
        The stack size is set using the call pthread_attr_setstacksize(): int pthread_attr_setstacksize(pthread_attr_t *threadAttr, int stack_size);

    In this article, using default thread attributes to create threads on Windows and Linux.
    In Windows: Used WaitForMultipleObjects() API to force main() to wait until all threads execution are done.
    In Linux: Used pthread_join() to achieve the same.

    Following code snippets does same stuff on Windows and Linux but there are some differences from programming point of view.
    Code Windows:
    =============
    #include < windows.h >
    #include < stdio.h >
    #define MAX_THREADS 2

    struct MyData
    {
        char name[20];
        char thread[20];
    };

    DWORD WINAPI MyThreadFunction( LPVOID lpParam );

    int _tmain(int argc, _TCHAR* argv[])
    {
        HANDLE hThread[2] = {NULL};
   
        DWORD   dwThreadId;
        struct MyData mData1;
        struct MyData mData2;

        strcpy(mData1.name, "Testing - 1");
        strcpy(mData1.thread, "Thread - 1");

        strcpy(mData2.name, "Testing - 2");
        strcpy(mData2.thread, "Thread - 2");

        hThread[0] = CreateThread(
            NULL,                // Default Security Attributes
            0,                    // Use Default Stack size
            MyThreadFunction,    // Thread function name
            &mData1,            // Argument to thread function
            0,                    // Use default creation flags
            &dwThreadId
            );

        if(NULL == hThread[0])
        {
            printf("CreateThread failed for Thread 1\n");
        }
   
        hThread[1] = CreateThread(
            NULL,                // Default Security Attributes
            0,                // Use Default Stack size
            MyThreadFunction,        // Thread function name
            &mData2,            // Argument to thread function
            0,                    // Use default creation flags
            &dwThreadId
        );

        if(NULL == hThread[1])
        {
            printf("CreateThread failed for Thread 2\n");
        }

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

        CloseHandle(hThread[0]);
        CloseHandle(hThread[1]);
   
        return 0;
    }

    DWORD WINAPI MyThreadFunction( LPVOID lpParam )
    {
        struct MyData *p = (struct MyData *)lpParam;
        printf("Name: %s\n", p->name);
        printf("Thread: %s\n", p->thread);
        printf("+++++++++++++++++++++++++++++\n");

        return 0;
    }   

    Code Linux:
    =============
    #include < pthread.h >
    #include < stdio.h >
    #include < string.h >

    struct mystruct
    {
        char name[20];
        char thread[20];
    };

    void *Print_Details(void *param)
    {
        /*Cast the pointer to right type */
        struct mystruct* p = (struct mystruct*) param;

        printf("Name: %s\n", p->name);
        printf("Thread: %s\n", p->thread);
        printf("+++++++++++++++++++\n");   

        return NULL;
    }

    /* Main program */

    int main()
    {
        pthread_t thread1;
        pthread_t thread2;

        struct mystruct args1;
        struct mystruct args2;

        /* Create new thread */
        strcpy(args1.name, "Testing - 1");
        strcpy(args1.thread, "Thread - 1");
        pthread_create(&thread1, NULL, &Print_Details, &args1);

        /* Create another new thread */
        strcpy(args2.name, "Testing - 2");
        strcpy(args2.thread, "Thread - 2");
        pthread_create(&thread2, NULL, &Print_Details, &args2);

        /* Ensure First thread has finished */
        pthread_join(thread1, NULL);
   
        /* Ensure second thread has finished */
        pthread_join(thread2, NULL);

        /* Now safe to return main */
        return 0;
    }

Reference Windows: http://msdn.microsoft.com/en-us/library/ms682453%28VS.85%29.aspx
Reference Linux: http://publib.boulder.ibm.com/infocenter/iseries/v5r4/index.jsp?topic=%2Fapis%2Fusers_14.htm

Tuesday, July 16, 2013

A STL vector usage through shared_ptr

We know vector can store homogeneous kind of stuff. That is, it can store type int, string etc individually but not element of type int with string etc.

However, sometimes we might have requirements that it can store elements which are in inheritance relation and can do stuff by calling function of respective element stored in vector. As an example, I've a Shape class from which I've derived Circle, Polygon etc. Now I want to store Circle, Polygon object in a vector and then access each element by its iterator and draw shape accordingly.

C++ 2011 made it possible via shared_ptr. Thanks to Stephan aka STL.

Code snippet

#include < iostream >
#include < memory >
#include < vector >

using namespace std;

class Shape
{
public:
    Shape(){}
    virtual ~Shape(){}

    virtual void draw(int x, int y)
    {
        cout << "Shape::draw(" << x << ", " << y << ")" << endl;
    }

private:
    Shape(const Shape&);
    Shape& operator=(const Shape&);
};

class Circle : public Shape
{
public:
    virtual void draw(int x, int y) override
    {
        cout << "Circle::draw(" << x << ", " << y << ")" << endl;
    }
};

class Polygon : public Shape
{
public:
    virtual void draw(int x, int y)
    {
        cout << "Polygon::draw(" << x << ", " << y << ")" << endl;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    vector< shared_ptr< Shape > >vec;

    shared_ptr< Shape > shape = make_shared< Polygon >();
    vec.push_back(shape);

    shape = make_shared< Circle >();
    vec.push_back(shape);

    vec.at(0)->draw(11, 22);
    vec.at(1)->draw(33, 44);

    return 0;
}

I've used Visual Studio 2010 to build this code. And output will be:
Polygon::draw(11, 22)
Circle::draw(33, 44)