fork(1) download
  1. #include <algorithm>
  2. #include <cassert>
  3. #include <initializer_list>
  4. #include <iostream>
  5. #include <iterator>
  6. #include <memory>
  7. #include <vector>
  8.  
  9. using namespace std;
  10.  
  11. // All the JointPool / JointAllocator code would be 'library' code in practice and should be
  12. // compared to the code required to implement joint allocation in the compiler. Once the library
  13. // code is written it can be used fairly simply as demonstrated in the 'Usage' section below.
  14.  
  15. template <typename T>
  16. struct JointPoolSizeTraits;
  17.  
  18. struct JointPool {
  19. explicit JointPool(size_t totalBytes)
  20. : m_jointBegin(new char[totalBytes]),
  21. m_jointCurrent(m_jointBegin.get()),
  22. m_jointEnd(m_jointBegin.get() + totalBytes) {}
  23. unique_ptr<char[]> m_jointBegin;
  24. char* m_jointCurrent = nullptr;
  25. char* m_jointEnd = nullptr;
  26.  
  27. void* allocate(size_t bytes) {
  28. if (m_jointCurrent + bytes <= m_jointEnd) {
  29. auto p = m_jointCurrent;
  30. m_jointCurrent += bytes;
  31. return p;
  32. }
  33. assert(false);
  34. return nullptr;
  35. }
  36. };
  37.  
  38. template <typename... Ts>
  39. size_t GetJointPoolSize() {
  40. return 0;
  41. }
  42.  
  43. template <typename T, typename... Ts, typename U, typename... Us>
  44. size_t GetJointPoolSize(U&& arg, Us&&... args) {
  45. return JointPoolSizeTraits<T>::size(arg) + GetJointPoolSize<Ts...>(args...);
  46. }
  47.  
  48. template <class T>
  49. struct JointAllocator {
  50. typedef T value_type;
  51.  
  52. JointAllocator(JointPool* pool) : m_pool(pool) {}
  53. JointAllocator(const JointAllocator&) = default;
  54.  
  55. template <class U>
  56. JointAllocator(const JointAllocator<U>& other)
  57. : m_pool(other.m_pool) {}
  58.  
  59. T* allocate(std::size_t n) { return reinterpret_cast<T*>(m_pool->allocate(n * sizeof(T))); }
  60. void deallocate(T* p, std::size_t n) {}
  61.  
  62. JointPool* m_pool = nullptr;
  63. };
  64.  
  65. template <typename T>
  66. using JointVector = vector<T, JointAllocator<T>>;
  67.  
  68. template <typename T>
  69. struct JointPoolSizeTraits<JointVector<T>> {
  70. static constexpr size_t size(size_t n) { return sizeof(T*) + sizeof(T) * n; }
  71. };
  72.  
  73. // Usage - with library support for joint allocation, usage might look something like this:
  74.  
  75. struct Vector3 {
  76. float x, y, z;
  77. };
  78.  
  79. struct Mesh {
  80. private:
  81. JointPool pool;
  82.  
  83. public:
  84. template <typename ItPs, typename ItIs>
  85. Mesh(ItPs firstP, ItPs lastP, ItIs firstI, ItIs lastI)
  86. : pool(GetJointPoolSize<decltype(positions), decltype(indices)>(distance(firstP, lastP),
  87. distance(firstI, lastI))),
  88. positions(firstP, lastP, &pool),
  89. indices(firstI, lastI, &pool) {}
  90.  
  91. Mesh(initializer_list<Vector3> ps, initializer_list<int> is)
  92. : Mesh(begin(ps), end(ps), begin(is), end(is)) {}
  93.  
  94. JointVector<Vector3> positions;
  95. JointVector<int> indices;
  96. };
  97.  
  98. ostream& operator<<(ostream& os, const Mesh& m) {
  99. for (const auto& pos : m.positions) os << "(" << pos.x << ", " << pos.y << ", " << pos.z << "), ";
  100. for (const auto& index : m.indices) os << index << ", ";
  101. return os << endl;
  102. }
  103.  
  104. int main() {
  105. // initialize a Mesh with explicit verts and indices
  106. Mesh myMesh{{{0.f, 0.f, 0.f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}}, {0, 1, 2}};
  107.  
  108. // initialize a Mesh with iterator pairs
  109. Mesh mySecondMesh{begin(myMesh.positions), end(myMesh.positions), begin(myMesh.indices),
  110. end(myMesh.indices)};
  111.  
  112. cout << myMesh << mySecondMesh;
  113. }
  114.  
Success #stdin #stdout 0s 3432KB
stdin
Standard input is empty
stdout
(0, 0, 0), (1, 0, 0), (0, 1, 0), 0, 1, 2, 
(0, 0, 0), (1, 0, 0), (0, 1, 0), 0, 1, 2,