Поліморфізм
Feb. 24th, 2010 03:34 pmСподіваюсь, фінальна версія "дій".
Додав трошки динамічного поліморфізму, викинув зайвий функтор. Думаю чи не перемістити Invoke в деструктор. Зупиняє тільки неочевидність такого підходу (хоча при цьому зникне пара "зайвих" методів). Клас ACTION здався мені дуже схожим на std::mem_fun1_ref_t, але все-таки він не такий. ACTION містить повну інформацію про дію, а mem_fun1_ref_t це лише функтор для метода що отримує об’єкт і дані для виклику.
Цього разу сильно не вистачало boost'івських shared_ptr.
Додав трошки динамічного поліморфізму, викинув зайвий функтор. Думаю чи не перемістити Invoke в деструктор. Зупиняє тільки неочевидність такого підходу (хоча при цьому зникне пара "зайвих" методів). Клас ACTION здався мені дуже схожим на std::mem_fun1_ref_t, але все-таки він не такий. ACTION містить повну інформацію про дію, а mem_fun1_ref_t це лише функтор для метода що отримує об’єкт і дані для виклику.
Цього разу сильно не вистачало boost'івських shared_ptr.
#ifndef __ACTIONS_H__
#define __ACTIONS_H__
// Usage:
//
// ACTIONS_LIST actionsList;
// CLASS myClass;
// DATA1 myData1;
// DATA2 myData2;
//
// actionsList.Enqueue(MakeAction(myClass, &CLASS::myMethod1, myData1));
// actionsList.Enqueue(MakeAction(myClass, &CLASS::myMethod2, myData2));
//
// actionsList.InvokeAll();
#include <pthread.h>
#include <list>
// 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:
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
~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
void Enqueue(BASE_ACTION * action);
// Invoke all actions in the list
void InvokeAll();
private:
mutable pthread_mutex_t mutex;
};
template <class ACTIVE_CLASS, typename DATA_TYPE>
ACTION<ACTIVE_CLASS, DATA_TYPE> * MakeAction(ACTIVE_CLASS & ac,
typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
DATA_TYPE d)
{
return new ACTION<ACTIVE_CLASS, DATA_TYPE>(ac, a, d);
}
#include "actions.inl.h"
#endif
|
| _Winnie C++ Colorizer |
#ifndef __ACTIONS_INL_H__
#define __ACTIONS_INL_H__
#include <algorithm>
#include <functional>
// Polymorphic action invocation
template <class ACTIVE_CLASS, typename DATA_TYPE>
void ACTION<ACTIVE_CLASS, DATA_TYPE>::Invoke()
{
(activeClass.*actor)(data);
}
// Delete all actions before deleting list
inline
ACTIONS_LIST::~ACTIONS_LIST()
{
{
STG_LOCKER(&mutex, __FILE__, __LINE__);
parent::iterator it(parent::begin());
while (it != parent::end())
{
delete *it++;
}
}
pthread_mutex_destroy(&mutex);
};
// ...
inline
void ACTIONS_LIST::InvokeAll()
{
STG_LOCKER lock(&mutex, __FILE__, __LINE__);
std::for_each(
parent::begin(),
parent::end(),
std::mem_fun(&BASE_ACTION::Invoke)
);
};
#endif
|
| _Winnie C++ Colorizer |