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 value; \
          (_Dispatching) \
            return; \
          (_State == PlayState) { \
            _start(); \
            (mFile,value); \
            _finish(); \
            return value; \
         } \
         _Dispatching = true; \
         value = (*func) Arg2; \
         _Dispatching = false; \
          (_State == RecordState) { \
            _start(); \
            (mFile,value); \
            _finish(); \
         } \
         return value; \
      }

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 value; \
          (_Dispatching) \
            return; \
          (_State == PlayState) { \
            _start(); \
            (mFile,value); \
            _finish(); \
            return value; \
         } \
         _Dispatching = true; \
         value = (*func) Arg2; \
         _Dispatching = false; \
          (_State == RecordState) { \
            _start(); \
            (mFile,value); \
            _finish(); \
         } \
         return value; \
      }

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      virtual ~FuncDecl() {}
340      virtual bool match(VoidPtr,VoidMethod) const = 0;
341      virtual Functor* create() const = 0;
342   };
343
344   template<typename T>
345   struct FuncRep: public FuncDecl {
346      typename T::FuncPtr function;
347      virtual bool match(VoidPtr ptr,VoidMethod) const {
348         return function == (typename T::FuncPtr)ptr;
349      }
350      T* create() const { return new T(function); };
351   };
352
353   template<typename T>
354   struct MethodRep: public FuncDecl {
355      typename T::ObjPtr obj;
356      typename T::MethodPtr method;
357      virtual bool match(VoidPtr ptr,VoidMethod func) const {
358         return obj == (typename T::ObjPtr)ptr && method == (typename T::MethodPtr)func;
359      }
360      T* create() const { return new T(obj,method); };
361   };
362
363   static FuncDecl* _FunctionList;
364
365   static inline IdGenerator &idPool()
366   {
367      static IdGenerator _IdPool(1, 65535);
368      return _IdPool;
369   }
370
371   static U32 _Count;
372   static Stream *mFile;
373   static enum Mode {
374      StopState, PlayState, RecordState, DisabledState
375   } _State;
376   static bool _Dispatching;
377
378   static Functor* _create(Id id);
379   static void _start();
380   static void _finish();
381   static Id _getFunctionId(VoidPtr ptr,VoidMethod method);
382   static void _removeFunctionId(VoidPtr ptr,VoidMethod method);
383
384public:
385   static void Record(const char * file);
386   static void Play(const char * file);
387   static bool PlayNext();
388   static void Stop();
389   static void Disable();
390
391   /// Returns true if in recording mode.
392   static inline bool IsRecording() {
393      return _State == RecordState;
394   }
395
396   /// Returns true if in play mode.
397   static inline bool IsPlaying() {
398      return _State == PlayState;
399   }
400
401   /// Returns true if a function is being dispatched
402   static inline bool IsDispatching() {
403      return _Dispatching;
404   }
405
406   template<typename T>
407   static void Read(T *v)
408   {
409      AssertFatal(IsPlaying(), "Journal::Read - not playing right now.");
410      bool r = mFile->read(v);
411      AssertFatal(r, "Journal::Read - failed to read!");
412   }
413
414   static bool Read(U32 size, void *buffer)
415   {
416      AssertFatal(IsPlaying(), "Journal::Read - not playing right now.");
417      bool r = mFile->read(size, buffer);
418      AssertFatal(r, "Journal::Read - failed to read!");
419      return r;
420   }
421
422   static void ReadString(char str[256])
423   {
424      AssertFatal(IsPlaying(), "Journal::ReadString - not playing right now.");
425      mFile->readString(str);
426   }
427
428   template<typename T>
429   static void Write(const T &v)
430   {
431      AssertFatal(IsRecording(), "Journal::Write - not recording right now.");
432      bool r = mFile->write(v);
433      AssertFatal(r, "Journal::Write - failed to write!");
434   }
435
436   static bool Write(U32 size, void *buffer)
437   {
438      AssertFatal(IsRecording(), "Journal::Write - not recording right now.");
439      bool r = mFile->write(size, buffer);
440      AssertFatal(r, "Journal::Write - failed to write!");
441      return r;   
442   }
443
444   static void WriteString(const char str[256])
445   {
446      AssertFatal(IsRecording(), "Journal::WriteString - not recording right now.");
447      mFile->writeString(str);
448   }
449
450   /// Register a function with the journalling system.
451   template<typename T>
452   static void DeclareFunction(T func) {
453      if (!_getFunctionId((VoidPtr)func,0)) {
454         FuncRep<FunctorDecl<T> >* decl = new FuncRep<FunctorDecl<T> >;
455         decl->function = func;
456         decl->id = idPool().alloc();
457         decl->next = _FunctionList;
458         _FunctionList = decl;
459      }
460   }
461
462   template<typename T, typename U>
463   static void DeclareFunction(T obj, U method)
464   {
465      if (!_getFunctionId((VoidPtr)obj,(VoidMethod)method)) {
466         MethodRep<MethodDecl<T,U> >* decl = new MethodRep<MethodDecl<T,U> >;
467         decl->obj = obj;
468         decl->method = method;
469         decl->id = idPool().alloc();
470         decl->next = _FunctionList;
471         _FunctionList = decl;
472      }
473   }
474
475   template<typename T, typename U>
476   static void RemoveFunction(T obj, U method)
477   {
478      _removeFunctionId((VoidPtr)obj,(VoidMethod)method);
479   }
480
481   /// Journal a function's return value. The return value of the
482   /// function is stored into the journal and retrieved during
483   /// playback. During playback the function is not executed.
484   #define Method(Func,Arg1,Arg2) \
485      static typename ReturnType<Func>::ValueType Result Arg1 { \
486         typename ReturnType<Func>::ValueType value; \
487         if (_Dispatching) \
488            return; \
489         if (_State == PlayState) { \
490            _start(); \
491            IOHelper::reads(mFile,value); \
492            _finish(); \
493            return value; \
494         } \
495         _Dispatching = true; \
496         value = (*func) Arg2; \
497         _Dispatching = false; \
498         if (_State == RecordState) { \
499            _start(); \
500            IOHelper::writes(mFile,value); \
501            _finish(); \
502         } \
503         return value; \
504      }
505
506   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>
507      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))
508   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>
509      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))
510   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>
511      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))
512   template<class Func,class A,class B,class C,class D,class E,class F, class G, class H, class I, class J>
513      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))
514   template<class Func,class A,class B,class C,class D,class E,class F, class G, class H, class I>
515      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))
516   template<class Func,class A,class B,class C,class D,class E,class F, class G, class H>
517      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))
518   template<class Func,class A,class B,class C,class D,class E,class F, class G>
519      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))
520   template<class Func,class A,class B,class C,class D,class E,class F>
521      Method(Func,(Func func,A a,B b,C c,D d,E e,F f),(a,b,c,d,e,f))
522   template<class Func,class A,class B,class C,class D,class E>
523      Method(Func,(Func func,A a,B b,C c,D d,E e),(a,b,c,d,e))
524   template<class Func,class A,class B,class C,class D>
525      Method(Func,(Func func,A a,B b,C c,D d),(a,b,c,d))
526   template<class Func,class A,class B,class C>
527      Method(Func,(Func func,A a,B b,C c),(a,b,c))
528   template<class Func,class A,class B>
529      Method(Func,(Func func,A a,B b),(a,b))
530   template<class Func,class A>
531      Method(Func,(Func func,A a),(a))
532   template<class Func>
533      Method(Func,(Func func),())
534   #undef Method
535
536   /// Journal a function call. Store the function id and all the
537   /// function's arguments into the journal. On journal playback the
538   /// function is executed with the retrieved arguments. The function
539   /// must have been previously declared using the declareFunction()
540   /// method.
541   #define Method(Arg1,Arg2,Arg3) \
542      static void Call Arg1 { \
543         if (_Dispatching) \
544            return; \
545         if (_State == PlayState) \
546            return; \
547         if (_State == RecordState) { \
548            Id id = _getFunctionId((VoidPtr)func,0); \
549            AssertFatal(id,"Journal: Function must be be declared before being called"); \
550            _start(); \
551            IOHelper::writes Arg2; \
552            _finish(); \
553         } \
554         _Dispatching = true; \
555         (*func) Arg3; \
556         _Dispatching = false; \
557         return; \
558      }
559
560   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>
561      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))
562   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>
563      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))
564   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>
565      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))
566   template<class Func,class A,class B,class C,class D,class E, class F, class G, class H, class I, class J>
567      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))
568   template<class Func,class A,class B,class C,class D,class E, class F, class G, class H, class I>
569      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))
570   template<class Func,class A,class B,class C,class D,class E, class F, class G, class H>
571      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))
572   template<class Func,class A,class B,class C,class D,class E, class F, class G>
573      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))
574   template<class Func,class A,class B,class C,class D,class E, class F>
575      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))
576   template<class Func,class A,class B,class C,class D,class E>
577      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))
578   template<class Func,class A,class B,class C,class D>
579      Method((Func func,A a,B b,C c,D d),(mFile,id,a,b,c,d),(a,b,c,d))
580   template<class Func,class A,class B,class C>
581      Method((Func func,A a,B b,C c),(mFile,id,a,b,c),(a,b,c))
582   template<class Func,class A,class B>
583      Method((Func func,A a,B b),(mFile,id,a,b),(a,b))
584   template<class Func,class A>
585      Method((Func func,A a),(mFile,id,a),(a))
586   template<class Func>
587      Method((Func func),(mFile,id),())
588   #undef Method
589
590   #define Method(Arg1,Arg2,Arg3) \
591      static void Call Arg1 { \
592         if (_Dispatching) \
593            return; \
594         if (_State == PlayState) \
595            return; \
596         if (_State == RecordState) { \
597            Id id = _getFunctionId((VoidPtr)obj,(VoidMethod)method); \
598            AssertFatal(id != 0,"Journal: Function must be be declared before being called"); \
599            _start(); \
600            IOHelper::writes Arg2; \
601            _finish(); \
602         } \
603         _Dispatching = true; \
604         (obj->*method) Arg3; \
605         _Dispatching = false; \
606         return; \
607      }
608
609
610   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>
611      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))
612   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>
613      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))
614   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>
615      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))
616   template<class Obj,class A,class B,class C,class D,class E,class F,class G,class H,class I,class J>
617      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))
618   template<class Obj,class A,class B,class C,class D,class E,class F,class G,class H,class I>
619      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))
620   template<class Obj,class A,class B,class C,class D,class E,class F,class G,class H>
621      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))
622   template<class Obj,class A,class B,class C,class D,class E,class F,class G>
623      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))
624   template<class Obj,class A,class B,class C,class D,class E,class F>
625      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))
626   template<class Obj,class A,class B,class C,class D,class E>
627      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))
628   template<class Obj,class A,class B,class C,class D>
629      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))
630   template<class Obj,class A,class B,class C>
631      Method((Obj* obj,void (Obj::*method)(A,B,C),A a,B b,C c),(mFile,id,a,b,c),(a,b,c))
632   template<class Obj,class A,class B>
633      Method((Obj* obj,void (Obj::*method)(A,B),A a,B b),(mFile,id,a,b),(a,b))
634   template<class Obj,class A>
635      Method((Obj* obj,void (Obj::*method)(A),A a),(mFile,id,a),(a))
636   template<class Obj>
637      Method((Obj* obj,void (Obj::*method)()),(mFile,id),())
638
639   #undef Method
640
641   /// Write data into the journal. Non-deterministic data can be stored
642   /// into the journal for reading during playback. The function
643   /// returns true if the journal is record mode.
644   #define Method(Arg1,Arg2) \
645      static inline bool Writes Arg1 { \
646         if (_State == RecordState) { \
647            _start(); IOHelper::writes Arg2; _finish(); \
648            return true; \
649         } \
650         return false; \
651      }
652
653   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>
654      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));
655   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>
656      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));
657   template<class A,class B,class C,class D,class E, class F, class G, class H,class I,class J,class K>
658      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));
659   template<class A,class B,class C,class D,class E, class F, class G, class H,class I,class J>
660      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));
661   template<class A,class B,class C,class D,class E, class F, class G, class H,class I>
662      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));
663   template<class A,class B,class C,class D,class E, class F, class G, class H>
664      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));
665   template<class A,class B,class C,class D,class E, class F, class G>
666      Method((A& a,B& b,C& c,D& d,E& e, F& f, G& g),(mFile,a,b,c,d,e,f,g));
667   template<class A,class B,class C,class D,class E, class F>
668      Method((A& a,B& b,C& c,D& d,E& e, F& f),(mFile,a,b,c,d,e,f));
669   template<class A,class B,class C,class D,class E>
670      Method((A& a,B& b,C& c,D& d,E& e),(mFile,a,b,c,d,e));
671   template<class A,class B,class C,class D>
672      Method((A& a,B& b,C& c,D& d),(mFile,a,b,c,d));
673   template<class A,class B,class C>
674      Method((A& a,B& b,C& c),(mFile,a,b,c));
675   template<class A,class B>
676      Method((A& a,B& b),(mFile,a,b));
677   template<class A>
678      Method((A& a),(mFile,a));
679   #undef Method
680
681   /// Read data from the journal. Read non-deterministic data stored
682   /// during the recording phase. The function returns true if the
683   /// journal is play mode.
684   #define Method(Arg1,Arg2) \
685      static inline bool Reads Arg1 { \
686         if (_State == PlayState) { \
687            _start(); IOHelper::reads Arg2; _finish(); \
688         return true; \
689         } \
690         return false; \
691      }
692
693   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>
694      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));
695   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>
696      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));
697   template<class A,class B,class C,class D,class E, class F, class G, class H, class I, class J, class K>
698      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));
699   template<class A,class B,class C,class D,class E, class F, class G, class H, class I, class J>
700      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));
701   template<class A,class B,class C,class D,class E, class F, class G, class H, class I>
702      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));
703   template<class A,class B,class C,class D,class E, class F, class G, class H>
704      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));
705   template<class A,class B,class C,class D,class E, class F, class G>
706      Method((A& a,B& b,C& c,D& d,E& e,F& f,G& g),(mFile,a,b,c,d,e,f,g));
707   template<class A,class B,class C,class D,class E, class F>
708      Method((A& a,B& b,C& c,D& d,E& e,F& f),(mFile,a,b,c,d,e,f));
709   template<class A,class B,class C,class D,class E>
710      Method((A& a,B& b,C& c,D& d,E& e),(mFile,a,b,c,d,e));
711   template<class A,class B,class C,class D>
712      Method((A& a,B& b,C& c,D& d),(mFile,a,b,c,d));
713   template<class A,class B,class C>
714      Method((A& a,B& b,C& c),(mFile,a,b,c));
715   template<class A,class B>
716      Method((A& a,B& b),(mFile,a,b));
717   template<class A>
718      Method((A& a),(mFile,a));
719
720   #undef Method
721};
722
723#endif
724