journal.h

Engine/source/core/util/journal/journal.h

More...

Classes:

class

Journaling System.

class

Functor base classes.

class

Multiple argument function functor specialization.

Public Defines

define
Method(Arg1, Arg2)       static inline bool Writes Arg1 { \
          (_State == RecordState) { \
            _start();  Arg2; _finish(); \
            return true; \
         } \
         return false; \
      }

Journal a function's return value.

define
Method(Arg1, Arg2)       static inline bool Reads Arg1 { \
          (_State == PlayState) { \
            _start();  Arg2; _finish(); \
         return true; \
         } \
         return false; \
      }

Journal a function's return value.

define
Method(Arg1, Arg2, Arg3)       static  Call Arg1 { \
          (_Dispatching) \
            return; \
          (_State == PlayState) \
            return; \
          (_State == RecordState) { \
            Id  = _getFunctionId((VoidPtr)func,0); \
            (,"Journal: Function must be be declared before being called"); \
            _start(); \
             Arg2; \
            _finish(); \
         } \
         _Dispatching = true; \
         (*func) Arg3; \
         _Dispatching = false; \
         return; \
      }

Journal a function's return value.

define
Method(Arg1, Arg2, Arg3)       static  Call Arg1 { \
          (_Dispatching) \
            return; \
          (_State == PlayState) \
            return; \
          (_State == RecordState) { \
            Id  = _getFunctionId((VoidPtr)obj,(VoidMethod)method); \
            ( != 0,"Journal: Function must be be declared before being called"); \
            _start(); \
             Arg2; \
            _finish(); \
         } \
         _Dispatching = true; \
         (obj->*method) Arg3; \
         _Dispatching = false; \
         return; \
      }

Journal a function's return value.

define
Method(Func, Arg1, Arg2)       static typename <Func>::ValueType Result Arg1 { \
         typename <Func>::ValueType ; \
          (_Dispatching) \
            return; \
          (_State == PlayState) { \
            _start(); \
            (mFile,); \
            _finish(); \
            return ; \
         } \
         _Dispatching = true; \
          = (*func) Arg2; \
         _Dispatching = false; \
          (_State == RecordState) { \
            _start(); \
            (mFile,); \
            _finish(); \
         } \
         return ; \
      }

Journal a function's return value.

Detailed Description

Public Defines

Method(Arg1, Arg2)       static inline bool Writes Arg1 { \
          (_State == RecordState) { \
            _start();  Arg2; _finish(); \
            return true; \
         } \
         return false; \
      }

Journal a function's return value.

Read data from the journal.

Write data into the journal.

Journal a function call.

The return value of the function is stored into the journal and retrieved during playback. During playback the function is not executed.

Store the function id and all the function's arguments into the journal. On journal playback the function is executed with the retrieved arguments. The function must have been previously declared using the declareFunction() method.

Non-deterministic data can be stored into the journal for reading during playback. The function returns true if the journal is record mode.

Read non-deterministic data stored during the recording phase. The function returns true if the journal is play mode.

Method(Arg1, Arg2)       static inline bool Reads Arg1 { \
          (_State == PlayState) { \
            _start();  Arg2; _finish(); \
         return true; \
         } \
         return false; \
      }

Journal a function's return value.

Read data from the journal.

Write data into the journal.

Journal a function call.

The return value of the function is stored into the journal and retrieved during playback. During playback the function is not executed.

Store the function id and all the function's arguments into the journal. On journal playback the function is executed with the retrieved arguments. The function must have been previously declared using the declareFunction() method.

Non-deterministic data can be stored into the journal for reading during playback. The function returns true if the journal is record mode.

Read non-deterministic data stored during the recording phase. The function returns true if the journal is play mode.

Method(Arg1, Arg2, Arg3)       static  Call Arg1 { \
          (_Dispatching) \
            return; \
          (_State == PlayState) \
            return; \
          (_State == RecordState) { \
            Id  = _getFunctionId((VoidPtr)func,0); \
            (,"Journal: Function must be be declared before being called"); \
            _start(); \
             Arg2; \
            _finish(); \
         } \
         _Dispatching = true; \
         (*func) Arg3; \
         _Dispatching = false; \
         return; \
      }

Journal a function's return value.

Read data from the journal.

Write data into the journal.

Journal a function call.

The return value of the function is stored into the journal and retrieved during playback. During playback the function is not executed.

Store the function id and all the function's arguments into the journal. On journal playback the function is executed with the retrieved arguments. The function must have been previously declared using the declareFunction() method.

Non-deterministic data can be stored into the journal for reading during playback. The function returns true if the journal is record mode.

Read non-deterministic data stored during the recording phase. The function returns true if the journal is play mode.

Method(Arg1, Arg2, Arg3)       static  Call Arg1 { \
          (_Dispatching) \
            return; \
          (_State == PlayState) \
            return; \
          (_State == RecordState) { \
            Id  = _getFunctionId((VoidPtr)obj,(VoidMethod)method); \
            ( != 0,"Journal: Function must be be declared before being called"); \
            _start(); \
             Arg2; \
            _finish(); \
         } \
         _Dispatching = true; \
         (obj->*method) Arg3; \
         _Dispatching = false; \
         return; \
      }

Journal a function's return value.

Read data from the journal.

Write data into the journal.

Journal a function call.

The return value of the function is stored into the journal and retrieved during playback. During playback the function is not executed.

Store the function id and all the function's arguments into the journal. On journal playback the function is executed with the retrieved arguments. The function must have been previously declared using the declareFunction() method.

Non-deterministic data can be stored into the journal for reading during playback. The function returns true if the journal is record mode.

Read non-deterministic data stored during the recording phase. The function returns true if the journal is play mode.

Method(Func, Arg1, Arg2)       static typename <Func>::ValueType Result Arg1 { \
         typename <Func>::ValueType ; \
          (_Dispatching) \
            return; \
          (_State == PlayState) { \
            _start(); \
            (mFile,); \
            _finish(); \
            return ; \
         } \
         _Dispatching = true; \
          = (*func) Arg2; \
         _Dispatching = false; \
          (_State == RecordState) { \
            _start(); \
            (mFile,); \
            _finish(); \
         } \
         return ; \
      }

Journal a function's return value.

Read data from the journal.

Write data into the journal.

Journal a function call.

The return value of the function is stored into the journal and retrieved during playback. During playback the function is not executed.

Store the function id and all the function's arguments into the journal. On journal playback the function is executed with the retrieved arguments. The function must have been previously declared using the declareFunction() method.

Non-deterministic data can be stored into the journal for reading during playback. The function returns true if the journal is record mode.

Read non-deterministic data stored during the recording phase. The function returns true if the journal is play mode.

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#ifndef _UTIL_JOURNAL_JOURNAL_H_
 25#define _UTIL_JOURNAL_JOURNAL_H_ 
 26
 27#include "platform/platform.h"
 28#include "core/stream/stream.h"
 29#include "util/returnType.h"
 30#include "core/stream/ioHelper.h"
 31#include "core/idGenerator.h"
 32
 33/// Journaling System.
 34///
 35/// The journaling system is used to record external events and
 36/// non-deterministic values from an execution run in order that the
 37/// run may be re-played for debugging purposes.  The journaling
 38/// system is integrated into the platform library, though not all
 39/// platform calls are journaled.
 40///
 41/// File system calls are not journaled, so any modified files must
 42/// be reset to their original state before playback.  Only a single
 43/// journal can be recored or played back at a time.
 44///
 45/// For the journals to play back correctly, journal events cannot
 46/// be triggered during the processing of another event.
 47class Journal 
 48{
 49   Journal() {}
 50   ~<a href="/coding/class/classjournal/">Journal</a>();
 51
 52   static Journal smInstance;
 53
 54   typedef U32 Id;
 55   typedef void* VoidPtr;
 56   typedef void (Journal::*VoidMethod)();
 57
 58   /// Functor base classes
 59   struct Functor 
 60   {
 61      Functor() {}
 62      virtual ~Functor() {}
 63      virtual void read(Stream *s) = 0;
 64      virtual void dispatch() = 0;
 65   };
 66
 67   /// Multiple argument function functor specialization
 68   template <class T>
 69   struct FunctorDecl: public Functor  {
 70      typedef void(*FuncPtr)();
 71      FuncPtr ptr;
 72      FunctorDecl(FuncPtr p): ptr(p)   {}
 73      void read(Stream *file)   {}
 74      void dispatch()                  { (*ptr)(); }
 75   };
 76
 77   template <class A,class B,class C,class D,class E,class F,class G,class H,class I,class J,class K,class L,class M>
 78   struct FunctorDecl< void(*)(A,B,C,D,E,F,G,H,I,J,K,L,M) >: public Functor {
 79      typedef void(*FuncPtr)(A,B,C,D,E,F,G,H,I,J,K,L,M);
 80      FuncPtr ptr; A a; B b; C c; D d; E e; F f; G g; H h; I i; J j; K k; L l; M m;
 81      FunctorDecl(FuncPtr p): ptr(p)   {}
 82      void read(Stream *file)   { IOHelper::reads(file,a,b,c,d,e,f,g,h,i,j,k,l,m); }
 83      void dispatch()                  { (*ptr)(a,b,c,d,e,f,g,h,i,j,k,l,m); }
 84   };
 85
 86   template <class A,class B,class C,class D,class E,class F,class G,class H,class I,class J,class K,class L>
 87   struct FunctorDecl< void(*)(A,B,C,D,E,F,G,H,I,J,K,L) >: public Functor {
 88      typedef void(*FuncPtr)(A,B,C,D,E,F,G,H,I,J,K,L);
 89      FuncPtr ptr; A a; B b; C c; D d; E e; F f; G g; H h; I i; J j; K k; L l;
 90      FunctorDecl(FuncPtr p): ptr(p)   {}
 91      void read(Stream *file)   { IOHelper::reads(file,a,b,c,d,e,f,g,h,i,j,k,l); }
 92      void dispatch()                  { (*ptr)(a,b,c,d,e,f,g,h,i,j,k,l); }
 93   };
 94
 95   template <class A,class B,class C,class D,class E,class F,class G,class H,class I,class J,class K>
 96   struct FunctorDecl< void(*)(A,B,C,D,E,F,G,H,I,J,K) >: public Functor {
 97      typedef void(*FuncPtr)(A,B,C,D,E,F,G,H,I,J,K);
 98      FuncPtr ptr; A a; B b; C c; D d; E e; F f; G g; H h; I i; J j; K k;
 99      FunctorDecl(FuncPtr p): ptr(p)   {}
100      void read(Stream *file)   { IOHelper::reads(file,a,b,c,d,e,f,g,h,i,j,k); }
101      void dispatch()                  { (*ptr)(a,b,c,d,e,f,g,h,i,j,k); }
102   };
103
104   template <class A,class B,class C,class D,class E,class F,class G,class H,class I,class J>
105   struct FunctorDecl< void(*)(A,B,C,D,E,F,G,H,I,J) >: public Functor {
106      typedef void(*FuncPtr)(A,B,C,D,E,F,G,H,I,J);
107      FuncPtr ptr; A a; B b; C c; D d; E e; F f; G g; H h; I i; J j;
108      FunctorDecl(FuncPtr p): ptr(p)   {}
109      void read(Stream *file)   { IOHelper::reads(file,a,b,c,d,e,f,g,h,i,j); }
110      void dispatch()                  { (*ptr)(a,b,c,d,e,f,g,h,i,j); }
111   };
112
113   template <class A,class B,class C,class D,class E,class F,class G,class H,class I>
114   struct FunctorDecl< void(*)(A,B,C,D,E,F,G,H,I) >: public Functor {
115      typedef void(*FuncPtr)(A,B,C,D,E,F,G,H,I);
116      FuncPtr ptr; A a; B b; C c; D d; E e; F f; G g; H h; I i;
117      FunctorDecl(FuncPtr p): ptr(p)   {}
118      void read(Stream *file)   { IOHelper::reads(file,a,b,c,d,e,f,g,h,i); }
119      void dispatch()                  { (*ptr)(a,b,c,d,e,f,g,h,i); }
120   };
121
122   template <class A,class B,class C,class D,class E,class F,class G,class H>
123   struct FunctorDecl< void(*)(A,B,C,D,E,F,G,H) >: public Functor {
124      typedef void(*FuncPtr)(A,B,C,D,E,F,G,H);
125      FuncPtr ptr; A a; B b; C c; D d; E e; F f; G g; H h;
126      FunctorDecl(FuncPtr p): ptr(p)   {}
127      void read(Stream *file)   { IOHelper::reads(file,a,b,c,d,e,f,g,h); }
128      void dispatch()                  { (*ptr)(a,b,c,d,e,f,g,h); }
129   };
130
131   template <class A,class B,class C,class D,class E,class F,class G>
132   struct FunctorDecl< void(*)(A,B,C,D,E,F,G) >: public Functor {
133      typedef void(*FuncPtr)(A,B,C,D,E,F,G);
134      FuncPtr ptr; A a; B b; C c; D d; E e; F f; G g;
135      FunctorDecl(FuncPtr p): ptr(p)   {}
136      void read(Stream *file)   { IOHelper::reads(file,a,b,c,d,e,f,g); }
137      void dispatch()                  { (*ptr)(a,b,c,d,e,f,g); }
138   };
139
140   template <class A,class B,class C,class D,class E,class F>
141   struct FunctorDecl< void(*)(A,B,C,D,E,F) >: public Functor {
142      typedef void(*FuncPtr)(A,B,C,D,E,F);
143      FuncPtr ptr; A a; B b; C c; D d; E e; F f;
144      FunctorDecl(FuncPtr p): ptr(p)   {}
145      void read(Stream *file)   { IOHelper::reads(file,a,b,c,d,e,f); }
146      void dispatch()                  { (*ptr)(a,b,c,d,e,f); }
147   };
148
149   template <class A,class B,class C,class D,class E>
150   struct FunctorDecl< void(*)(A,B,C,D,E) >: public Functor {
151      typedef void(*FuncPtr)(A,B,C,D,E);
152      FuncPtr ptr; A a; B b; C c; D d; E e;
153      FunctorDecl(FuncPtr p): ptr(p)   {}
154      void read(Stream *file)   { IOHelper::reads(file,a,b,c,d,e); }
155      void dispatch()                  { (*ptr)(a,b,c,d,e); }
156   };
157
158   template <class A,class B,class C,class D>
159   struct FunctorDecl< void(*)(A,B,C,D) >: public Functor {
160      typedef void(*FuncPtr)(A,B,C,D);
161      FuncPtr ptr; A a; B b; C c; D d;
162      FunctorDecl(FuncPtr p): ptr(p)   {}
163      void read(Stream *file)   { IOHelper::reads(file,a,b,c,d); }
164      void dispatch()                  { (*ptr)(a,b,c,d); }
165   };
166
167   template <class A,class B,class C>
168   struct FunctorDecl< void(*)(A,B,C) >: public Functor {
169      typedef void(*FuncPtr)(A,B,C);
170      FuncPtr ptr; A a; B b; C c;
171      FunctorDecl(FuncPtr p): ptr(p)   {}
172      void read(Stream *file)   { IOHelper::reads(file,a,b,c); }
173      void dispatch()                  { (*ptr)(a,b,c); }
174   };
175
176   template <class A,class B>
177   struct FunctorDecl< void(*)(A,B) >: public Functor {
178      typedef void(*FuncPtr)(A,B);
179      FuncPtr ptr; A a; B b;
180      FunctorDecl(FuncPtr p): ptr(p)   {}
181      void read(Stream *file)   { IOHelper::reads(file,a,b); }
182      void dispatch()                  { (*ptr)(a,b); }
183   };
184
185   template <class A>
186   struct FunctorDecl< void(*)(A) >: public Functor {
187      typedef void(*FuncPtr)(A);
188      FuncPtr ptr; A a;
189      FunctorDecl(FuncPtr p): ptr(p)   {}
190      void read(Stream *file)   { IOHelper::reads(file,a); }
191      void dispatch()                  { (*ptr)(a); }
192   };
193
194   // Multiple argument object member function functor specialization
195   template <class T,class U>
196   struct MethodDecl: public Functor  {
197      typedef T ObjPtr;
198      typedef U MethodPtr;
199      ObjPtr obj; MethodPtr method;
200      MethodDecl(ObjPtr o,MethodPtr p): obj(o), method(p)   {}
201      void read(Stream *file)   {}
202      void dispatch()                  { (obj->*method)(); }
203   };
204
205   template <class T,class A,class B,class C,class D,class E,class F,class G,class H,class I,class J,class K,class L,class M>
206   struct MethodDecl<T*, void(T::*)(A,B,C,D,E,F,G,H,I,J,K,L,M) >: public Functor {
207      typedef T* ObjPtr;
208      typedef void(T::*MethodPtr)(A,B,C,D,E,F,G,H,I,J,K,L,M);
209      ObjPtr obj; MethodPtr method; A a; B b; C c; D d; E e; F f; G g; H h; I i; J j; K k; L l; M m;
210      MethodDecl(ObjPtr o,MethodPtr p): obj(o), method(p)   {}
211      void read(Stream *file)   { IOHelper::reads(file,a,b,c,d,e,f,g,h,i,j,k,l,m); }
212      void dispatch()                  { (obj->*method)(a,b,c,d,e,f,g,h,i,j,k,l,m); }
213   };
214
215   template <class T,class A,class B,class C,class D,class E,class F,class G,class H,class I,class J,class K,class L>
216   struct MethodDecl<T*, void(T::*)(A,B,C,D,E,F,G,H,I,J,K,L) >: public Functor {
217      typedef T* ObjPtr;
218      typedef void(T::*MethodPtr)(A,B,C,D,E,F,G,H,I,J,K,L);
219      ObjPtr obj; MethodPtr method; A a; B b; C c; D d; E e; F f; G g; H h; I i; J j; K k; L l;
220      MethodDecl(ObjPtr o,MethodPtr p): obj(o), method(p)   {}
221      void read(Stream *file)   { IOHelper::reads(file,a,b,c,d,e,f,g,h,i,j,k,l); }
222      void dispatch()                  { (obj->*method)(a,b,c,d,e,f,g,h,i,j,k,l); }
223   };
224
225   template <class T,class A,class B,class C,class D,class E,class F,class G,class H,class I,class J,class K>
226   struct MethodDecl<T*, void(T::*)(A,B,C,D,E,F,G,H,I,J,K) >: public Functor {
227      typedef T* ObjPtr;
228      typedef void(T::*MethodPtr)(A,B,C,D,E,F,G,H,I,J,K);
229      ObjPtr obj; MethodPtr method; A a; B b; C c; D d; E e; F f; G g; H h; I i; J j; K k;
230      MethodDecl(ObjPtr o,MethodPtr p): obj(o), method(p)   {}
231      void read(Stream *file)   { IOHelper::reads(file,a,b,c,d,e,f,g,h,i,j,k); }
232      void dispatch()                  { (obj->*method)(a,b,c,d,e,f,g,h,i,j,k); }
233   };
234
235   template <class T,class A,class B,class C,class D,class E,class F,class G,class H,class I,class J>
236   struct MethodDecl<T*, void(T::*)(A,B,C,D,E,F,G,H,I,J) >: public Functor {
237      typedef T* ObjPtr;
238      typedef void(T::*MethodPtr)(A,B,C,D,E,F,G,H,I,J);
239      ObjPtr obj; MethodPtr method; A a; B b; C c; D d; E e; F f; G g; H h; I i; J j;
240      MethodDecl(ObjPtr o,MethodPtr p): obj(o), method(p)   {}
241      void read(Stream *file)   { IOHelper::reads(file,a,b,c,d,e,f,g,h,i,j); }
242      void dispatch()                  { (obj->*method)(a,b,c,d,e,f,g,h,i,j); }
243   };
244
245   template <class T,class A,class B,class C,class D,class E,class F,class G,class H,class I>
246   struct MethodDecl<T*, void(T::*)(A,B,C,D,E,F,G,H,I) >: public Functor {
247      typedef T* ObjPtr;
248      typedef void(T::*MethodPtr)(A,B,C,D,E,F,G,H,I);
249      ObjPtr obj; MethodPtr method; A a; B b; C c; D d; E e; F f; G g; H h; I i;
250      MethodDecl(ObjPtr o,MethodPtr p): obj(o), method(p)   {}
251      void read(Stream *file)   { IOHelper::reads(file,a,b,c,d,e,f,g,h,i); }
252      void dispatch()                  { (obj->*method)(a,b,c,d,e,f,g,h,i); }
253   };
254
255   template <class T,class A,class B,class C,class D,class E,class F,class G,class H>
256   struct MethodDecl<T*, void(T::*)(A,B,C,D,E,F,G,H) >: public Functor {
257      typedef T* ObjPtr;
258      typedef void(T::*MethodPtr)(A,B,C,D,E,F,G,H);
259      ObjPtr obj; MethodPtr method; A a; B b; C c; D d; E e; F f; G g; H h;
260      MethodDecl(ObjPtr o,MethodPtr p): obj(o), method(p)   {}
261      void read(Stream *file)   { IOHelper::reads(file,a,b,c,d,e,f,g,h); }
262      void dispatch()                  { (obj->*method)(a,b,c,d,e,f,g,h); }
263   };
264
265   template <class T,class A,class B,class C,class D,class E,class F,class G>
266   struct MethodDecl<T*, void(T::*)(A,B,C,D,E,F,G) >: public Functor {
267      typedef T* ObjPtr;
268      typedef void(T::*MethodPtr)(A,B,C,D,E,F,G);
269      ObjPtr obj; MethodPtr method; A a; B b; C c; D d; E e; F f; G g;
270      MethodDecl(ObjPtr o,MethodPtr p): obj(o), method(p)   {}
271      void read(Stream *file)   { IOHelper::reads(file,a,b,c,d,e,f,g); }
272      void dispatch()                  { (obj->*method)(a,b,c,d,e,f,g); }
273   };
274
275   template <class T,class A,class B,class C,class D,class E,class F>
276   struct MethodDecl<T*, void(T::*)(A,B,C,D,E,F) >: public Functor {
277      typedef T* ObjPtr;
278      typedef void(T::*MethodPtr)(A,B,C,D,E,F);
279      ObjPtr obj; MethodPtr method; A a; B b; C c; D d; E e; F f;
280      MethodDecl(ObjPtr o,MethodPtr p): obj(o), method(p)   {}
281      void read(Stream *file)   { IOHelper::reads(file,a,b,c,d,e,f); }
282      void dispatch()                  { (obj->*method)(a,b,c,d,e,f); }
283   };
284
285   template <class T,class A,class B,class C,class D,class E>
286   struct MethodDecl<T*, void(T::*)(A,B,C,D,E) >: public Functor {
287      typedef T* ObjPtr;
288      typedef void(T::*MethodPtr)(A,B,C,D,E);
289      ObjPtr obj; MethodPtr method; A a; B b; C c; D d; E e;
290      MethodDecl(ObjPtr o,MethodPtr p): obj(o), method(p)   {}
291      void read(Stream *file)   { IOHelper::reads(file,a,b,c,d,e); }
292      void dispatch()                  { (obj->*method)(a,b,c,d,e); }
293   };
294
295   template <class T,class A,class B,class C,class D>
296   struct MethodDecl<T*, void(T::*)(A,B,C,D) >: public Functor {
297      typedef T* ObjPtr;
298      typedef void(T::*MethodPtr)(A,B,C,D);
299      ObjPtr obj; MethodPtr method; A a; B b; C c; D d;
300      MethodDecl(ObjPtr o,MethodPtr p): obj(o), method(p)   {}
301      void read(Stream *file)   { IOHelper::reads(file,a,b,c,d); }
302      void dispatch()                  { (obj->*method)(a,b,c,d); }
303   };
304
305   template <class T,class A,class B,class C>
306   struct MethodDecl<T*, void(T::*)(A,B,C) >: public Functor {
307      typedef T* ObjPtr;
308      typedef void(T::*MethodPtr)(A,B,C);
309      ObjPtr obj; MethodPtr method; A a; B b; C c;
310      MethodDecl(ObjPtr o,MethodPtr p): obj(o), method(p)   {}
311      void read(Stream *file)   { IOHelper::reads(file,a,b,c); }
312      void dispatch()                  { (obj->*method)(a,b,c); }
313   };
314
315   template <class T,class A,class B>
316   struct MethodDecl<T*, void(T::*)(A,B) >: public Functor {
317      typedef T* ObjPtr;
318      typedef void(T::*MethodPtr)(A,B);
319      ObjPtr obj; MethodPtr method; A a; B b;
320      MethodDecl(ObjPtr o,MethodPtr p): obj(o), method(p)   {}
321      void read(Stream *file)   { IOHelper::reads(file,a,b); }
322      void dispatch()                  { (obj->*method)(a,b); }
323   };
324
325   template <class T,class A>
326   struct MethodDecl<T*, void(T::*)(A) >: public Functor {
327      typedef T* ObjPtr;
328      typedef void(T::*MethodPtr)(A);
329      ObjPtr obj; MethodPtr method; A a;
330      MethodDecl(ObjPtr o,MethodPtr p): obj(o), method(p)   {}
331      void read(Stream *file)   { IOHelper::reads(file,a); }
332      void dispatch()                  { (obj->*method)(a); }
333   };
334
335   // Function declarations
336   struct FuncDecl {
337      FuncDecl* next;
338      Id id;
339      FuncDecl() :next(NULL), id(0){}
340      virtual ~FuncDecl() {}
341      virtual bool match(VoidPtr,VoidMethod) const = 0;
342      virtual Functor* create() const = 0;
343   };
344
345   template<typename T>
346   struct FuncRep: public FuncDecl {
347      typename T::FuncPtr function;
348      virtual bool match(VoidPtr ptr,VoidMethod) const {
349         return function == (typename T::FuncPtr)ptr;
350      }
351      T* create() const { return new T(function); };
352   };
353
354   template<typename T>
355   struct MethodRep: public FuncDecl {
356      typename T::ObjPtr obj;
357      typename T::MethodPtr method;
358      virtual bool match(VoidPtr ptr,VoidMethod func) const {
359         return obj == (typename T::ObjPtr)ptr && method == (typename T::MethodPtr)func;
360      }
361      T* create() const { return new T(obj,method); };
362   };
363
364   static FuncDecl* _FunctionList;
365
366   static inline IdGenerator &idPool()
367   {
368      static IdGenerator _IdPool(1, 65535);
369      return _IdPool;
370   }
371
372   static U32 _Count;
373   static Stream *mFile;
374   static enum Mode {
375      StopState, PlayState, RecordState, DisabledState
376   } _State;
377   static bool _Dispatching;
378
379   static Functor* _create(Id id);
380   static void _start();
381   static void _finish();
382   static Id _getFunctionId(VoidPtr ptr,VoidMethod method);
383   static void _removeFunctionId(VoidPtr ptr,VoidMethod method);
384
385public:
386   static void Record(const char * file);
387   static void Play(const char * file);
388   static bool PlayNext();
389   static void Stop();
390   static void Disable();
391
392   /// Returns true if in recording mode.
393   static inline bool IsRecording() {
394      return _State == RecordState;
395   }
396
397   /// Returns true if in play mode.
398   static inline bool IsPlaying() {
399      return _State == PlayState;
400   }
401
402   /// Returns true if a function is being dispatched
403   static inline bool IsDispatching() {
404      return _Dispatching;
405   }
406
407   template<typename T>
408   static void Read(T *v)
409   {
410      AssertFatal(IsPlaying(), "Journal::Read - not playing right now.");
411      bool r = mFile->read(v);
412      AssertFatal(r, "Journal::Read - failed to read!");
413   }
414
415   static bool Read(U32 size, void *buffer)
416   {
417      AssertFatal(IsPlaying(), "Journal::Read - not playing right now.");
418      bool r = mFile->read(size, buffer);
419      AssertFatal(r, "Journal::Read - failed to read!");
420      return r;
421   }
422
423   static void ReadString(char str[256])
424   {
425      AssertFatal(IsPlaying(), "Journal::ReadString - not playing right now.");
426      mFile->readString(str);
427   }
428
429   template<typename T>
430   static void Write(const T &v)
431   {
432      AssertFatal(IsRecording(), "Journal::Write - not recording right now.");
433      bool r = mFile->write(v);
434      AssertFatal(r, "Journal::Write - failed to write!");
435   }
436
437   static bool Write(U32 size, void *buffer)
438   {
439      AssertFatal(IsRecording(), "Journal::Write - not recording right now.");
440      bool r = mFile->write(size, buffer);
441      AssertFatal(r, "Journal::Write - failed to write!");
442      return r;   
443   }
444
445   static void WriteString(const char str[256])
446   {
447      AssertFatal(IsRecording(), "Journal::WriteString - not recording right now.");
448      mFile->writeString(str);
449   }
450
451   /// Register a function with the journalling system.
452   template<typename T>
453   static void DeclareFunction(T func) {
454      if (!_getFunctionId((VoidPtr)func,0)) {
455         FuncRep<FunctorDecl<T> >* decl = new FuncRep<FunctorDecl<T> >;
456         decl->function = func;
457         decl->id = idPool().alloc();
458         decl->next = _FunctionList;
459         _FunctionList = decl;
460      }
461   }
462
463   template<typename T, typename U>
464   static void DeclareFunction(T obj, U method)
465   {
466      if (!_getFunctionId((VoidPtr)obj,(VoidMethod)method)) {
467         MethodRep<MethodDecl<T,U> >* decl = new MethodRep<MethodDecl<T,U> >;
468         decl->obj = obj;
469         decl->method = method;
470         decl->id = idPool().alloc();
471         decl->next = _FunctionList;
472         _FunctionList = decl;
473      }
474   }
475
476   template<typename T, typename U>
477   static void RemoveFunction(T obj, U method)
478   {
479      _removeFunctionId((VoidPtr)obj,(VoidMethod)method);
480   }
481
482   /// Journal a function's return value. The return value of the
483   /// function is stored into the journal and retrieved during
484   /// playback. During playback the function is not executed.
485   #define Method(Func,Arg1,Arg2) \
486      static typename ReturnType<Func>::ValueType Result Arg1 { \
487         typename ReturnType<Func>::ValueType value; \
488         if (_Dispatching) \
489            return; \
490         if (_State == PlayState) { \
491            _start(); \
492            IOHelper::reads(mFile,value); \
493            _finish(); \
494            return value; \
495         } \
496         _Dispatching = true; \
497         value = (*func) Arg2; \
498         _Dispatching = false; \
499         if (_State == RecordState) { \
500            _start(); \
501            IOHelper::writes(mFile,value); \
502            _finish(); \
503         } \
504         return value; \
505      }
506
507   template<class Func,class A,class B,class C,class D,class E,class F, class G, class H, class I, class J, class K, class L, class M>
508      Method(Func,(Func func,A a,B b,C c,D d,E e,F f, G g, H h, I i, J j, K k, L l, M m),(a,b,c,d,e,f,g,h,i,j,k,l,m))
509   template<class Func,class A,class B,class C,class D,class E,class F, class G, class H, class I, class J, class K, class L>
510      Method(Func,(Func func,A a,B b,C c,D d,E e,F f, G g, H h, I i, J j, K k, L l),(a,b,c,d,e,f,g,h,i,j,k,l))
511   template<class Func,class A,class B,class C,class D,class E,class F, class G, class H, class I, class J, class K>
512      Method(Func,(Func func,A a,B b,C c,D d,E e,F f, G g, H h, I i, J j, K k),(a,b,c,d,e,f,g,h,i,j,k))
513   template<class Func,class A,class B,class C,class D,class E,class F, class G, class H, class I, class J>
514      Method(Func,(Func func,A a,B b,C c,D d,E e,F f, G g, H h, I i, J j),(a,b,c,d,e,f,g,h,i,j))
515   template<class Func,class A,class B,class C,class D,class E,class F, class G, class H, class I>
516      Method(Func,(Func func,A a,B b,C c,D d,E e,F f, G g, H h, I i),(a,b,c,d,e,f,g,h,i))
517   template<class Func,class A,class B,class C,class D,class E,class F, class G, class H>
518      Method(Func,(Func func,A a,B b,C c,D d,E e,F f, G g, H h),(a,b,c,d,e,f,g,h))
519   template<class Func,class A,class B,class C,class D,class E,class F, class G>
520      Method(Func,(Func func,A a,B b,C c,D d,E e,F f, G g),(a,b,c,d,e,f,g))
521   template<class Func,class A,class B,class C,class D,class E,class F>
522      Method(Func,(Func func,A a,B b,C c,D d,E e,F f),(a,b,c,d,e,f))
523   template<class Func,class A,class B,class C,class D,class E>
524      Method(Func,(Func func,A a,B b,C c,D d,E e),(a,b,c,d,e))
525   template<class Func,class A,class B,class C,class D>
526      Method(Func,(Func func,A a,B b,C c,D d),(a,b,c,d))
527   template<class Func,class A,class B,class C>
528      Method(Func,(Func func,A a,B b,C c),(a,b,c))
529   template<class Func,class A,class B>
530      Method(Func,(Func func,A a,B b),(a,b))
531   template<class Func,class A>
532      Method(Func,(Func func,A a),(a))
533   template<class Func>
534      Method(Func,(Func func),())
535   #undef Method
536
537   /// Journal a function call. Store the function id and all the
538   /// function's arguments into the journal. On journal playback the
539   /// function is executed with the retrieved arguments. The function
540   /// must have been previously declared using the declareFunction()
541   /// method.
542   #define Method(Arg1,Arg2,Arg3) \
543      static void Call Arg1 { \
544         if (_Dispatching) \
545            return; \
546         if (_State == PlayState) \
547            return; \
548         if (_State == RecordState) { \
549            Id id = _getFunctionId((VoidPtr)func,0); \
550            AssertFatal(id,"Journal: Function must be be declared before being called"); \
551            _start(); \
552            IOHelper::writes Arg2; \
553            _finish(); \
554         } \
555         _Dispatching = true; \
556         (*func) Arg3; \
557         _Dispatching = false; \
558         return; \
559      }
560
561   template<class Func,class A,class B,class C,class D,class E, class F, class G, class H, class I, class J, class K, class L, class M>
562      Method((Func func,A a,B b,C c,D d,E e,F f,G g,H h,I i,J j,K k,L l,M m),(mFile,id,a,b,c,d,e,f,g,h,i,j,k,l,m),(a,b,c,d,e,f,g,h,i,j,k,l,m))
563   template<class Func,class A,class B,class C,class D,class E, class F, class G, class H, class I, class J, class K, class L>
564      Method((Func func,A a,B b,C c,D d,E e,F f,G g,H h,I i,J j,K k,L l),(mFile,id,a,b,c,d,e,f,g,h,i,j,k,l),(a,b,c,d,e,f,g,h,i,j,k,l))
565   template<class Func,class A,class B,class C,class D,class E, class F, class G, class H, class I, class J, class K>
566      Method((Func func,A a,B b,C c,D d,E e,F f,G g,H h,I i,J j,K k),(mFile,id,a,b,c,d,e,f,g,h,i,j,k),(a,b,c,d,e,f,g,h,i,j,k))
567   template<class Func,class A,class B,class C,class D,class E, class F, class G, class H, class I, class J>
568      Method((Func func,A a,B b,C c,D d,E e,F f,G g,H h,I i,J j),(mFile,id,a,b,c,d,e,f,g,h,i,j),(a,b,c,d,e,f,g,h,i,j))
569   template<class Func,class A,class B,class C,class D,class E, class F, class G, class H, class I>
570      Method((Func func,A a,B b,C c,D d,E e,F f,G g,H h,I i),(mFile,id,a,b,c,d,e,f,g,h,i),(a,b,c,d,e,f,g,h,i))
571   template<class Func,class A,class B,class C,class D,class E, class F, class G, class H>
572      Method((Func func,A a,B b,C c,D d,E e,F f,G g,H h),(mFile,id,a,b,c,d,e,f,g,h),(a,b,c,d,e,f,g,h))
573   template<class Func,class A,class B,class C,class D,class E, class F, class G>
574      Method((Func func,A a,B b,C c,D d,E e,F f,G g),(mFile,id,a,b,c,d,e,f,g),(a,b,c,d,e,f,g))
575   template<class Func,class A,class B,class C,class D,class E, class F>
576      Method((Func func,A a,B b,C c,D d,E e,F f),(mFile,id,a,b,c,d,e,f),(a,b,c,d,e,f))
577   template<class Func,class A,class B,class C,class D,class E>
578      Method((Func func,A a,B b,C c,D d,E e),(mFile,id,a,b,c,d,e),(a,b,c,d,e))
579   template<class Func,class A,class B,class C,class D>
580      Method((Func func,A a,B b,C c,D d),(mFile,id,a,b,c,d),(a,b,c,d))
581   template<class Func,class A,class B,class C>
582      Method((Func func,A a,B b,C c),(mFile,id,a,b,c),(a,b,c))
583   template<class Func,class A,class B>
584      Method((Func func,A a,B b),(mFile,id,a,b),(a,b))
585   template<class Func,class A>
586      Method((Func func,A a),(mFile,id,a),(a))
587   template<class Func>
588      Method((Func func),(mFile,id),())
589   #undef Method
590
591   #define Method(Arg1,Arg2,Arg3) \
592      static void Call Arg1 { \
593         if (_Dispatching) \
594            return; \
595         if (_State == PlayState) \
596            return; \
597         if (_State == RecordState) { \
598            Id id = _getFunctionId((VoidPtr)obj,(VoidMethod)method); \
599            AssertFatal(id != 0,"Journal: Function must be be declared before being called"); \
600            _start(); \
601            IOHelper::writes Arg2; \
602            _finish(); \
603         } \
604         _Dispatching = true; \
605         (obj->*method) Arg3; \
606         _Dispatching = false; \
607         return; \
608      }
609
610
611   template<class Obj,class A,class B,class C,class D,class E,class F,class G,class H,class I,class J,class K,class L,class M>
612      Method((Obj* obj,void (Obj::*method)(A,B,C,D,E,F,G,H,I,J,K,L,M),A a,B b,C c,D d,E e,F f,G g,H h,I i,J j,K k,L l,M m),(mFile,id,a,b,c,d,e,f,g,h,i,j,k,l,m),(a,b,c,d,e,f,g,h,i,j,k,l,m))
613   template<class Obj,class A,class B,class C,class D,class E,class F,class G,class H,class I,class J,class K,class L>
614      Method((Obj* obj,void (Obj::*method)(A,B,C,D,E,F,G,H,I,J,K,L),A a,B b,C c,D d,E e,F f,G g,H h,I i,J j,K k,L l),(mFile,id,a,b,c,d,e,f,g,h,i,j,k,l),(a,b,c,d,e,f,g,h,i,j,k,l))
615   template<class Obj,class A,class B,class C,class D,class E,class F,class G,class H,class I,class J,class K>
616      Method((Obj* obj,void (Obj::*method)(A,B,C,D,E,F,G,H,I,J,K),A a,B b,C c,D d,E e,F f,G g,H h,I i,J j,K k),(mFile,id,a,b,c,d,e,f,g,h,i,j,k),(a,b,c,d,e,f,g,h,i,j,k))
617   template<class Obj,class A,class B,class C,class D,class E,class F,class G,class H,class I,class J>
618      Method((Obj* obj,void (Obj::*method)(A,B,C,D,E,F,G,H,I,J),A a,B b,C c,D d,E e,F f,G g,H h,I i,J j),(mFile,id,a,b,c,d,e,f,g,h,i,j),(a,b,c,d,e,f,g,h,i,j))
619   template<class Obj,class A,class B,class C,class D,class E,class F,class G,class H,class I>
620      Method((Obj* obj,void (Obj::*method)(A,B,C,D,E,F,G,H,I),A a,B b,C c,D d,E e,F f,G g,H h,I i),(mFile,id,a,b,c,d,e,f,g,h,i),(a,b,c,d,e,f,g,h,i))
621   template<class Obj,class A,class B,class C,class D,class E,class F,class G,class H>
622      Method((Obj* obj,void (Obj::*method)(A,B,C,D,E,F,G,H),A a,B b,C c,D d,E e,F f,G g,H h),(mFile,id,a,b,c,d,e,f,g,h),(a,b,c,d,e,f,g,h))
623   template<class Obj,class A,class B,class C,class D,class E,class F,class G>
624      Method((Obj* obj,void (Obj::*method)(A,B,C,D,E,F,G),A a,B b,C c,D d,E e,F f,G g),(mFile,id,a,b,c,d,e,f,g),(a,b,c,d,e,f,g))
625   template<class Obj,class A,class B,class C,class D,class E,class F>
626      Method((Obj* obj,void (Obj::*method)(A,B,C,D,E,F),A a,B b,C c,D d,E e,F f),(mFile,id,a,b,c,d,e,f),(a,b,c,d,e,f))
627   template<class Obj,class A,class B,class C,class D,class E>
628      Method((Obj* obj,void (Obj::*method)(A,B,C,D,E),A a,B b,C c,D d,E e),(mFile,id,a,b,c,d,e),(a,b,c,d,e))
629   template<class Obj,class A,class B,class C,class D>
630      Method((Obj* obj,void (Obj::*method)(A,B,C,D),A a,B b,C c,D d),(mFile,id,a,b,c,d),(a,b,c,d))
631   template<class Obj,class A,class B,class C>
632      Method((Obj* obj,void (Obj::*method)(A,B,C),A a,B b,C c),(mFile,id,a,b,c),(a,b,c))
633   template<class Obj,class A,class B>
634      Method((Obj* obj,void (Obj::*method)(A,B),A a,B b),(mFile,id,a,b),(a,b))
635   template<class Obj,class A>
636      Method((Obj* obj,void (Obj::*method)(A),A a),(mFile,id,a),(a))
637   template<class Obj>
638      Method((Obj* obj,void (Obj::*method)()),(mFile,id),())
639
640   #undef Method
641
642   /// Write data into the journal. Non-deterministic data can be stored
643   /// into the journal for reading during playback. The function
644   /// returns true if the journal is record mode.
645   #define Method(Arg1,Arg2) \
646      static inline bool Writes Arg1 { \
647         if (_State == RecordState) { \
648            _start(); IOHelper::writes Arg2; _finish(); \
649            return true; \
650         } \
651         return false; \
652      }
653
654   template<class A,class B,class C,class D,class E, class F, class G, class H,class I,class J,class K,class L,class M>
655      Method((A& a,B& b,C& c,D& d,E& e, F& f, G& g, H& h, I& i,J& j,K& k,L& l,M& m),(mFile,a,b,c,d,e,f,g,h,i,j,k,l,m));
656   template<class A,class B,class C,class D,class E, class F, class G, class H,class I,class J,class K,class L>
657      Method((A& a,B& b,C& c,D& d,E& e, F& f, G& g, H& h, I& i,J& j,K& k,L& l),(mFile,a,b,c,d,e,f,g,h,i,j,k,l));
658   template<class A,class B,class C,class D,class E, class F, class G, class H,class I,class J,class K>
659      Method((A& a,B& b,C& c,D& d,E& e, F& f, G& g, H& h, I& i,J& j,K& k),(mFile,a,b,c,d,e,f,g,h,i,j,k));
660   template<class A,class B,class C,class D,class E, class F, class G, class H,class I,class J>
661      Method((A& a,B& b,C& c,D& d,E& e, F& f, G& g, H& h, I& i,J& j),(mFile,a,b,c,d,e,f,g,h,i,j));
662   template<class A,class B,class C,class D,class E, class F, class G, class H,class I>
663      Method((A& a,B& b,C& c,D& d,E& e, F& f, G& g, H& h, I& i),(mFile,a,b,c,d,e,f,g,h,i));
664   template<class A,class B,class C,class D,class E, class F, class G, class H>
665      Method((A& a,B& b,C& c,D& d,E& e, F& f, G& g, H& h),(mFile,a,b,c,d,e,f,g,h));
666   template<class A,class B,class C,class D,class E, class F, class G>
667      Method((A& a,B& b,C& c,D& d,E& e, F& f, G& g),(mFile,a,b,c,d,e,f,g));
668   template<class A,class B,class C,class D,class E, class F>
669      Method((A& a,B& b,C& c,D& d,E& e, F& f),(mFile,a,b,c,d,e,f));
670   template<class A,class B,class C,class D,class E>
671      Method((A& a,B& b,C& c,D& d,E& e),(mFile,a,b,c,d,e));
672   template<class A,class B,class C,class D>
673      Method((A& a,B& b,C& c,D& d),(mFile,a,b,c,d));
674   template<class A,class B,class C>
675      Method((A& a,B& b,C& c),(mFile,a,b,c));
676   template<class A,class B>
677      Method((A& a,B& b),(mFile,a,b));
678   template<class A>
679      Method((A& a),(mFile,a));
680   #undef Method
681
682   /// Read data from the journal. Read non-deterministic data stored
683   /// during the recording phase. The function returns true if the
684   /// journal is play mode.
685   #define Method(Arg1,Arg2) \
686      static inline bool Reads Arg1 { \
687         if (_State == PlayState) { \
688            _start(); IOHelper::reads Arg2; _finish(); \
689         return true; \
690         } \
691         return false; \
692      }
693
694   template<class A,class B,class C,class D,class E, class F, class G, class H, class I, class J, class K,class L,class M>
695      Method((A& a,B& b,C& c,D& d,E& e,F& f,G& g, H& h, I& i, J& j, K& k, L& l, M& m),(mFile,a,b,c,d,e,f,g,h,i,j,k,l,m));
696   template<class A,class B,class C,class D,class E, class F, class G, class H, class I, class J, class K,class L>
697      Method((A& a,B& b,C& c,D& d,E& e,F& f,G& g, H& h, I& i, J& j, K& k, L& l),(mFile,a,b,c,d,e,f,g,h,i,j,k,l));
698   template<class A,class B,class C,class D,class E, class F, class G, class H, class I, class J, class K>
699      Method((A& a,B& b,C& c,D& d,E& e,F& f,G& g, H& h, I& i, J& j, K& k),(mFile,a,b,c,d,e,f,g,h,i,j,k));
700   template<class A,class B,class C,class D,class E, class F, class G, class H, class I, class J>
701      Method((A& a,B& b,C& c,D& d,E& e,F& f,G& g, H& h, I& i, J& j),(mFile,a,b,c,d,e,f,g,h,i,j));
702   template<class A,class B,class C,class D,class E, class F, class G, class H, class I>
703      Method((A& a,B& b,C& c,D& d,E& e,F& f,G& g, H& h, I& i),(mFile,a,b,c,d,e,f,g,h,i));
704   template<class A,class B,class C,class D,class E, class F, class G, class H>
705      Method((A& a,B& b,C& c,D& d,E& e,F& f,G& g, H& h),(mFile,a,b,c,d,e,f,g,h));
706   template<class A,class B,class C,class D,class E, class F, class G>
707      Method((A& a,B& b,C& c,D& d,E& e,F& f,G& g),(mFile,a,b,c,d,e,f,g));
708   template<class A,class B,class C,class D,class E, class F>
709      Method((A& a,B& b,C& c,D& d,E& e,F& f),(mFile,a,b,c,d,e,f));
710   template<class A,class B,class C,class D,class E>
711      Method((A& a,B& b,C& c,D& d,E& e),(mFile,a,b,c,d,e));
712   template<class A,class B,class C,class D>
713      Method((A& a,B& b,C& c,D& d),(mFile,a,b,c,d));
714   template<class A,class B,class C>
715      Method((A& a,B& b,C& c),(mFile,a,b,c));
716   template<class A,class B>
717      Method((A& a,B& b),(mFile,a,b));
718   template<class A>
719      Method((A& a),(mFile,a));
720
721   #undef Method
722};
723
724#endif
725