journal.h
Engine/source/core/util/journal/journal.h
Classes:
Journaling System.
Functor base classes.
Multiple argument function functor specialization.
Public Defines
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.
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.
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