LCOV - code coverage report
Current view: top level - source/tools/atlas/GameInterface - MessagesSetup.h (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 0 7 0.0 %
Date: 2023-01-18 11:29:14 Functions: 0 13 0.0 %

          Line data    Source code
       1             : /* Copyright (C) 2019 Wildfire Games.
       2             :  * This file is part of 0 A.D.
       3             :  *
       4             :  * 0 A.D. is free software: you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation, either version 2 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * 0 A.D. is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : // Used by Messages.h, so that file stays relatively clean.
      19             : 
      20             : #ifndef MESSAGESSETUP_NOTFIRST
      21             : #define MESSAGESSETUP_NOTFIRST
      22             : 
      23             : #include "MessagePasser.h"
      24             : #include "SharedTypes.h"
      25             : #include "Shareable.h"
      26             : 
      27             : // Structures in this file are passed over the DLL boundary, so some
      28             : // carefulness and/or luck is required...
      29             : 
      30             : namespace AtlasMessage
      31             : {
      32             : 
      33             : struct IMessage
      34             : {
      35             :     virtual const char* GetName() const = 0;
      36             :     virtual ~IMessage() {}
      37             : 
      38             :     enum Type { Message, Query };
      39             :     virtual Type GetType() const = 0;
      40             : };
      41             : 
      42             : 
      43             : #define MESSAGESTRUCT(t) \
      44             :     struct m##t : public IMessage { \
      45             :         virtual const char* GetName() const { return #t; } \
      46             :         virtual Type GetType() const { return IMessage::Message; } \
      47             :     private: \
      48             :         const m##t& operator=(const m##t&); \
      49             :     public:
      50             : 
      51             : // Messages for doing/undoing/etc world-altering commands
      52             : 
      53           0 : MESSAGESTRUCT(WorldCommand)
      54             :     mWorldCommand() {}
      55             :     virtual void* CloneData() const = 0;
      56             :     virtual bool IsMergeable() const = 0;
      57             : };
      58           0 : MESSAGESTRUCT(DoCommand)
      59             :     mDoCommand(mWorldCommand* c) : name(c->GetName()), data(c->CloneData()) {}
      60             :     const Shareable<std::string> name;
      61             :     const Shareable<void*> data;
      62             :         // 'data' gets deallocated by ~cWhatever in the game thread
      63             : };
      64           0 : MESSAGESTRUCT(UndoCommand)  };
      65           0 : MESSAGESTRUCT(RedoCommand)  };
      66           0 : MESSAGESTRUCT(MergeCommand) };
      67             : 
      68             : 
      69           0 : struct QueryMessage : public IMessage
      70             : {
      71           0 :     Type GetType() const { return IMessage::Query; }
      72             :     void Post(); // defined in ScenarioEditor.cpp
      73             : 
      74             :     void* m_Semaphore; // for use by MessagePasser implementations (yay encapsulation)
      75             : };
      76             : 
      77             : 
      78             : #define QUERYSTRUCT(t) \
      79             :     struct q##t : public QueryMessage { \
      80             :         const char* GetName() const { return #t; } \
      81             :     private: \
      82             :         const q##t& operator=(const q##t&); \
      83             :     public:
      84             : 
      85             : 
      86             : 
      87             : const bool MERGE = true;
      88             : const bool NOMERGE = false;
      89             : 
      90             : 
      91             : #define COMMANDDATASTRUCT(t) \
      92             :     struct d##t { \
      93             :     private: \
      94             :         d##t& operator=(const d##t&) = delete; \
      95             :     public:
      96             : 
      97             : #define COMMANDSTRUCT(t, merge) \
      98             :     struct m##t : public mWorldCommand, public d##t { \
      99             :         m##t(const d##t& d) : d##t(d) {} \
     100             :         const char* GetName() const { return #t; } \
     101             :         virtual bool IsMergeable() const { return merge; } \
     102             :         void* CloneData() const { return SHAREABLE_NEW(d##t, (*this)); } \
     103             :     private: \
     104             :         const m##t& operator=(const m##t&);\
     105             :     }
     106             : 
     107             : 
     108             : 
     109             : #include <boost/preprocessor/tuple/elem.hpp>
     110             : #include <boost/preprocessor/punctuation/comma_if.hpp>
     111             : #include <boost/preprocessor/seq/for_each_i.hpp>
     112             : #include <boost/preprocessor/comparison/equal.hpp>
     113             : 
     114             : #define B_TYPE(elem) BOOST_PP_TUPLE_ELEM(2, 0, elem)
     115             : #define B_NAME(elem) BOOST_PP_TUPLE_ELEM(2, 1, elem)
     116             : #define B_CONSTRUCTORARGS(r, data, n, elem) BOOST_PP_COMMA_IF(n) B_TYPE(elem) BOOST_PP_CAT(B_NAME(elem),_)
     117             : #define B_CONSTRUCTORTYPES(r, data, n, elem) BOOST_PP_COMMA_IF(n) B_TYPE(elem)
     118             : #define B_CONSTRUCTORINIT(r, data, n, elem) BOOST_PP_COMMA_IF(n) B_NAME(elem)(BOOST_PP_CAT(B_NAME(elem),_))
     119             : #define B_CONSTMEMBERS(r, data, n, elem) const Shareable< B_TYPE(elem) > B_NAME(elem);
     120             : #define B_MEMBERS(r, data, n, elem) Shareable< B_TYPE(elem) > B_NAME(elem);
     121             : 
     122             : /* For each message type, generate something roughly like:
     123             :     struct mBlah : public IMessage {
     124             :         const char* GetName() const { return "Blah"; }
     125             :         mBlah(int in0_, bool in1_) : in0(in0_), in1(in1_) {}
     126             :         static mBlah* CtorType (int, bool) { return NULL; } // This doesn't do anything useful - it's just to make template-writing easier
     127             :         const Shareable<int> in0;
     128             :         const Shareable<bool> in1;
     129             :     }
     130             : */
     131             : 
     132             : #define MESSAGE_WITH_INPUTS(name, vals) \
     133             :     MESSAGESTRUCT(name) \
     134             :         m##name( BOOST_PP_SEQ_FOR_EACH_I(B_CONSTRUCTORARGS, ~, vals) ) \
     135             :             : BOOST_PP_SEQ_FOR_EACH_I(B_CONSTRUCTORINIT, ~, vals) {} \
     136             :         static m##name* CtorType( BOOST_PP_SEQ_FOR_EACH_I(B_CONSTRUCTORTYPES, ~, vals) ) { return NULL; } \
     137             :         BOOST_PP_SEQ_FOR_EACH_I(B_CONSTMEMBERS, ~, vals) \
     138             :     }
     139             : 
     140             : #define MESSAGE_WITHOUT_INPUTS(name, vals) \
     141             :     MESSAGESTRUCT(name) \
     142             :         m##name() {} \
     143             :         static m##name* CtorType() { return NULL; } \
     144             :     }
     145             : 
     146             : #define MESSAGE(name, vals) \
     147             :     BOOST_PP_IIF( \
     148             :         BOOST_PP_EQUAL(BOOST_PP_SEQ_SIZE((~)vals), 1), \
     149             :         MESSAGE_WITHOUT_INPUTS, \
     150             :         MESSAGE_WITH_INPUTS) \
     151             :     (name, vals)
     152             : 
     153             : 
     154             : 
     155             : #define COMMAND(name, merge, vals) \
     156             :     COMMANDDATASTRUCT(name) \
     157             :         d##name( BOOST_PP_SEQ_FOR_EACH_I(B_CONSTRUCTORARGS, ~, vals) ) \
     158             :             : BOOST_PP_SEQ_FOR_EACH_I(B_CONSTRUCTORINIT, ~, vals) {} \
     159             :         BOOST_PP_SEQ_FOR_EACH_I(B_CONSTMEMBERS, ~, vals) \
     160             :     }; \
     161             :     COMMANDSTRUCT(name, merge)
     162             : 
     163             : 
     164             : // Need different syntax depending on whether there are some input values in the query:
     165             : 
     166             : #define QUERY_WITHOUT_INPUTS(name, in_vals, out_vals) \
     167             :     QUERYSTRUCT(name) \
     168             :         q##name() {} \
     169             :         static q##name* CtorType() { return NULL; } \
     170             :         BOOST_PP_SEQ_FOR_EACH_I(B_MEMBERS, ~, out_vals) /* other members */ \
     171             :     }
     172             : 
     173             : #define QUERY_WITH_INPUTS(name, in_vals, out_vals) \
     174             :     QUERYSTRUCT(name) \
     175             :         q##name( BOOST_PP_SEQ_FOR_EACH_I(B_CONSTRUCTORARGS, ~, in_vals) ) \
     176             :             : BOOST_PP_SEQ_FOR_EACH_I(B_CONSTRUCTORINIT, ~, in_vals) {} \
     177             :         static q##name* CtorType( BOOST_PP_SEQ_FOR_EACH_I(B_CONSTRUCTORTYPES, ~, in_vals) ) { return NULL; } \
     178             :         BOOST_PP_SEQ_FOR_EACH_I(B_CONSTMEMBERS, ~, in_vals) \
     179             :         BOOST_PP_SEQ_FOR_EACH_I(B_MEMBERS, ~, out_vals) \
     180             :     }
     181             : 
     182             : #define QUERY(name, in_vals, out_vals) \
     183             :     BOOST_PP_IIF( \
     184             :         BOOST_PP_EQUAL(BOOST_PP_SEQ_SIZE((~)in_vals), 1), \
     185             :         QUERY_WITHOUT_INPUTS, \
     186             :         QUERY_WITH_INPUTS) \
     187             :     (name, in_vals, out_vals)
     188             : 
     189             : //////////////////////////////////////////////////////////////////////////
     190             : //////////////////////////////////////////////////////////////////////////
     191             : 
     192             : #else // MESSAGESSETUP_NOTFIRST => clean up the mess
     193             : 
     194             : #undef MESSAGESTRUCT
     195             : #undef QUERYSTRUCT
     196             : #undef COMMANDDATASTRUCT
     197             : #undef COMMANDSTRUCT
     198             : #undef B_TYPE
     199             : #undef B_NAME
     200             : #undef B_CONSTRUCTORARGS
     201             : #undef B_CONSTRUCTORTYPES
     202             : #undef B_CONSTRUCTORINIT
     203             : #undef B_CONSTMEMBERS
     204             : #undef B_MEMBERS
     205             : #undef MESSAGE
     206             : #undef COMMAND
     207             : #undef QUERY_WITHOUT_INPUTS
     208             : #undef QUERY_WITH_INPUTS
     209             : #undef QUERY
     210             : 
     211             : }
     212             : 
     213             : #endif

Generated by: LCOV version 1.13