#ifndef __ACTIONS_H__
#define __ACTIONS_H__

// Usage:
//
// ACTIONS_LIST actionsList;
// CLASS myClass;
// DATA1 myData1;
// DATA2 myData2;
//
// actionsList.Enqueue(myClass, &CLASS::myMethod1, myData1);
// actionsList.Enqueue(myClass, &CLASS::myMethod2, myData2);
//
// actionsList.InvokeAll();

#include <pthread.h>
#include <list>
#include <functional>

// Generalized actor type - a method of some class with one argument
template <class ACTIVE_CLASS, typename DATA_TYPE>
struct ACTOR
{
typedef void (ACTIVE_CLASS::*TYPE)(DATA_TYPE);
};

// Abstract base action class for polymorphic action invocation
class BASE_ACTION
{
public:
    virtual ~BASE_ACTION() {}
    virtual void Invoke() = 0;
};

// Concrete generalized action type - an actor with it's data and owner
template <class ACTIVE_CLASS, typename DATA_TYPE>
class ACTION : public BASE_ACTION,
               public std::unary_function<ACTIVE_CLASS &, void>
{
public:
    ACTION(ACTIVE_CLASS & ac,
           typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
           DATA_TYPE d)
        : activeClass(ac), actor(a), data(d) {}
    void Invoke();
private:
    ACTION(const ACTION<ACTIVE_CLASS, DATA_TYPE> & rvalue);
    ACTION<ACTIVE_CLASS, DATA_TYPE> & operator=(const ACTION<ACTIVE_CLASS, DATA_TYPE> & rvalue);

    ACTIVE_CLASS & activeClass;
    typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE actor;
    DATA_TYPE data;
};

// A list of an actions
// All methods are thread-safe
class ACTIONS_LIST : private std::list<BASE_ACTION *>
{
public:
    // Just a typedef for parent class
    typedef std::list<BASE_ACTION *> parent;

    // Initialize mutex
    ACTIONS_LIST();
    // Delete actions and destroy mutex
    virtual ~ACTIONS_LIST();

    parent::iterator begin();
    parent::iterator end();
    parent::const_iterator begin() const;
    parent::const_iterator end() const;

    bool empty() const;
    size_t size() const;
    void swap(ACTIONS_LIST & list);

    // Add an action to list
    template <class ACTIVE_CLASS, typename DATA_TYPE>
    void Enqueue(ACTIVE_CLASS & ac,
                 typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
                 DATA_TYPE d);
    // Invoke all actions in the list
    void InvokeAll();
private:
    mutable pthread_mutex_t mutex;
};

#include "actions.inl.h"

#endif