Thursday, November 19, 2009

C++ cast operators

Describe C++ cast operators

static_castis used to cast up and down the class hierarchy, conversions with unary constructors as well as conversions with conversion operators. It is similar to the C-style casts.

For instance, in the code below, a call is made to the operator int in class X

dynamic_cast is the C++ way of casting. It uses RTTI to determine if the cast is valid.

If we are attempting to cast to an incompatible pointer type, the result is a NULL.

If we try to cast to an incompatible reference type, an std::bad_cast exception is thrown.

The dynamic_cast must be un-ambigous.

dynamic_cast works only with polymorphic types (ie where the classes have at least one virtual function)

struct X
 {
     int value;
     virtual ~X() {}
 };

 struct Y : public X
 {
 };


 int main(int, char **)
 {
     Y anY;
     X anX;

     X & xRef = anY;
     Y& yRef = dynamic_cast( xRef );

     X& xRef2 = anX;
     try
     {
         Y& yRef2 = dynamic_cast( xRef2 );
     }
     catch( std::bad_cast&  e)
     {
         std::cout <<"Caught bad cast exception ! " << e.what() << "\n";
     }
     std::cout << "Program finished !\n";
     return 0;
 }


reinterpret_castAllows you to cast apples to horses.

const_castallows us to cast away the const or volatile from a reference or pointer. The target data type must be the same as the source type.


Thursday, November 12, 2009

Delegates and events in C#

What are delegates and events in C# ? Delegates

Delegates in C# are objects which points towards a function which matches its signature. Delegates are reference type used to encapsulate a method with a specific signature. Delegates are similar to function pointers in C++; however, delegates are type-safe and secure.

Here are some features of delegates:

  • A delegate represents a class.
  • A delegate is type-safe.
  • We can use delegates both for static and instance methods
  • We can combine multiple delegates into a single delegate.
  • Delegates are often used in event-based programming, such as publish/subscribe.
  • We can use delegates in asynchronous-style programming.
  • We can define delegates inside or outside of classes.
  • Delegte declarations are like ordinary declerations and can be public, private internal etc.
  • Two delegates are compatible if their parameters are of the same type, order and modifiers and their return types are the same.
  • Delegates can be combined using the + and += operators. When two delegates are combined, the resulting delegate contains all the callable entities from both the delegates. Similarily, delegates can be removed using the - or -= operators.
  • Delegates can be compared.
  • delegate methods are invoked synchronously.
  • If such a delegate invocation includes reference parameters, each method invocation will occur with a reference to the same variable and changes to that variable by one method in the invocation list will be visible to methods further down the invocation list.
  • If the delegate invocation includes output parameters or a return value, their final value will come from the invocation of the last delegate in the list.
  • If an exception occurs within a delegate and the exception is not caught in the method that was called, continues in the method that called the delegate. If the exception is not handled in the called method, delegate processing is abandoned and other functions in the delegate are not called.

To declare a delegate, use the delegate keyword like:

    // declare a delegate
    public delegate void MyDelegate(int x); 

    /*
     * Declare a function which takes a 
     * delegate parameter. 
     */
    void MyFunc( MyDelegate inDelegateParam)
    {
         inDelegateParam(100); // Call the delegate
    }

    // Create a function with the same signature 
    // as the delegate decl
    void someFunc(int p)
    {
    }

    static void Main(string[] args)
    {
        MyDelegate aDel = new MyDelegate( someFunc);
        MyFunc( aDel );
    }

When we declare a delegate, the compiler automatically creates a class derrived from System.Delegate. A delegate instance encapsulates one or more methods, each of which is a callable entiry. For instance methods, the callable entity consists of the instance and the method.

When we invoke a delegate, all the callable entities get called.

Events

Delegates are used to create events. here is an example of an event

        // First declare a delegate
        public delegate void MyDelegate(int x);

        // now, the event
        public static event MyDelegate m_del;

        public static void testit()
        {
            m_del += new MyDelegate(EventFunc);
            m_del(2);
        }

        // This is the event handler
        static void EventFunc(int x)
        {
            Console.WriteLine("in event handler!!!!\n");
        }

Thursday, November 5, 2009

Singleton in multi-threaded environment

Question: How would you write a singleton in a multi-threaded environment?

In a singleton, there are two race conditions; one where the instance is created and the other when we access instance data. The method which creates the singleton instance must be made thread safe. Here is an example:

Wednesday, October 14, 2009

Reversing a single linked list

Question :How do you reverse a list?
Ans:
void reverselist(void)
{
    if(head==0)
        return;
    if(head->next==0)
        return;
    if(head->next==tail)
    {
        head->next = 0;
        tail->next = head;
    }
    else
    {
        node* pre = head;
        node* cur = head->next;
        node* curnext = cur->next;
        head->next = 0;
        cur->next = head;
        for(; curnext!=0; )
        {
            cur->next = pre;
            pre = cur;
            cur = curnext;
            curnext = curnext->next;
        }
        curnext->next = cur;
    }
}


Wednesday, September 2, 2009

Functors

Summary A Function Object, or Functor (the two terms are synonymous) is simply any object that can be called as if it is a function. An ordinary function is a function object, and so is a function pointer; more generally, so is an object of a class that defines operator(). Description

The basic function object concepts are Generator, Unary Function, and Binary Function. For example, a generator can be called as f(), Unary function as f(x), and binary function as f(x,y). All other function object concepts defined by the STL are refinements of these three. Function objects that return bool are an important special case.

A Unary Function whose return type is bool is called a Predicate, and a Binary Function whose return type is bool is called a Binary Predicate.

There is an important distinction, but a somewhat subtle one, between function objects and adaptable function objects. In general, a function object has restrictions on the type of its argument. The type restrictions need not be simple, though: operator() may be overloaded, or may be a member template, or both. Similarly, there need be no way for a program to determine what those restrictions are. An adaptable function object, however, does specify what the argument and return types are, and provides nested typedefs so that those types can be named and used in programs. If a type F0 is a model of Adaptable Generator, then it must define F0::result_type. Similarly, if F1 is a model of Adaptable Unary Function then it must define F1::argument_type and F1::result_type, and if F2 is a model of Adaptable Binary Function then it must define F2::first_argument_type, F2::second_argument_type, and F2::result_type. The STL provides base classes unary_function and binary_function to simplify the definition of Adaptable Unary Functions and Adaptable Binary Functions. [2] Adaptable function objects are important because they can be used by function object adaptors: function objects that transform or manipulate other function objects. The STL provides many different function object adaptors, including unary_negate (which returns the logical complement of the value returned by a particular AdaptablePredicate), and unary_compose and binary_compose, which perform composition of function object. Finally, the STL includes many different predefined function objects, including arithmetic operations (plus, minus, multiplies, divides, modulus, and negate), comparisons (equal_to, not_equal_to greater, less, greater_equal, and less_equal), and logical operations (logical_and, logical_or, and logical_not). It is possible to perform very sophisticated operations without actually writing a new function object, simply by combining predefined function objects and function object adaptors.

Wednesday, July 29, 2009

Everything about virtual functions

  • A class that declares or inherits a virtual function is called a polymorphic class
  • A virtual funtion ensures dynamic binding.
  • If a function is declared virtual, then if we have a function with the same name and parameters in a derrived class, then that function is automatically virtual, even if we do not declare it as virtual in the derrived class.
     struct A
     {
        virtual void f()
        {
           cout << "A::f()";      
        }    
    }     
    struct B : A    
    {        
        void f( int )      
        {         
           cout << "B::f()";     // Hides A:f()
        }    
    }     
    struct C: B    
    {        
        void f()      
        {          
            cout <<"C::f()";     // This is always virtual
        }    
    }   
    

    In the above example, B::F(int) hides A:f(). A b; b.f is illegal.

    Also, C::F() is implicitly virtual.

  • If a funcion has the same name as the base class function and different parameters, then it hides all functions with the same name in the base class. In the Example 1 above, B::f hides A:f
  • The return type of a virtual function may be different from the overridden one. This is called covarent virtual function. The return types may differ provided all the following conditions are met:

    1. If A::func returns a pointer or reference of type T, then B:func can return only a direct or un-ambigous derrived class from T

    2. The const or volatile qualifier of type returned by B is at lease as restrictive as A

    3. The return type of B::func must be complete and accessible at the point or it may be a B.

  • We can call a base classes virtual function by base::func().
  • A virtual function can be == 0, or pure virtual. Instances of abstract classes can not be created and an abstract class can not be used as parameters to templates.
  • A derrived class can be abstract, even if it is derrived from a non-abstract class.
  • We can pass a pointer or reference to an abstract class as a parameter in a function. In that function, we can even call a pure virtual method. However, we can not have an instance of an abstract class as a parameter.
  • We can override a virtual function with an abstract function in a derrived class.

Everything about constructors

  1. Everything you wanted to know about constructors
    • Constructors are used to initialize objects.
    • When a class derives from other classes, the constructors are called in the following order.
      • Virtual base classes, left to right in the class decleration
      • base classes, left to right in the class decleration
      • Member classes and references
      • Finally, the body of the constructor is executed.
    • A copy constructor is a constructor which takes a const reference of type self and is used to construct a copy of the instance. A copy constructor is used extensively by STL containers and algorithms.
    • A constructor must not leak memory, even if any of the constructors of base or member classes throws an exception.
    • A default constructor is a constructor which takes no arguments, or a constructor which has default values for all arguments. If we dont define any constructor in our class, then the compiler automatically creates a default constructor for our class
    • If we make the constructor of a class private, then an instance of the class can not be created directly. We often use this to create a singleton pattern.
    • If you have a reference member, then the only way for you to initialize the reference is in the constructor. If your class has pointers, then you should always initialize the pointer to NULL in the constructor.

Monday, July 27, 2009

Using Expat to parse XML

Socket programming

Sockets are endpoints in communication. We create a socket on the server application and sit and listen for incomming connections. Clients initiate a connection and send data once the connection is established.

There are two types of sockets; connected and datagram sockets. Connected sockets keep the connection between the client-server. With datagram sockets, there is no gurantee of delivery of packet and we have to use packet counting mechanism if we want to gurantee delivery of data. However, datagram sockets are less resource intensive and can be used with applications like media streaming applications.

Let us look at connection oriented sockets.

For the server side, the basic steps are:

  • Create a socket (int aSocket = ::socket(...) )
  • Bind the socket to an address and port
  • Call accept in a loop to listen to connection requests. This call blocks until there is a connection request. On return, the OS returns a socket which we use to communicate with the client application (see example)

On the client side, we create a socket simply call connect and we are off.

Data structures used:

1. sockaddr and sockaddr_in are used to specify the host and port we want to connect to. Both these structures are of the same size. All networking calls where we need to specify an address take a pointer to a sockaddr structure as a parameter. With TCP/IP sockets, we fill in a sockaddr_in structure and typecast it to a sockaddr structure in calls to networking functions.


typedef uint32_t in_addr_t;

struct in_addr
{
  in_addr_t s_addr;
};

struct sockaddr_in
{
  sa_family_t sin_family;
  in_port_t sin_port;
  struct in_addr sin_addr;

  unsigned char __pad[16 - sizeof(short int)
   - sizeof(unsigned short int) - sizeof(struct in_addr)];
};

The following functions can be used to convert dotted (127.0.0.1) to binary and vice-versa:

    #include 
    in_addr_t inet_addr(const char *cp);
    char *inet_ntoa(struct in_addr in);

--more stuff to follow ---

Using the select command

Typically, on the server side, we would have several sockets which we would read and write data to. We use the select function to determine which sockets we can read and/or write to without the call blocking.

The select call takes the following parameters:

   int select(int maxFD, fd_set *read, 
              fd_set *write, 
              fd_set *exceptions, 
              struct timeval *tv);

where:

  • The first parameter, i.e. maxFD in the above call is the highest number +1 of descriptor in read, write and except set we are interested in. For example, if we currently have sockets 4,7 and 9 open and we wish to read from any one of these, we would pass 10 as the first argument to select call.
  • read, write and ex in the call above are pointers to three fd_set structures which specify the sockets we are interested in. This structure is described below. Any or all of these parameters can be null. For example, if we are only interested in determining which sockets have data to read, we would pass NULL for the write and exceptions sets. We use the FD_SET, FD_CLR calls to set, clear individual sockets and FD_ZERO to zero out the entire set. FD_ISSET is used to determine which sockets are ready (see example below).
  • The timeval struct gives the number of seconds to wait before returning. This argument can be used to specify an indefinite wait, or a definite wait time, as described below.
  • The return value is the total number of descriptors that are ready, with -1 representing an error condition, 0 means that the call timed out before any of the descriptors became ready, etc.

The fd_set structure is simply a bit map with each bit representing an integer value. For example, if we use the FD_SET macro like FD_SET( 4,&readFD), bit 4 in the readFD will be set.

The struct timeval is as follows:

    struct timeval
    {
        long tv_sec;
        long tv_usec;
     };

where tv_sec and tv_usec specify the seconds and microseconds to wait.

  • If the tv parameter is null, then the kernal will wait forever until a socket does become ready.
  • If both tv_sec and tv_usec are zero, then the call will return immediately.
  • If either of these parameters is non-zero, then the call will wait for the specified interval. We can then use the return value from this call to check if any of the sockets are ready. The POSIX specs allow the call to modify this struct, so remember to reset the values before each call.

If a bit is set on the exception set, that indicates the arrival of out-of-band data.

Note that setting a socket in the non-blocking mode will not affect the way select works. So, even if all the sockets in the read set are non-blocking, the select call will wait as specified by the tv parameter.

Producer-Consumer using Windows threading

Here is a simple solution to the producer-consumer problem using Windows threading. Basic classes are
  • Producer This is the thread that produces jobs at random intervals
  • Consumer This is the thread that pulls jobs off the messageQueue and processes the job. There are multiple consumers.
  • MessageQueue Fixed size queue to hold the jobs
  • Job Abstract job class that the Consumer consumes
  • Thread Utility class to manage trreads

Sunday, July 26, 2009

Barber Problem Solution in C++

The barber shop simulation is a good problem to practice multi-threading concepts. Here is the problem, which we need to simulate. Barber shop consists of a waiting room with 'n' chairs, and a barber room with one barber chair

  1. If there are no customers to be served the barber goes to sleep.
  2. If a customer enters the barber shop and all the chairs are occupied then customer leaves shop.
  3. If barber is busy but chairs are available then customer sits in one of the free chairs.
  4. If barber is asleep the customer wakes up barber.

Here is one solution to the barber problem using Windows threading primitives. Essential classes that we need:

  • Barber This class runs in a different thread. It calls BarberShop.GetNextCustomer to get an available customer.
  • Customer
  • BarberShop This is where all the business logic resides. The two main routines are GetNextCustomer, which picks up the next available customer from the queue or blocks on m_BarberSleepEvt if no customers. The NeedsHaircut routine adds a customer to the end of the queue of waiting customers if the queue has empty spaces. If not, it simply ignores the request. If the queue was empty before adding, then it means that the barber thread was waiting on the event and it releases the event after adding the customer.
  • Thread This is a utility class that can be used to start/stop threads. Simply derive your class from this class after overriding the virtual run method and then call the Start routine.

The entire solution is in 2 files. I compiled the code using Borland's command line C++ compiler (free).


File: BarberShopSimulation.h

#ifndef _BARBER_SHOP_SIMULATION_H
#define _BARBER_SHOP_SIMULATION_H


#define NUM_WAITING_CHAIRS  5


class Barber;
class Customer;
class BarberShop;

class Thread
{
    HANDLE m_ThreadHandle;
    bool m_Terminate;
    DWORD m_ThreadID;

    static DWORD _ThreadProc(void *);
public:
    Thread();
    virtual ~Thread();
    void Start();
    void Stop() {m_Terminate = true;}
    bool KeepRunning() {return !m_Terminate;}
    DWORD GetThreadID() const {return m_ThreadID;}
    virtual DWORD run() = 0;
};


class Barber : public Thread
{
    BarberShop & m_Shop;

public:
    Barber( BarberShop & inShop);
    ~Barber();
    DWORD run();
};


// Dummy class
class Customer
{
    int m_ID;
public:
    Customer(int inID) : m_ID(inID)
    {
    }
    int GetID() const  {return m_ID;}

    Customer(const Customer & inCust): m_ID( inCust.m_ID )
    {
    }
};


std::ostream & operator << (std::ostream & os, const Customer & inCust)
{
    os << inCust.GetID() ;
    return os;
}


class BarberShop
{

    std::auto_ptr m_Barber;
    HANDLE m_BarberSleepEvt;
    HANDLE m_Mutex;
    int m_Head, m_Tail;
    std::auto_ptr  m_WaitingCustomers[ NUM_WAITING_CHAIRS];

    inline incr(int& inValue)
    {
        ++inValue;
        if(inValue >= NUM_WAITING_CHAIRS )
            inValue = 0;
    }
public:
    BarberShop();
    ~BarberShop() {}

    void GetNextCusomer( std::auto_ptr & outCust);
    void NeedsHaircut( std::auto_ptr& inCust);
};



#endif // _BARBER_SHOP_SIMULATION_H

BarberShopSimulation.cpp

#include <iostream>
#include <windows.h>
#include "BarberShopSimulation.h"

// For random sleep
#include <stdio.h>javascript:void(0)
#include <stdlib.h>
#include <time.h>

// =================================================
//      Thread
// =================================================
Thread::Thread()
: m_ThreadHandle(NULL), m_Terminate(false)
{
}

Thread::~Thread()
{
    if( m_ThreadHandle != NULL )
    {
        ::TerminateThread( m_ThreadHandle, 0 );
        m_ThreadHandle = NULL;
    }
}

DWORD Thread::_ThreadProc(void *ap)
{
    Thread *r = (Thread *)ap;
    return r->run();
}

void Thread::Start()
{
    m_ThreadHandle = ::CreateThread(
                     NULL,       // default security attributes
                     0,          // default stack size
                     (LPTHREAD_START_ROUTINE) _ThreadProc,
                     this,       // no thread function arguments
                     0,          // default creation flags
                     &m_ThreadID); // receive thread identifier
    if( m_ThreadHandle == NULL )
        std::cout << "Could not create a thread!\n";
}

// =================================================
//      Barber
// =================================================
Barber:: Barber( BarberShop & inShop)
: m_Shop(inShop)
{
}
Barber::~Barber()
{
}

DWORD Barber::run()
{
    std::cout << "Barber::run...";
    while(1)
    {

        std::auto_ptr aCust;
        m_Shop.GetNextCusomer( aCust );
        if( !aCust.get() )
        {
            std::cout << "Barber Error: Customer is null ?? terminating...";
            return 1;
        }
        std::cout << "Barber is now cutting hair for customer " << *aCust << "...\n";
        ::Sleep( 600 );
        std::cout << " finished\n";
    }
}


// =================================================
//      BarberShop
// =================================================

BarberShop::BarberShop()
:m_BarberSleepEvt(NULL),
    m_Mutex(NULL),
    m_Head(0),
    m_Tail(0)
{
    m_BarberSleepEvt = ::CreateEvent( NULL, FALSE, FALSE, NULL);
    m_Mutex = ::CreateMutex( NULL, FALSE, NULL );
    std::auto_ptr aBarb( new Barber(*this) );
    m_Barber = aBarb;
    m_Barber->Start();
}


void BarberShop::GetNextCusomer( std::auto_ptr & outCust)
{
    DWORD aResult;

    do
    {
        aResult = ::WaitForSingleObject( m_Mutex, INFINITE );
        if( aResult != WAIT_OBJECT_0 )
        {
            std::cout << "BarberShop::GetNextCusomer. Error while waiting for mutex!\n";
            return;
        }
        // If the queue is empty, go to sleep. When a customer arrives, we will be woken up
        if( m_Head == m_Tail)
        {
            ::ReleaseMutex( m_Mutex );
            aResult = ::WaitForSingleObject( m_BarberSleepEvt, INFINITE );
            if( aResult != WAIT_OBJECT_0 )
            {
                std::cout << "BarberShop::GetNextCusomer. Error while waiting for event!\n";
                return;
            }
        }
        else
        {
            // There are some waiting customers. Get the one from the head
            outCust = m_WaitingCustomers[m_Head];
            incr( m_Head );
            ::ReleaseMutex( m_Mutex );
            return;
        }
    }
    while(1);
}


void BarberShop::NeedsHaircut( std::auto_ptr & inCust)
{
    DWORD aResult;
    int aNextPos;
    bool aQueueWasEmpty;

    // Get the mutex...
    aResult = ::WaitForSingleObject( m_Mutex, INFINITE );
    if( aResult != WAIT_OBJECT_0 )
    {
        std::cout << "BarberShop::GetNextCusomer. Error while waiting for mutex!\n";
        return;
    }

    // Check if the queue was empty. If the queue was empty, then we need to signal the
    // sleeping barber that there is a waiting customer
    aQueueWasEmpty = m_Tail == m_Head;
    aNextPos = m_Tail;
    incr(aNextPos );
    if( aNextPos == m_Head )
    {
        std::cout << "BarberShop::NeedsHaircut. Cant accept customer " << *inCust << " as Queue is full..\n";
        ::ReleaseMutex( m_Mutex );
        return;
    }
    // queue is not full. Add the customer to the tail
    m_WaitingCustomers[ m_Tail ] = inCust;
    m_Tail = aNextPos;
    ::ReleaseMutex( m_Mutex );
    if( aQueueWasEmpty )
    {
        ::SetEvent(m_BarberSleepEvt);
    }
    return;
}



// ====================================================
//    Application
// ====================================================
int main(int, char **)
{
    std::cout << "Hello, everyone. I am now running barber shop simulation\n";

    BarberShop aShop;
    for(int i=0; i < 1000; i++)
    {
        std::auto_ptr aCust( new Customer(i));
        std::cout << "adding customer # " << i << " to shop\n";
        aShop.NeedsHaircut( aCust );
        ::srand(time(NULL));
        int aCount = ::rand()%100 + 10;
        ::Sleep( 700 ); //aCount );
    }
    ::Sleep(10000);
}