forked from 0ad/0ad
Ykkrosh
13f2e3ca0c
* Fixed some bugs with incorrect macro usage (SDL_BYTE_ORDER vs SDL_BYTEORDER, {MSC,GCC}_VER vs {MSC,GCC}_VERSION, OS_WIN/OS_UNIX in projects where they're not defined). * Removed some redundant declarations of g_Console. * Removed some unnecessary semicolons. * Removed some unused variables. * Added throw specification to operator new. This was SVN commit r4698.
192 lines
5.1 KiB
C++
192 lines
5.1 KiB
C++
// Used by Messages.h, so that file stays relatively clean.
|
|
|
|
#ifndef MESSAGESSETUP_NOTFIRST
|
|
#define MESSAGESSETUP_NOTFIRST
|
|
|
|
#include "MessagePasser.h"
|
|
#include "SharedTypes.h"
|
|
#include "Shareable.h"
|
|
|
|
// Structures in this file are passed over the DLL boundary, so some
|
|
// carefulness and/or luck is required...
|
|
|
|
class CMutex;
|
|
|
|
namespace AtlasMessage
|
|
{
|
|
|
|
struct IMessage
|
|
{
|
|
virtual const char* GetName() const = 0;
|
|
virtual ~IMessage() {}
|
|
|
|
enum Type { Message, Query };
|
|
virtual Type GetType() const = 0;
|
|
};
|
|
|
|
|
|
#define MESSAGESTRUCT(t) \
|
|
struct m##t : public IMessage { \
|
|
virtual const char* GetName() const { return #t; } \
|
|
virtual Type GetType() const { return IMessage::Message; } \
|
|
private: \
|
|
const m##t& operator=(const m##t&); \
|
|
public:
|
|
|
|
// Messages for doing/undoing/etc world-altering commands
|
|
|
|
MESSAGESTRUCT(WorldCommand)
|
|
mWorldCommand() {}
|
|
virtual void* CloneData() const = 0;
|
|
virtual bool IsMergeable() const = 0;
|
|
};
|
|
MESSAGESTRUCT(DoCommand)
|
|
mDoCommand(mWorldCommand* c) : name(c->GetName()), data(c->CloneData()) {}
|
|
const Shareable<std::string> name;
|
|
const Shareable<void*> data;
|
|
// 'data' gets deallocated by ~cWhatever in the game thread
|
|
};
|
|
MESSAGESTRUCT(UndoCommand) };
|
|
MESSAGESTRUCT(RedoCommand) };
|
|
MESSAGESTRUCT(MergeCommand) };
|
|
|
|
|
|
struct QueryMessage : public IMessage
|
|
{
|
|
Type GetType() const { return IMessage::Query; }
|
|
void Post(); // defined in ScenarioEditor.cpp
|
|
|
|
void* m_Semaphore; // for use by MessagePasser implementations (yay encapsulation)
|
|
};
|
|
|
|
|
|
#define QUERYSTRUCT(t) \
|
|
struct q##t : public QueryMessage { \
|
|
const char* GetName() const { return #t; } \
|
|
private: \
|
|
const q##t& operator=(const q##t&); \
|
|
public:
|
|
|
|
|
|
|
|
const bool MERGE = true;
|
|
const bool NOMERGE = false;
|
|
|
|
|
|
#define COMMANDDATASTRUCT(t) \
|
|
struct d##t { \
|
|
private: \
|
|
const d##t& operator=(const d##t&); \
|
|
public:
|
|
|
|
#define COMMANDSTRUCT(t, merge) \
|
|
struct m##t : public mWorldCommand, public d##t { \
|
|
m##t(const d##t& d) : d##t(d) {} \
|
|
const char* GetName() const { return #t; } \
|
|
virtual bool IsMergeable() const { return merge; } \
|
|
void* CloneData() const { return SHAREABLE_NEW(d##t, (*this)); } \
|
|
private: \
|
|
const m##t& operator=(const m##t&);\
|
|
}
|
|
|
|
|
|
|
|
#include <boost/preprocessor/tuple/elem.hpp>
|
|
#include <boost/preprocessor/punctuation/comma_if.hpp>
|
|
#include <boost/preprocessor/seq/for_each_i.hpp>
|
|
#include <boost/preprocessor/comparison/equal.hpp>
|
|
|
|
#define B_TYPE(elem) BOOST_PP_TUPLE_ELEM(2, 0, elem)
|
|
#define B_NAME(elem) BOOST_PP_TUPLE_ELEM(2, 1, elem)
|
|
#define B_CONSTRUCTORARGS(r, data, n, elem) BOOST_PP_COMMA_IF(n) B_TYPE(elem) BOOST_PP_CAT(B_NAME(elem),_)
|
|
#define B_CONSTRUCTORINIT(r, data, n, elem) BOOST_PP_COMMA_IF(n) B_NAME(elem)(BOOST_PP_CAT(B_NAME(elem),_))
|
|
#define B_CONSTMEMBERS(r, data, n, elem) const Shareable< B_TYPE(elem) > B_NAME(elem);
|
|
#define B_MEMBERS(r, data, n, elem) Shareable< B_TYPE(elem) > B_NAME(elem);
|
|
|
|
/* For each message type, generate something roughly like:
|
|
struct mBlah : public IMessage {
|
|
const char* GetName() const { return "Blah"; }
|
|
mBlah(int in0_, bool in1_) : in0(in0_), in1(in1_) {}
|
|
const Shareable<int> in0;
|
|
const Shareable<bool> in1;
|
|
}
|
|
*/
|
|
|
|
#define MESSAGE_WITH_INPUTS(name, vals) \
|
|
MESSAGESTRUCT(name) \
|
|
m##name( BOOST_PP_SEQ_FOR_EACH_I(B_CONSTRUCTORARGS, ~, vals) ) \
|
|
: BOOST_PP_SEQ_FOR_EACH_I(B_CONSTRUCTORINIT, ~, vals) {} \
|
|
BOOST_PP_SEQ_FOR_EACH_I(B_CONSTMEMBERS, ~, vals) \
|
|
}
|
|
|
|
#define MESSAGE_WITHOUT_INPUTS(name, vals) \
|
|
MESSAGESTRUCT(name) \
|
|
m##name() {} \
|
|
}
|
|
|
|
#define MESSAGE(name, vals) \
|
|
BOOST_PP_IIF( \
|
|
BOOST_PP_EQUAL(BOOST_PP_SEQ_SIZE((~)vals), 1), \
|
|
MESSAGE_WITHOUT_INPUTS, \
|
|
MESSAGE_WITH_INPUTS) \
|
|
(name, vals)
|
|
|
|
|
|
|
|
#define COMMAND(name, merge, vals) \
|
|
COMMANDDATASTRUCT(name) \
|
|
d##name( BOOST_PP_SEQ_FOR_EACH_I(B_CONSTRUCTORARGS, ~, vals) ) \
|
|
: BOOST_PP_SEQ_FOR_EACH_I(B_CONSTRUCTORINIT, ~, vals) {} \
|
|
BOOST_PP_SEQ_FOR_EACH_I(B_CONSTMEMBERS, ~, vals) \
|
|
}; \
|
|
COMMANDSTRUCT(name, merge)
|
|
|
|
|
|
// Need different syntax depending on whether there are some input values in the query:
|
|
|
|
#define QUERY_WITHOUT_INPUTS(name, in_vals, out_vals) \
|
|
QUERYSTRUCT(name) \
|
|
q##name() {} \
|
|
BOOST_PP_SEQ_FOR_EACH_I(B_MEMBERS, ~, out_vals) /* other members */ \
|
|
}
|
|
|
|
#define QUERY_WITH_INPUTS(name, in_vals, out_vals) \
|
|
QUERYSTRUCT(name) \
|
|
q##name( BOOST_PP_SEQ_FOR_EACH_I(B_CONSTRUCTORARGS, ~, in_vals) ) \
|
|
: BOOST_PP_SEQ_FOR_EACH_I(B_CONSTRUCTORINIT, ~, in_vals) {} \
|
|
BOOST_PP_SEQ_FOR_EACH_I(B_CONSTMEMBERS, ~, in_vals) \
|
|
BOOST_PP_SEQ_FOR_EACH_I(B_MEMBERS, ~, out_vals) \
|
|
}
|
|
|
|
#define QUERY(name, in_vals, out_vals) \
|
|
BOOST_PP_IIF( \
|
|
BOOST_PP_EQUAL(BOOST_PP_SEQ_SIZE((~)in_vals), 1), \
|
|
QUERY_WITHOUT_INPUTS, \
|
|
QUERY_WITH_INPUTS) \
|
|
(name, in_vals, out_vals)
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
#else // MESSAGESSETUP_NOTFIRST => clean up the mess
|
|
|
|
#undef MESSAGESTRUCT
|
|
#undef QUERYSTRUCT
|
|
#undef COMMANDDATASTRUCT
|
|
#undef COMMANDSTRUCT
|
|
#undef B_TYPE
|
|
#undef B_NAME
|
|
#undef B_CONSTRUCTORARGS
|
|
#undef B_CONSTRUCTORINIT
|
|
#undef B_CONSTMEMBERS
|
|
#undef B_MEMBERS
|
|
#undef MESSAGE
|
|
#undef COMMAND
|
|
#undef QUERY_WITHOUT_INPUTS
|
|
#undef QUERY_WITH_INPUTS
|
|
#undef QUERY
|
|
|
|
}
|
|
|
|
#endif
|