#include <ace/OS_main.h>
#include <ace/Refcounted_Auto_Ptr.h>
#include <ace/Null_Mutex.h>
#include <algorithm>
#include <iostream>
#include <set>
struct Msg1 {
int sending_time;
int seq_num;
};
int getTime( const Msg1 & m ) { return m.sending_time; }
int compareType( const Msg1 & a, const Msg1 & b ) {
return a.seq_num - b.seq_num;
}
void apiCall( const Msg1 & m ) {
std::cout << "api on Msg1: "
<< m.sending_time << ", " << m.seq_num << std::endl;
}
struct Msg2 {
int update_time;
int external_id;
};
int getTime( const Msg2 & m ) { return m.update_time; }
int compareType( const Msg2 & a, const Msg2 & b ) {
return a.external_id - b.external_id;
}
void apiCall( const Msg2 & m ) {
std::cout << "api on Msg2: "
<< m.update_time << ", " << m.external_id << std::endl;
}
struct Msg3 {
int orig_time;
int counter;
};
int getTime( const Msg3 & m ) { return m.orig_time; }
int compareType( const Msg3 & a, const Msg3 & b ) {
return a.counter - b.counter;
}
void apiCall( const Msg3 & m ) {
std::cout << "api on Msg3: "
<< m.orig_time << ", " << m.counter << std::endl;
}
template< class T > struct TypeTag {};
template<> struct TypeTag<Msg1> { static const int value = 0; };
template<> struct TypeTag<Msg2> { static const int value = TypeTag<Msg1>::value + 1; };
template<> struct TypeTag<Msg3> { static const int value = TypeTag<Msg2>::value + 1; };
class AbstractMessageHolder {
public :
virtual ~AbstractMessageHolder() {}
virtual void callApi() = 0;
virtual void print() const = 0;
virtual int getTime() const = 0;
virtual int compareWith( const AbstractMessageHolder & other ) const = 0;
virtual int typeTag() const = 0;
virtual const void * rawPointer() const = 0;
};
typedef ACE_Refcounted_Auto_Ptr< AbstractMessageHolder, ACE_Null_Mutex >
AbstractMessageHolderAutoPtr;
template< class T >
class MessageHolder : public AbstractMessageHolder {
public :
MessageHolder( const T & value ) : msg( value ) {}
virtual void callApi() { apiCall( msg ); }
virtual void print() const { apiCall( const_cast< T& >( msg ) ); }
virtual int getTime() const { return ::getTime( msg ); }
virtual int compareWith( const AbstractMessageHolder & other ) const {
int r = getTime() - other.getTime();
if( !r ) {
r = typeTag() - other.typeTag();
if( !r ) {
r = compareType(
msg,
*(reinterpret_cast< const T*>( other.rawPointer() )) );
}
}
return r;
}
virtual int typeTag() const { return TypeTag<T>::value; }
virtual const void * rawPointer() const { return &msg; }
private :
T msg;
};
template< class T >
AbstractMessageHolderAutoPtr makeMessageHolder( const T & o ) {
return AbstractMessageHolderAutoPtr( new MessageHolder< T >( o ) );
}
struct MessageHolderComparator {
bool operator()(
const AbstractMessageHolderAutoPtr & a,
const AbstractMessageHolderAutoPtr & b ) {
return a->compareWith( *b ) < 0;
}
};
typedef std::multiset<
AbstractMessageHolderAutoPtr,
MessageHolderComparator >
MessageContainer;
void ApiCaller(
const AbstractMessageHolderAutoPtr & o ) {
o->callApi();
}
void MsgPrinter(
const AbstractMessageHolderAutoPtr & o ) {
o->print();
}
void fillContainer( MessageContainer & to ) {
Msg1 a1 = { 4, 3 };
Msg1 a2 = { 4, 2 };
Msg1 a3 = { 2, 4 };
Msg2 b1 = { 3, 0 };
Msg2 b2 = { 3, 4 };
Msg2 b3 = { 3, 1 };
Msg2 b4 = { 2, 0 };
Msg3 c1 = { 3, 0 };
Msg3 c2 = { 1, 8 };
Msg3 c3 = { 1, 9 };
to.insert( makeMessageHolder( a1 ) );
to.insert( makeMessageHolder( a2 ) );
to.insert( makeMessageHolder( a3 ) );
to.insert( makeMessageHolder( b1 ) );
to.insert( makeMessageHolder( b2 ) );
to.insert( makeMessageHolder( b3 ) );
to.insert( makeMessageHolder( b4 ) );
to.insert( makeMessageHolder( c1 ) );
to.insert( makeMessageHolder( c2 ) );
to.insert( makeMessageHolder( c3 ) );
}
int main( int argc, char ** argv ) {
MessageContainer msgs;
fillContainer( msgs );
std::cout << "calling API..." << std::endl;
std::for_each( msgs.begin(), msgs.end(), ApiCaller );
std::cout << "printing messages..." << std::endl;
std::for_each( msgs.begin(), msgs.end(), MsgPrinter );
return 0;
}