All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
MaterialIdGenerator.h
1 // Copyright eeGeo Ltd (2012-2014), All Rights Reserved
2 
3 #pragma once
4 
5 #include "Types.h"
6 #include "IdTypes.h"
7 #include "MaterialId.h"
8 #include "ICallback.h"
9 #include "SortKey.h"
10 #include <set>
11 
12 namespace Eegeo
13 {
14  namespace Rendering
15  {
16  namespace Materials
17  {
22  {
23  public:
25  : m_nextIdentifier(0)
26  , m_allocatedIdentifierCount(0)
27  , m_releaseCallback(this, &MaterialIdGenerator::ReleaseIdentifier)
28  {
29  }
30 
31  TMaterialId GetNextId()
32  {
33  return TMaterialId(Eegeo_NEW(TMaterialIdWrapper)(AllocateNextIdentifier(), m_releaseCallback));
34  }
35 
36  private:
37  void ReleaseIdentifier(const TMaterialIdWrapper::TValueType& identifier)
38  {
39  Eegeo_ASSERT(m_allocatedIdentifierCount > 0,
40  "Releasing material but no materials allocated. Indicates possible double release of identifier.\n");
41 
42  --m_allocatedIdentifierCount;
43  size_t valuesErased(m_identifiersUsed.erase(identifier));
44 
45  Eegeo_ASSERT(valuesErased == 1,
46  "Error: Consistency error in tracking material identifiers. Untracked identifier released.\n");
47  }
48 
49  TMaterialIdWrapper::TValueType AllocateNextIdentifier()
50  {
51  Eegeo_ASSERT(m_allocatedIdentifierCount < SortKey::MaxMaterialValue,
52  "Too many materials allocated, out of space to identify. Indicates possible identifier leak.\n");
53 
54  ++m_allocatedIdentifierCount;
55  TMaterialIdWrapper::TValueType identifierToUse(m_nextIdentifier);
56  std::pair<TIdentifiersUsed::iterator, bool> insertionResult(m_identifiersUsed.insert(identifierToUse));
57  Eegeo_ASSERT(insertionResult.second, "Error: reused material identifier in MaterialIdGenerator.\n");
58  m_nextIdentifier = FindNextUnusedIdentifierAfter(identifierToUse);
59 
60  return identifierToUse;
61  }
62 
63  TMaterialIdWrapper::TValueType FindNextUnusedIdentifierAfter(TMaterialIdWrapper::TValueType identifier)
64  {
65  do
66  {
67  identifier = (identifier + 1) % SortKey::MaxMaterialValue;
68  }
69  while(m_identifiersUsed.find(identifier) != m_identifiersUsed.end());
70 
71  return identifier;
72  }
73 
74  TMaterialIdWrapper::TValueType m_nextIdentifier;
75  int m_allocatedIdentifierCount;
77 
78  typedef std::set<TMaterialIdWrapper::TValueType> TIdentifiersUsed;
79  TIdentifiersUsed m_identifiersUsed;
80  };
81  }
82  }
83 }