// event.hpp ********************************************************
//
#ifndef EVENT_HPP
#define EVENT_HPP
// Qt include.
#include <QEvent>
//
// Color
//
enum Color
{
BLUE = 0,
RED = 1,
YELLOW = 2,
FADED = 3
}; // enum Color
//
// ChangeColorEvent
//
class ChangeColorEvent
: public QEvent
{
public:
static const int changeColorEventType;
public:
ChangeColorEvent( Color c );
Color color() const;
private:
Color col;
}; // class ChangeColorEvent
#endif // EVENT_HPP
// event.cpp ********************************************************
//
#include "event.hpp"
//
// ChangeColorEvent
//
const int ChangeColorEvent::changeColorEventType = QEvent::registerEventType();
ChangeColorEvent::ChangeColorEvent( Color c )
: QEvent( static_cast< QEvent::Type >( changeColorEventType ) )
, col( c )
{
}
Color
ChangeColorEvent::color() const
{
return col;
}
// launcher.hpp *****************************************************
//
#ifndef LAUNCHER_HPP
#define LAUNCHER_HPP
// Qt include.
#include <QObject>
#include <QThread>
#include <QVector>
//
// Launcher
//
class Launcher
: public QObject
{
Q_OBJECT
signals:
void start();
public:
Launcher();
public slots:
void launch();
};
#endif // LAUNCHER_HPP
// launcher.cpp *****************************************************
//
#include "launcher.hpp"
//
// Launcher
//
Launcher::Launcher()
{
}
void
Launcher::launch()
{
emit start();
}
// chameleon.hpp ****************************************************
//
#ifndef CHAMELEON_HPP
#define CHAMELEON_HPP
// Qt include.
#include <QObject>
#include "event.hpp"
class MeetingPlace;
class Launcher;
//
// Chameleon
//
class Chameleon
: public QObject
{
Q_OBJECT
signals:
void meetingRequest();
void shutdownAck( int count );
public:
Chameleon( Color c );
Color color() const;
void setMeetingPlace( MeetingPlace * place );
void setLauncher( Launcher * l );
bool event( QEvent * e );
private slots:
void start();
void shutdownRequest();
private:
void changeColor( Color c );
Color newColor( Color c );
private:
int total;
Color col;
}; // class Chameleon
#endif // CHAMELEON_HPP
// chameleon.cpp ****************************************************
//
#include "chameleon.hpp"
#include "place.hpp"
#include "launcher.hpp"
//
// Chameleon
//
Chameleon::Chameleon( Color c )
: total( 0 )
, col( c )
{
}
Color
Chameleon::color() const
{
return col;
}
void
Chameleon::setMeetingPlace( MeetingPlace * place )
{
connect( place, SIGNAL( shutdownRequest() ),
this, SLOT( shutdownRequest() ) );
}
void
Chameleon::setLauncher( Launcher * l )
{
connect( l, SIGNAL( start() ),
this, SLOT( start() ) );
}
bool
Chameleon::event( QEvent * e )
{
if( e->type() == ChangeColorEvent::changeColorEventType )
{
ChangeColorEvent * event = static_cast< ChangeColorEvent* > ( e );
changeColor( event->color() );
return true;
}
else
return QObject::event( e );
}
void
Chameleon::start()
{
emit meetingRequest();
}
void
Chameleon::shutdownRequest()
{
col = FADED;
emit shutdownAck( total );
}
void
Chameleon::changeColor( Color c )
{
col = newColor( c );
++total;
start();
}
Color
Chameleon::newColor( Color c )
{
switch( col )
{
case BLUE:
return c == RED ? YELLOW : RED;
case RED:
return c == BLUE ? YELLOW : BLUE;
case YELLOW:
return c == BLUE ? RED : BLUE;
default:
return FADED;
}
}
// place.hpp ********************************************************
//
#ifndef PLACE_HPP
#define PLACE_HPP
// Qt include.
#include <QObject>
class Chameleon;
//
// MeetingPlace
//
class MeetingPlace
: public QObject
{
Q_OBJECT
signals:
void shutdownRequest();
public:
MeetingPlace( int remaining, const QVector< Chameleon* > & chameleons );
private slots:
void meetingRequest();
void shutdownAck( int count );
private:
void processMeeting( Chameleon * chameleon );
private:
int remainingMeetings;
Chameleon * first;
int chameleonsAlive;
int total;
bool shutdownInitiated;
}; // class MeetingPlace
#endif // PLACE_HPP
// place.cpp ********************************************************
//
#include <QCoreApplication>
#include <QDebug>
#include "place.hpp"
#include "chameleon.hpp"
//
// MeetingPlace
//
MeetingPlace::MeetingPlace( int remaining, const QVector< Chameleon* > & chameleons )
: remainingMeetings( remaining )
, first( 0 )
, chameleonsAlive( chameleons.size() )
, total( 0 )
, shutdownInitiated( false )
{
foreach( Chameleon * chameleon, chameleons )
{
connect( chameleon, SIGNAL( meetingRequest() ),
this, SLOT( meetingRequest() ) );
connect( chameleon, SIGNAL( shutdownAck( int ) ),
this, SLOT( shutdownAck( int ) ) );
}
}
void
MeetingPlace::meetingRequest()
{
if( remainingMeetings )
{
if( !first )
first = qobject_cast< Chameleon* > ( sender() );
else
processMeeting( qobject_cast< Chameleon* > ( sender() ) );
}
else if( !shutdownInitiated )
{
shutdownInitiated = true;
emit shutdownRequest();
}
}
void
MeetingPlace::shutdownAck( int count )
{
qDebug() << "Creatures met:" << count;
total += count;
if( --chameleonsAlive == 0 )
{
qDebug() << "Total: " << total;
QCoreApplication::quit();
}
}
void
MeetingPlace::processMeeting( Chameleon * chameleon )
{
Color firstChameleonColor = first->color();
Color secondChameleonColor = chameleon->color();
QCoreApplication::postEvent( first,
new ChangeColorEvent( secondChameleonColor ) );
QCoreApplication::postEvent( chameleon,
new ChangeColorEvent( firstChameleonColor ) );
first = 0;
--remainingMeetings;
}
// main.cpp *********************************************************
//
#include <QCoreApplication>
#include <QThread>
#include <QVector>
#include <QTimer>
// C++ include.
#include <cstdlib>
#include "chameleon.hpp"
#include "place.hpp"
#include "launcher.hpp"
int main( int argc, char ** argv )
{
QCoreApplication app( argc, argv );
const int meetings = 2 == argc ? std::atoi( argv[ 1 ] ) : 10;
QVector< Chameleon* > chameleons;
Chameleon c1( BLUE );
QThread t1;
c1.moveToThread( &t1 );
chameleons.append( &c1 );
t1.start();
Chameleon c2( RED );
QThread t2;
c2.moveToThread( &t2 );
chameleons.append( &c2 );
t2.start();
Chameleon c3( YELLOW );
QThread t3;
c3.moveToThread( &t3 );
chameleons.append( &c3 );
t3.start();
Chameleon c4( BLUE );
QThread t4;
c4.moveToThread( &t4 );
chameleons.append( &c4 );
t4.start();
MeetingPlace place( meetings, chameleons );
Launcher launcher;
foreach( Chameleon * c, chameleons )
{
c->setMeetingPlace( &place );
c->setLauncher( &launcher );
}
QTimer::singleShot( 0, &launcher, SLOT( launch() ) );
int ret = app.exec();
t1.quit();
t2.quit();
t3.quit();
t4.quit();
t1.wait();
t2.wait();
t3.wait();
t4.wait();
return ret;
}