gwnavruntime/kernel/SF_Stats.h Source File

SF_Stats.h
Go to the documentation of this file.
1 /*
2 * Copyright 2015 Autodesk, Inc. All rights reserved.
3 * Use of this software is subject to the terms of the Autodesk license agreement and any attachments or Appendices thereto provided at the time of installation or download,
4 * or which otherwise accompanies this software in either electronic or hard copy form, or which is signed by you and accepted by Autodesk.
5 */
6 
7 /**************************************************************************
8 
9 PublicHeader: Kernel
10 Filename : KY_Stats.h
11 Content : Statistics tracking and reporting APIs
12 Created : May 20, 2008
13 Authors : Michael Antonov, Boris Rayskiy, Maxim Shemanarev
14 
15 **************************************************************************/
16 
17 #ifndef INC_KY_Kernel_Stats_H
18 #define INC_KY_Kernel_Stats_H
19 
22 
23 namespace Kaim {
24 
25 
26 // ***** Stat Group Identifiers
27 //
28 // Stat identifiers are organized into groups corresponding to different
29 // sub-systems such as the renderer, MovieDef, etc. Every group receives
30 // its own Id range, allowing identifiers within that system to be added
31 // without having to modify StatId (those identifiers are normally defined
32 // as a part of a separate enumeration in their own header file).
33 
34 // All identifier constants must follow this naming convention:
35 // - Start with a system group prefix such as StatGroup_ (for group ids),
36 // StatHeap_, StatRenderer_, GFxStatMV_, etc.
37 // - User one of the following endings to identify stat types:
38 // - _Mem for MemoryStat.
39 // - _Tks for TimerStat.
40 // - _Cnt for CounterStat.
41 //---------------------------------------------------------------------------
42 enum StatBasicValues
43 {
44  // Starting values
45  StatGroup_Default = 0,
46  StatGroup_Core = 16,
47 
48  Stat_Mem = StatGroup_Default + 1,
49  Stat_Default_Mem = Stat_Mem + 1,
50 
51  // General Memory
52  Stat_Image_Mem,
53  Stat_String_Mem,
54  Stat_StatBag_Mem,
55  Stat_Debug_Mem,
56  Stat_EndDefault_Mem, //< used by other layers to start defining their own memory stats
57 
58  // Core entries.
59  StatHeap_Start = StatGroup_Core,
60  // 16 slots for HeapSummary
61 
62  // How many entries we support by default
63  Stat_MaxId = 64 << 6, // 64 * 64 = 4096
64  Stat_EntryCount = 512,
65 
66  // Other values
67  HeapId_Default = 1,
68 };
69 
70 enum HeapId
71 {
72  HeapId_Global = HeapId_Default,
73 };
74 
75 // ***** Stat
76 
77 // Base class for all of the statistics. This class does not actually store
78 // any data, expecting derived classes such as MemoryStat to do so.
79 
80 class Stat
81 {
82 public:
83 
84  // Different statistics types that we collect.
85  enum StatType
86  {
87  Stat_LogicalGroup,
88  Stat_Memory,
89  Stat_Timer,
90  Stat_Counter,
91  // The number of supported types.
92  Stat_TypeCount
93  };
94 
95  // A structure that represents a single statistics value.
96  struct StatValue
97  {
98  enum ValueType
99  {
100  VT_None,
101  VT_Int,
102  VT_Int64,
103  VT_Float
104  };
105 
106  ValueType Type;
107  const char* pName;
108  union
109  {
110  UPInt IValue;
111  UInt64 I64Value;
112  float FValue;
113  };
114 
115  StatValue() : Type(VT_None), pName(""), IValue(0)
116  { }
117  StatValue(const StatValue& src)
118  : Type(src.Type), pName(src.pName), I64Value(src.I64Value)
119  { }
120 
121  StatValue& operator = (const StatValue& src)
122  {
123  Type = src.Type; pName = src.pName; I64Value = src.I64Value;
124  return *this;
125  }
126 
127  // Assignment of particular types
128  void SetInt(const char* pname, UPInt val)
129  {
130  Type = VT_Int;
131  pName = pname;
132  IValue = val;
133  }
134 
135  void SetInt64(const char* pname, UInt64 val)
136  {
137  Type = VT_Int64;
138  pName = pname;
139  I64Value = val;
140  }
141 
142  void SetFloat(const char* pname, float val)
143  {
144  Type = VT_Float;
145  pName = pname;
146  FValue = val;
147  }
148  };
149 
150 };
151 
152 
153 // ***** MemoryStat
154 
155 // Records memory allocation statics for a particular allocation Id type.
156 // Keeps track of the number of bytes allocated and used, including use peak.
157 // Unlike allocation size, used includes the number of bytes occupied
158 // in the allocator for maintaining the block, including the different
159 // header and alignment space.
160 
161 class MemoryStat : public Stat
162 {
163 #ifndef KY_ENABLE_STATS
164 
165  // *** Null Stat implementation
166 public:
167 
168  MemoryStat() { }
169 
170  void Init() { }
171  void Increment(UPInt, UPInt ) { }
172  MemoryStat& operator += (MemoryStat& ) { return *this; }
173  MemoryStat& operator -= (MemoryStat& ) { return *this; }
174 
175  StatType GetStatType() const { return Stat_Memory; }
176  unsigned GetStatCount() const { return 3; }
177 
178  void GetStat(StatValue* pval, unsigned index) const
179  {
180  switch(index)
181  {
182  case 0: pval->SetInt("Allocated", 0); break;
183  case 1: pval->SetInt("Used", 0); break;
184  case 2: pval->SetInt("AllocCount", 0); break;
185  }
186  }
187 
188  void Add(MemoryStat*) { }
189  void SetMax(MemoryStat*) { }
190  void SetMin(MemoryStat*) { }
191  void Reset() { }
192 
193  UPInt GetAllocated() const { return 0; }
194  UPInt GetUsed() const { return 0; }
195  UPInt GetAllocCount() const { return 0; }
196 
197 #else
198 
199  // *** Default Stat implementation
200  UPInt Allocated;
201  UPInt Used;
202  UPInt AllocCount;
203 
204 public:
205 
206  MemoryStat()
207  {
208  Init();
209  }
210 
211  void Init()
212  {
213  Allocated = 0;
214  Used = 0;
215  AllocCount= 0;
216  }
217 
218 
219  void Increment(UPInt alloc, UPInt use)
220  {
221  Allocated+= alloc;
222  Used += use;
223  AllocCount++;
224  }
225 
226 
227  MemoryStat& operator += (MemoryStat& other)
228  {
229  Allocated += other.Allocated;
230  Used += other.Used;
231  AllocCount+= other.AllocCount;
232  return *this;
233  }
234 
235  MemoryStat& operator -= (MemoryStat& other)
236  {
237  Allocated -= other.Allocated;
238  Used -= other.Used;
239  AllocCount-= other.AllocCount;
240  return *this;
241  }
242 
243 
244  // *** General accessibility API.
245  StatType GetStatType() const { return Stat_Memory; }
246  unsigned GetStatCount() const { return 3; }
247 
248  void GetStat(StatValue* pval, unsigned index) const
249  {
250  switch(index)
251  {
252  case 0: pval->SetInt("Allocated", Allocated); break;
253  case 1: pval->SetInt("Used", Used); break;
254  case 2: pval->SetInt("AllocCount", AllocCount); break;
255  }
256  }
257 
258  // Reset, Add, SetMin, SetMax
259  void Add(MemoryStat* p)
260  { *this += *p; }
261 
262  void SetMin(MemoryStat* p)
263  {
264  Allocated = (p->Allocated < Allocated) ? p->Allocated : Allocated;
265  Used = (p->Used < Used ) ? p->Used : Used;
266  AllocCount= (p->AllocCount<AllocCount) ? p->AllocCount: AllocCount;
267  }
268  void SetMax(MemoryStat* p)
269  {
270  Allocated = (p->Allocated > Allocated) ? p->Allocated : Allocated;
271  Used = (p->Used > Used ) ? p->Used : Used;
272  AllocCount= (p->AllocCount>AllocCount) ? p->AllocCount: AllocCount;
273  }
274 
275 
276  void Reset()
277  {
278  Allocated = 0;
279  Used = 0;
280  AllocCount= 0;
281  }
282 
283  UPInt GetAllocated() const { return Allocated; }
284  UPInt GetUsed() const { return Used; }
285  UPInt GetAllocCount() const { return AllocCount; }
286 
287 #endif
288 };
289 
290 
291 
292 // ***** TimerStat
293 
294 // TimerStat records the number of nano-second ticks used for a certain
295 // measured activity, such as rendering or tessellation. The time is most
296 // easily measured by using the TimerStat::ScopeTimer scope object around
297 // the code whose performance is to be measured. Every time that block of
298 // code is executed, the number of ticks will be incremented appropriately.
299 
300 class TimerStat : public Stat
301 {
302 #ifndef KY_ENABLE_STATS
303 
304  // *** Null Stat implementation
305 public:
306  TimerStat() { }
307 
308  void Init() { }
309  TimerStat& operator += (TimerStat&) { return *this; }
310  StatType GetStatType() const { return Stat_Timer; }
311  unsigned GetStatCount() const { return 1; }
312 
313  void GetStat(StatValue* pval, unsigned index) const
314  {
315  switch(index)
316  {
317  case 0: pval->SetInt64("Ticks", 0); break;
318  }
319  }
320 
321  void Add(TimerStat*) { }
322  void SetMax(TimerStat*) { }
323  void SetMin(TimerStat*) { }
324  void AddTicks(UInt64) { }
325  void Reset() { }
326 
327  class ScopeTimer
328  {
329  public:
330  ScopeTimer(TimerStat*) { }
331  };
332 
333  UInt64 GetTicks() const { return 0; }
334 
335 #else
336 
337  // *** Full TimerStat implementation
338 
339  // Tracks the number of nano-second ticks that passed.
340  UInt64 Ticks;
341 
342 public:
343 
344  TimerStat()
345  {
346  Init();
347  }
348 
349  void Init()
350  {
351  Ticks = 0;
352  }
353 
354  TimerStat& operator += (TimerStat& other)
355  {
356  Ticks += other.Ticks;
357  return *this;
358  }
359 
360 
361  // *** General accessibility API.
362  StatType GetStatType() const { return Stat_Timer; }
363  unsigned GetStatCount() const { return 1; }
364 
365  void GetStat(StatValue* pval, unsigned index) const
366  {
367  switch(index)
368  {
369  case 0: pval->SetInt64("Ticks", Ticks); break;
370  }
371  }
372 
373  // Reset, Clear, Add
374  void Add(TimerStat* p)
375  { *this += *p; }
376 
377  void SetMin(TimerStat* p)
378  {
379  Ticks = (p->Ticks < Ticks) ? p->Ticks : Ticks;
380  }
381  void SetMax(TimerStat* p)
382  {
383  Ticks = (p->Ticks > Ticks) ? p->Ticks : Ticks;
384  }
385 
386  void AddTicks(UInt64 ticks)
387  {
388  Ticks += ticks;
389  }
390 
391 
392  void Reset()
393  {
394  Ticks = 0;
395  }
396 
397 
398  // Scope used for timer measurements.
399  class ScopeTimer
400  {
401  TimerStat* pTimer;
402  UInt64 StartTicks;
403  public:
404 
405  ScopeTimer(TimerStat* ptimer)
406  : pTimer(ptimer)
407  {
408  StartTicks = Timer::GetProfileTicks();
409  }
410  ~ScopeTimer()
411  {
412  UInt64 endTicks = Timer::GetProfileTicks();
413  pTimer->AddTicks(endTicks - StartTicks);
414  }
415  };
416 
417 
418  UInt64 GetTicks() const { return Ticks; }
419 
420 #endif
421 };
422 
423 
424 
425 
426 // ***** CounterStat
427 
428 // A counter stat tracks the number of times a certain measured event
429 // took place. The counter can also be used to record the number of
430 // certain objects processed by the algorithm, such as the number of
431 // DrawPrimitives or triangles drawn by the renderer.
432 
433 class CounterStat : public Stat
434 {
435 #ifndef KY_ENABLE_STATS
436 
437  // *** Null CounterStat
438 public:
439  CounterStat() { }
440  CounterStat(UPInt) { }
441 
442  void Init() { }
443  CounterStat& operator += (CounterStat&) { return *this; }
444  StatType GetStatType() const { return Stat_Counter; }
445  unsigned GetStatCount() const { return 1; }
446 
447  void GetStat(StatValue* pval, unsigned index) const
448  {
449  switch(index)
450  {
451  case 0: pval->SetInt("Count", 0); break;
452  }
453  }
454 
455  // Reset, Add, SetMin, SetMax
456  void Add(CounterStat*) { }
457  void SetMin(CounterStat*) { }
458  void SetMax(CounterStat*) { }
459  void Reset() { }
460  void AddCount(UPInt) { }
461 
462  UPInt GetCount() const { return 0; }
463 
464 #else
465  // *** Full CounterStat implementation
466 
467  UPInt Count;
468 
469 public:
470  CounterStat()
471  {
472  Init();
473  }
474  CounterStat(UPInt count)
475  {
476  Count = count;
477  }
478 
479  void Init()
480  {
481  Count = 0;
482  }
483 
484  CounterStat& operator += (CounterStat& other)
485  {
486  Count += other.Count;
487  return *this;
488  }
489 
490 
491  // *** General accessibility API.
492  StatType GetStatType() const { return Stat_Counter; }
493  unsigned GetStatCount() const { return 1; }
494 
495  void GetStat(StatValue* pval, unsigned index) const
496  {
497  switch(index)
498  {
499  case 0: pval->SetInt("Count", Count); break;
500  }
501  }
502 
503  // Reset, Add
504  void Add(CounterStat* p)
505  { *this += *p; }
506 
507  void SetMin(CounterStat* p)
508  {
509  Count = (p->Count < Count) ? p->Count : Count;
510  }
511  void SetMax(CounterStat* p)
512  {
513  Count = (p->Count > Count) ? p->Count : Count;
514  }
515 
516  void AddCount(UPInt count)
517  {
518  Count += count;
519  }
520 
521  void Reset()
522  {
523  Count = 0;
524  }
525 
526  UPInt GetCount() const { return Count; }
527 
528 #endif
529 };
530 
531 
532 
533 /* ***** Statistics Group Types
534 
535  Group (Logical)
536  - A logical group organizes a set of other stats into one group, giving
537  them a common display title.
538 
539  Sum Group
540  - A sum group maintains its own counter that includes the values of child
541  item counters, but can be greater. It is expected that sum group can have
542  additional 'remainder' values not accounted for by its children.
543  The group is updated manually by the user using scopes or calling the
544  appropriate Add function for the stat is question.
545 
546  AutoSum Group
547  - A sum group that is calculated automatically during the call to
548  StatBag::UpdateGroups; the user does not need to update the sum since it
549  is computed by adding up all of its child values.
550 */
551 
552 // Stat descriptor structure used by the KY_DECLARE_??_STAT macros.
553 struct StatDesc
554 {
555  enum
556  {
557  KY_Group = 0x01,
558  KY_Sum = 0x02, // This group is a manual sum of its sub-items.
559  KY_AutoSum = 0x04, // This an automatically computed sum of its items.
560 
561  // Combination of flags
562  KY_SumGroup = KY_Group | KY_Sum,
563  KY_AutoSumGroup = KY_Group | KY_AutoSum
564  };
565 
566  // Iterator used to enumerate children.
567  class Iterator
568  {
569  const StatDesc* pDesc;
570  public:
571 
572  Iterator(const StatDesc* p) { pDesc = p; }
573  Iterator(const Iterator&s) { pDesc = s.pDesc; }
574  Iterator& operator = (const Iterator&s) { pDesc = s.pDesc; return *this; }
575 
576  const StatDesc* operator * () const { return pDesc; }
577  const StatDesc* operator -> () const { return pDesc; }
578 
579 #ifndef KY_ENABLE_STATS
580 
581  bool operator ++ () { return false; }
582  unsigned GetId() const { return 0; }
583 
584 #else // KY_ENABLE_STATS
585 
586  bool operator ++ () { if (pDesc) pDesc = pDesc->pNextSibling; return (pDesc != 0); }
587  unsigned GetId() const { return pDesc->Id; }
588 
589 #endif // KY_ENABLE_STATS
590 
591  bool operator == (const Iterator&s) const { return pDesc == s.pDesc; }
592  bool operator != (const Iterator&s) const { return pDesc != s.pDesc; }
593  bool IsEnd() const { return pDesc == 0; }
594  };
595 
596  static void InitChildTree();
597 
598 #ifndef KY_ENABLE_STATS
599 
600  static const StatDesc* KY_CDECL GetDesc(unsigned) { return 0; }
601  StatDesc(Stat::StatType, UByte, unsigned, const char*, unsigned) { }
602 
603  bool IsAutoSumGroup() const { return false; }
604  const char* GetName() const { return ""; }
605  Iterator GetChildIterator() const { return Iterator(0); }
606  static Iterator GetGroupIterator(unsigned) { return Iterator(0); }
607  unsigned GetId() const { return 0; }
608 
609 #else // KY_ENABLE_STATS
610 
611  // Register descriptors so that they can be looked up by id.
612  static void RegisterDesc(StatDesc* pdesc);
613  static const StatDesc* KY_CDECL GetDesc(unsigned id);
614 
615 private:
616 
617  UByte Type;
618  UByte Flags;
619  unsigned Id;
620  unsigned GroupId;
621  const char* pName;
622 
623  // Tree data representation, established by RegisterDesc. A parent descriptor
624  // can have a list if children which are enumerated by accessing pChild and
625  // then traversing the chain of pNextSibling.
626  StatDesc* pChild;
627  StatDesc* pNextSibling;
628 
629 public:
630 
631  StatDesc(Stat::StatType type, UByte flags, unsigned id,
632  const char* pname, unsigned groupId)
633  {
634  Type = (UByte)type;
635  Flags = flags;
636  Id = id;
637  GroupId = groupId;
638  pName = pname;
639  pChild = 0;
640  pNextSibling = 0;
641 
642  RegisterDesc(this);
643  }
644 
645  UByte GetType() const { return Type; }
646 
647  unsigned GetId() const { return Id; }
648  void SetId(unsigned value) { Id = value; }
649 
650  unsigned GetGroupId() const { return GroupId; }
651  void SetGroupId(unsigned value) { GroupId = value; }
652 
653 
654  bool IsAutoSumGroup() const
655  {
656  return (Flags & KY_AutoSumGroup) == KY_AutoSumGroup;
657  }
658 
659  const char* GetName() const { return pName; }
660 
661  // Obtain Iterator for the first child. Users can call IsEnd() to determine
662  // if a child actually exists.
663  Iterator GetChildIterator() const { return Iterator(pChild); }
664 
665  // Get an item Iterator based on it.
666  static Iterator GetGroupIterator(unsigned groupId) { return Iterator(GetDesc(groupId)); }
667 
668 #endif // KY_ENABLE_STATS
669 
670 };
671 
672 
673 // We need to create this table during initialization.
674 // statId -> StatDesc
675 // statId -> StatInterface [identified by type]
676 
677 #define KY_DECLARE_STAT_GROUP(id, name, group) Kaim::StatDesc KY_STAT_##id(Kaim::Stat::Stat_LogicalGroup, Kaim::StatDesc::KY_Group, id, name, group);
678 
679 // Manual sum groups.
680 #define KY_DECLARE_MEMORY_STAT_SUM_GROUP(id, name, group) Kaim::StatDesc KY_STAT_##id(Kaim::Stat::Stat_Memory, Kaim::StatDesc::KY_SumGroup, id, name, group);
681 #define KY_DECLARE_TIMER_STAT_SUM_GROUP(id, name, group) Kaim::StatDesc KY_STAT_##id(Kaim::Stat::Stat_Timer, Kaim::StatDesc::KY_SumGroup, id, name, group);
682 #define KY_DECLARE_COUNTER_STAT_SUM_GROUP(id, name, group) Kaim::StatDesc KY_STAT_##id(Kaim::Stat::Stat_Counter, Kaim::StatDesc::KY_SumGroup, id, name, group);
683 // Automatically added groups.
684 #define KY_DECLARE_MEMORY_STAT_AUTOSUM_GROUP(id, name, group) Kaim::StatDesc KY_STAT_##id(Kaim::Stat::Stat_Memory, Kaim::StatDesc::KY_AutoSumGroup, id, name, group);
685 #define KY_DECLARE_TIMER_STAT_AUTOSUM_GROUP(id, name, group) Kaim::StatDesc KY_STAT_##id(Kaim::Stat::Stat_Timer, Kaim::StatDesc::KY_AutoSumGroup, id, name, group);
686 #define KY_DECLARE_COUNTER_STAT_AUTOSUM_GROUP(id, name, group) Kaim::StatDesc KY_STAT_##id(Kaim::Stat::Stat_Counter, Kaim::StatDesc::KY_AutoSumGroup, id, name, group);
687 // Stats.
688 #define KY_DECLARE_MEMORY_STAT(id, name, group) Kaim::StatDesc KY_STAT_##id(Kaim::Stat::Stat_Memory, 0, id, name, group);
689 #define KY_DECLARE_TIMER_STAT(id, name, group) Kaim::StatDesc KY_STAT_##id(Kaim::Stat::Stat_Timer, 0, id, name, group);
690 #define KY_DECLARE_COUNTER_STAT(id, name, group) Kaim::StatDesc KY_STAT_##id(Kaim::Stat::Stat_Counter, 0, id, name, group);
691 
692 
693 
694 
695 // {stat_data, stat_id} -> Stat interface.
696 
697 class StatInfo : public Stat
698 {
699 public:
700  // Abstract interface use to obtain Stat
701  class StatInterface
702  {
703  public:
704  virtual ~StatInterface() { }
705 
706  virtual StatType GetType(Stat* p) = 0;
707  virtual unsigned GetStatCount(Stat* p) = 0;
708  virtual void GetStat(Stat* p, StatValue* pval, unsigned index) = 0;
709  virtual UPInt GetStatDataSize() const = 0;
710  // Reset, Clear, Add
711  virtual void Init(Stat* p) = 0;
712  virtual void Add(Stat* p1, Stat* p2) = 0;
713  virtual void SetMin(Stat* p1, Stat* p2) = 0;
714  virtual void SetMax(Stat* p1, Stat* p2) = 0;
715  virtual void Reset(Stat* p) = 0;
716  };
717 
718 private:
719  unsigned StatId;
720  StatInterface* pInterface;
721  Stat* pData;
722 
723 public:
724 
725  StatInfo()
726  : StatId(0), pInterface(0), pData(0)
727  {}
728 
729  StatInfo(unsigned statId, StatInterface* psi, Stat* pdata)
730  : StatId(statId), pInterface(psi), pData(pdata)
731  { }
732 
733  StatInfo(const StatInfo& src)
734  {
735  StatId = src.StatId;
736  pInterface = src.pInterface;
737  pData = src.pData;
738  }
739 
740  bool IsNull() const { return pInterface == 0; }
741 
742  // Access individual stat components.
743  StatType GetType() const { return pInterface->GetType(pData); }
744  unsigned GetStatCount() const { return pInterface->GetStatCount(pData); }
745  void GetStat(StatValue* pval, unsigned index) { pInterface->GetStat(pData, pval, index); }
746 
747  void Add(StatInfo& si2)
748  {
749  KY_ASSERT(si2.GetType() == GetType());
750  pInterface->Add(pData, si2.pData);
751  }
752  void SetMin(StatInfo& si2)
753  {
754  KY_ASSERT(si2.GetType() == GetType());
755  pInterface->SetMin(pData, si2.pData);
756  }
757  void SetMax(StatInfo& si2)
758  {
759  KY_ASSERT(si2.GetType() == GetType());
760  pInterface->SetMax(pData, si2.pData);
761  }
762  void Reset()
763  {
764  pInterface->Reset(pData);
765  }
766 
767  const char* GetName() const { return StatDesc::GetDesc(StatId)->GetName(); }
768 
769 
770  // Manual interpretation.
771  bool IsMemory() const { return GetType() == Stat::Stat_Memory; }
772  bool IsTimer() const { return GetType() == Stat::Stat_Timer; }
773  bool IsCounter() const { return GetType() == Stat::Stat_Counter; }
774 
775  MemoryStat* ToMemoryStat() const { KY_ASSERT(IsMemory()); return (MemoryStat*)pData; }
776  TimerStat* ToTimerStat() const { KY_ASSERT(IsTimer()); return (TimerStat*)pData; }
777  CounterStat* ToCounterStat() const { KY_ASSERT(IsCounter()); return (CounterStat*)pData; }
778 
779 };
780 
781 
782 // Template class implementing StatInfo::StatInterface
783 template<class C>
784 class StatInfo_InterfaceImpl : public StatInfo::StatInterface
785 {
786  typedef Stat::StatType StatType;
787  typedef Stat::StatValue StatValue;
788 
789  StatType GetType(Stat* p) { return ((C*)p)->GetStatType(); }
790  unsigned GetStatCount(Stat* p) { return ((C*)p)->GetStatCount(); }
791  void GetStat(Stat* p, StatValue* pval, unsigned index) { ((C*)p)->GetStat(pval, index); }
792  UPInt GetStatDataSize() const { return sizeof(C); }
793  void Init(Stat* p) { ((C*)p)->Init(); }
794  void Add(Stat* p, Stat* p2) { ((C*)p)->Add((C*)p2); }
795  void SetMin(Stat* p, Stat* p2) { ((C*)p)->SetMin((C*)p2); }
796  void SetMax(Stat* p, Stat* p2) { ((C*)p)->SetMax((C*)p2); }
797  void Reset(Stat* p) { ((C*)p)->Reset(); }
798 };
799 
800 
801 // ***** StatBag
802 
803 // Represents a bag, or collection of statistics data. Any type of Stat can
804 // be added into the bag; after statistics data is added it can be iterated
805 // through with Iterator class, obtained from GetIterator.
806 
807 class MemoryHeap;
808 class StatBag
809 {
810 
811 public:
812 
813  typedef StatInfo::StatInterface StatInterface;
814 
815 
816 #ifndef KY_ENABLE_STATS
817 
818  // *** Null StatBag
819 
820  StatBag(MemoryHeap* = 0, unsigned = 0) { }
821  StatBag(const StatBag&) { }
822  ~StatBag() { }
823 
824  void Clear() { }
825  void Reset() { }
826  bool Add(unsigned, Stat* ) { return false; }
827  StatBag& operator += (const StatBag&) { return *this; }
828  StatBag& operator = (const StatBag&) { return *this; }
829  void UpdateGroups() { }
830 
831  bool GetStat(StatInfo *, unsigned) const { return false; }
832 
833  inline bool AddStat(unsigned, const Stat&) { return false; }
834 
835  // Add/SetMin/SetMax statistic value of a certain id.
836  bool SetMin(unsigned statId, Stat* pstat) { KY_UNUSED(statId); KY_UNUSED(pstat); return false; }
837  bool SetMax(unsigned statId, Stat* pstat) { KY_UNUSED(statId); KY_UNUSED(pstat); return false; }
838 
839  void SetMin(const StatBag& other) { KY_UNUSED(other); }
840  void SetMax(const StatBag& other) { KY_UNUSED(other); }
841 
842  struct Iterator
843  {
844  StatInfo Result;
845 
846  // Default Iterator start points to no data.
847  Iterator(StatBag*, unsigned, unsigned) { }
848  Iterator(const Iterator&) { }
849 
850  const StatInfo& operator * () const { return Result; }
851  const StatInfo* operator -> () const { return &Result; }
852  bool operator ++ () { return false; }
853  unsigned GetId() const { return StatGroup_Default; }
854  bool operator == (const Iterator&) const { return false; }
855  bool operator != (const Iterator&) const { return true; }
856  bool IsEnd() const { return true; }
857  };
858  Iterator GetIterator(unsigned groupId = Stat_MaxId) { return Iterator (this, 0, groupId);}
859 
860 #else // KY_ENABLE_STATS
861 
862 
863  // *** Full StatBag Implementation
864 
865  enum
866  {
867  StatBag_MemGranularity = 8,
868  StatBag_PageShift = 4,
869  StatBag_PageSize = 1 << StatBag_PageShift,
870  StatBag_PageTableSize = Stat_MaxId / StatBag_PageSize,
871  StatBag_EndId = Stat_MaxId,
872 
873  // Page table entries are set to this value if no memory
874  // or slot is allocated to them.
875  StatBag_IdUnused = 0xFFFF
876  };
877 
878  static StatInterface* GetInterface(unsigned id);
879 
880 private:
881 
882  // Allocated memory and pointer of how much of it is left.
883  UByte* pMem;
884  unsigned MemSize;
885  UPInt MemAllocOffset;
886 
887  // Id page table.
888  UInt16 IdPageTable[StatBag_PageTableSize];
889 
890  Stat* GetStatRef(unsigned statId) const;
891  UByte* AllocStatData(unsigned statId, UPInt size);
892 
893  void RecursiveGroupUpdate(StatDesc::Iterator it);
894 
895  // Combines statistics from two bags based on a function.
896  void CombineStatBags(const StatBag& other, bool (StatBag::*func)(unsigned id, Stat*));
897 
898 public:
899  // Create a stat bag with specified number of entries.
900  StatBag(MemoryHeap* pheap = 0, unsigned memReserve = Stat_EntryCount * 16);
901  StatBag(const StatBag& source);
902 
903  ~StatBag();
904 
905 public:
906 
907  // Clear out the bag, removing all states.
908  void Clear();
909  // Reset stat values.
910  void Reset();
911 
912 
913  // Add/SetMin/SetMax statistic value of a certain id.
914  bool Add(unsigned statId, Stat* pstat);
915  bool SetMin(unsigned statId, Stat* pstat);
916  bool SetMax(unsigned statId, Stat* pstat);
917 
918  inline bool AddStat(unsigned statId, const Stat& stat)
919  {
920  return Add(statId, const_cast<Stat*>(&stat));
921  }
922 
923  // Some optimization for MemoryHeapStat
924  bool AddMemoryStat(unsigned statId, const MemoryStat& stat);
925  bool IncrementMemoryStat(unsigned statId, UPInt alloc, UPInt use);
926 
927  // Compute minimums and maximums of two bags.
928  void Add(const StatBag& other) { CombineStatBags(other, &StatBag::Add); }
929  void SetMin(const StatBag& other) { CombineStatBags(other, &StatBag::SetMin); }
930  void SetMax(const StatBag& other) { CombineStatBags(other, &StatBag::SetMax); }
931 
932  // Add values of a different stat bag to ours.
933  StatBag& operator += (const StatBag& other) { Add(other); return *this; }
934  StatBag& operator = (const StatBag& other)
935  {
936  if (this == &other)
937  return *this;
938  Clear();
939  Add(other);
940  return *this;
941  }
942 
943  // Update all automatically computed groups in the list.
944  void UpdateGroups();
945 
946  // Does this accumulate data or not?
947  bool GetStat(StatInfo *pstat, unsigned statId) const;
948 
949 
950  // *** Iterating Stat Data
951 
952  struct Iterator
953  {
954  protected:
955  unsigned Id; // Current id we are traversing.
956  unsigned GroupId; // Group id mask.
957  StatBag* pBag;
958  StatInfo Result; // Cached result for entry
959 
960  // Advance to this/next valid item or fail.
961  bool AdvanceTillValid();
962 
963  public:
964 
965  // Default Iterator start points to no data.
966  Iterator(StatBag* pbag = 0, unsigned id = Stat_MaxId, unsigned groupId = Stat_MaxId);
967 
968  Iterator(const Iterator& src)
969  : Id(src.Id), GroupId(src.GroupId), Result(src.Result)
970  { }
971 
972 
973  const StatInfo& operator * () const { return Result; }
974  const StatInfo* operator -> () const { return &Result; }
975 
976  bool operator ++ ()
977  {
978  KY_ASSERT(pBag != 0);
979  Id++;
980  return AdvanceTillValid();
981  }
982 
983  unsigned GetId() const { return Id; }
984 
985  bool operator == (const Iterator& it) const
986  {
987  return Id == it.Id;
988  }
989  bool operator != (const Iterator& it) const
990  {
991  return ! (*this == it);
992  }
993 
994  bool IsEnd() const
995  {
996  return (Id >= StatBag_EndId) ;
997  }
998  };
999 
1000  // Obtains an Iterator for the specified stat group. Default implementation
1001  // will return all of the stats in the bag.
1002  Iterator GetIterator(unsigned groupId = Stat_MaxId);
1003 
1004 
1005  // Wait for stats to be ready; useful if stat update
1006  // request is queued up for update in a separate thread.
1007  //void WaitForData();
1008 
1009 #endif
1010 };
1011 
1012 } // Scaleform
1013 
1014 #endif
Definition: gamekitcrowddispersion.h:20
Vec2f operator*(KyFloat32 s, const Vec2f &v)
Multiplies the X and Y coordinates of v by s.
Definition: vec2f.h:184