tickCache.cpp

Engine/source/T3D/gameBase/tickCache.cpp

More...

Classes:

Detailed Description

  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#include "platform/platform.h"
 25#include "T3D/gameBase/gameBase.h"
 26#include "console/consoleTypes.h"
 27#include "console/consoleInternal.h"
 28#include "core/stream/bitStream.h"
 29#include "sim/netConnection.h"
 30#include "T3D/gameBase/gameConnection.h"
 31#include "math/mathIO.h"
 32#include "T3D/gameBase/moveManager.h"
 33#include "T3D/gameBase/gameProcess.h"
 34
 35struct TickCacheHead
 36{
 37   TickCacheEntry * oldest;
 38   TickCacheEntry * newest;
 39   TickCacheEntry * next;
 40   U32 numEntry;
 41};
 42
 43namespace
 44{
 45   FreeListChunker<TickCacheHead>  sgTickCacheHeadStore;
 46   FreeListChunker<TickCacheEntry> sgTickCacheEntryStore;
 47   FreeListChunker<Move>           sgMoveStore;
 48
 49   static TickCacheHead * allocHead() { return sgTickCacheHeadStore.alloc(); }
 50   static void freeHead(TickCacheHead * head) { sgTickCacheHeadStore.free(head); }
 51
 52   static TickCacheEntry * allocEntry() { return sgTickCacheEntryStore.alloc(); }
 53   static void freeEntry(TickCacheEntry * entry) { sgTickCacheEntryStore.free(entry); }
 54
 55   static Move * allocMove() { return sgMoveStore.alloc(); }
 56   static void freeMove(Move * move) { sgMoveStore.free(move); }
 57}
 58
 59//----------------------------------------------------------------------------
 60
 61TickCache::~TickCache()
 62{
 63   if (mTickCacheHead)
 64   {
 65      setCacheSize(0);
 66      freeHead(mTickCacheHead);
 67      mTickCacheHead = NULL;
 68   }
 69}
 70
 71Move * TickCacheEntry::allocateMove()
 72{
 73   return allocMove();
 74}
 75
 76TickCacheEntry * TickCache::addCacheEntry()
 77{
 78   // Add a new entry, creating head if needed
 79   if (!mTickCacheHead)
 80   {
 81      mTickCacheHead = allocHead();
 82      mTickCacheHead->newest = mTickCacheHead->oldest = mTickCacheHead->next = NULL;
 83      mTickCacheHead->numEntry = 0;
 84   }
 85   if (!mTickCacheHead->newest)
 86   {
 87      mTickCacheHead->newest = mTickCacheHead->oldest = allocEntry();
 88   }
 89   else
 90   {
 91      mTickCacheHead->newest->next = allocEntry();
 92      mTickCacheHead->newest = mTickCacheHead->newest->next;
 93   }
 94   mTickCacheHead->newest->next = NULL;
 95   mTickCacheHead->newest->move = NULL;
 96   mTickCacheHead->numEntry++;
 97   return mTickCacheHead->newest;
 98}
 99
100void TickCache::setCacheSize(S32 len)
101{
102   // grow cache to len size, adding to newest side of the list
103   while (!mTickCacheHead || mTickCacheHead->numEntry < len)
104      addCacheEntry();
105   // shrink tick cache down to given size, popping off oldest entries first
106   while (mTickCacheHead && mTickCacheHead->numEntry > len)
107      dropOldest();
108}
109
110void TickCache::dropOldest()
111{
112   AssertFatal(mTickCacheHead->oldest,"Popping off too many tick cache entries");
113   TickCacheEntry * oldest = mTickCacheHead->oldest;
114   mTickCacheHead->oldest = oldest->next;
115   if (oldest->move)
116      freeMove(oldest->move);
117   freeEntry(oldest);
118   mTickCacheHead->numEntry--;
119   if (mTickCacheHead->numEntry < 2)
120      mTickCacheHead->newest = mTickCacheHead->oldest;
121}
122
123void TickCache::dropNextOldest()
124{
125   AssertFatal(mTickCacheHead->oldest && mTickCacheHead->numEntry>1,"Popping off too many tick cache entries");
126   TickCacheEntry * oldest = mTickCacheHead->oldest;
127   TickCacheEntry * nextoldest = mTickCacheHead->oldest->next;
128   oldest->next = nextoldest->next;
129   if (nextoldest->move)
130      freeMove(nextoldest->move);
131   freeEntry(nextoldest);
132   mTickCacheHead->numEntry--;
133   if (mTickCacheHead->numEntry==1)
134      mTickCacheHead->newest = mTickCacheHead->oldest;
135}
136
137void TickCache::ageCache(S32 numToAge, S32 len)
138{
139   AssertFatal(mTickCacheHead,"No tick cache head");
140   AssertFatal(mTickCacheHead->numEntry>=numToAge,"Too few entries!");
141   AssertFatal(mTickCacheHead->numEntry>numToAge,"Too few entries!");
142
143   while (numToAge--)
144      dropOldest();
145   while (mTickCacheHead->numEntry>len)
146      dropNextOldest();
147   while (mTickCacheHead->numEntry<len)
148      addCacheEntry();
149}
150
151void TickCache::beginCacheList()
152{
153   // get ready iterate from oldest to newest entry
154   if (mTickCacheHead)
155      mTickCacheHead->next = mTickCacheHead->oldest;
156   // if no head, that's ok, we'll just add entries as we go
157}
158
159TickCacheEntry * TickCache::incCacheList(bool addIfNeeded)
160{
161   // continue iterating through cache, returning current entry
162   // we'll add new entries if need be
163   TickCacheEntry * ret = NULL;
164   if (mTickCacheHead && mTickCacheHead->next)
165   {
166      ret = mTickCacheHead->next;
167      mTickCacheHead->next = mTickCacheHead->next->next;
168   }
169   else if (addIfNeeded)
170   {
171      addCacheEntry();
172      ret = mTickCacheHead->newest;
173   }
174   return ret;
175}
176