00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #if defined(_MSC_VER)
00025 #pragma once
00026 #endif
00027
00028 #ifndef PBRT_CORE_MEMORY_H
00029 #define PBRT_CORE_MEMORY_H
00030
00031
00032 #include "pbrt.h"
00033 #include "parallel.h"
00034
00035
00036 class ReferenceCounted {
00037 public:
00038 ReferenceCounted() { nReferences = 0; }
00039 AtomicInt32 nReferences;
00040 private:
00041 ReferenceCounted(const ReferenceCounted &);
00042 ReferenceCounted &operator=(const ReferenceCounted &);
00043 };
00044
00045
00046 template <typename T> class Reference {
00047 public:
00048
00049 Reference(T *p = NULL) {
00050 ptr = p;
00051 if (ptr) AtomicAdd(&ptr->nReferences, 1);
00052 }
00053 Reference(const Reference<T> &r) {
00054 ptr = r.ptr;
00055 if (ptr) AtomicAdd(&ptr->nReferences, 1);
00056 }
00057 Reference &operator=(const Reference<T> &r) {
00058 if (r.ptr) AtomicAdd(&r.ptr->nReferences, 1);
00059 if (ptr && AtomicAdd(&ptr->nReferences, -1) == 0) delete ptr;
00060 ptr = r.ptr;
00061 return *this;
00062 }
00063 Reference &operator=(T *p) {
00064 if (p) AtomicAdd(&p->nReferences, 1);
00065 if (ptr && AtomicAdd(&ptr->nReferences, -1) == 0) delete ptr;
00066 ptr = p;
00067 return *this;
00068 }
00069 ~Reference() {
00070 if (ptr && AtomicAdd(&ptr->nReferences, -1) == 0)
00071 delete ptr;
00072 }
00073 T *operator->() { return ptr; }
00074 const T *operator->() const { return ptr; }
00075 operator bool() const { return ptr != NULL; }
00076 const T *GetPtr() const { return ptr; }
00077 private:
00078 T *ptr;
00079 };
00080
00081
00082 void *AllocAligned(size_t size);
00083 template <typename T> T *AllocAligned(uint32_t count) {
00084 return (T *)AllocAligned(count * sizeof(T));
00085 }
00086
00087
00088 void FreeAligned(void *);
00089 class MemoryArena {
00090 public:
00091
00092 MemoryArena(uint32_t bs = 32768) {
00093 blockSize = bs;
00094 curBlockPos = 0;
00095 currentBlock = AllocAligned<char>(blockSize);
00096 }
00097 ~MemoryArena() {
00098 FreeAligned(currentBlock);
00099 for (uint32_t i = 0; i < usedBlocks.size(); ++i)
00100 FreeAligned(usedBlocks[i]);
00101 for (uint32_t i = 0; i < availableBlocks.size(); ++i)
00102 FreeAligned(availableBlocks[i]);
00103 }
00104 void *Alloc(uint32_t sz) {
00105
00106 sz = ((sz + 15) & (~15));
00107 if (curBlockPos + sz > blockSize) {
00108
00109 usedBlocks.push_back(currentBlock);
00110 if (availableBlocks.size() && sz <= blockSize) {
00111 currentBlock = availableBlocks.back();
00112 availableBlocks.pop_back();
00113 }
00114 else
00115 currentBlock = AllocAligned<char>(max(sz, blockSize));
00116 curBlockPos = 0;
00117 }
00118 void *ret = currentBlock + curBlockPos;
00119 curBlockPos += sz;
00120 return ret;
00121 }
00122 template<typename T> T *Alloc(uint32_t count = 1) {
00123 T *ret = (T *)Alloc(count * sizeof(T));
00124 for (uint32_t i = 0; i < count; ++i)
00125 new (&ret[i]) T();
00126 return ret;
00127 }
00128 void FreeAll() {
00129 curBlockPos = 0;
00130 while (usedBlocks.size()) {
00131 #ifndef NDEBUG
00132 memset(usedBlocks.back(), 0xfa, blockSize);
00133 #endif
00134 availableBlocks.push_back(usedBlocks.back());
00135 usedBlocks.pop_back();
00136 }
00137 }
00138 private:
00139
00140 uint32_t curBlockPos, blockSize;
00141 char *currentBlock;
00142 vector<char *> usedBlocks, availableBlocks;
00143 };
00144
00145
00146 template <typename T, int logBlockSize> class BlockedArray {
00147 public:
00148
00149 BlockedArray(uint32_t nu, uint32_t nv, const T *d = NULL) {
00150 uRes = nu;
00151 vRes = nv;
00152 uBlocks = RoundUp(uRes) >> logBlockSize;
00153 uint32_t nAlloc = RoundUp(uRes) * RoundUp(vRes);
00154 data = AllocAligned<T>(nAlloc);
00155 for (uint32_t i = 0; i < nAlloc; ++i)
00156 new (&data[i]) T();
00157 if (d)
00158 for (uint32_t v = 0; v < vRes; ++v)
00159 for (uint32_t u = 0; u < uRes; ++u)
00160 (*this)(u, v) = d[v * uRes + u];
00161 }
00162 uint32_t BlockSize() const { return 1 << logBlockSize; }
00163 uint32_t RoundUp(uint32_t x) const {
00164 return (x + BlockSize() - 1) & ~(BlockSize() - 1);
00165 }
00166 uint32_t uSize() const { return uRes; }
00167 uint32_t vSize() const { return vRes; }
00168 ~BlockedArray() {
00169 for (uint32_t i = 0; i < uRes * vRes; ++i)
00170 data[i].~T();
00171 FreeAligned(data);
00172 }
00173 uint32_t Block(uint32_t a) const { return a >> logBlockSize; }
00174 uint32_t Offset(uint32_t a) const { return (a & (BlockSize() - 1)); }
00175 T &operator()(uint32_t u, uint32_t v) {
00176 uint32_t bu = Block(u), bv = Block(v);
00177 uint32_t ou = Offset(u), ov = Offset(v);
00178 uint32_t offset = BlockSize() * BlockSize() * (uBlocks * bv + bu);
00179 offset += BlockSize() * ov + ou;
00180 return data[offset];
00181 }
00182 const T &operator()(uint32_t u, uint32_t v) const {
00183 uint32_t bu = Block(u), bv = Block(v);
00184 uint32_t ou = Offset(u), ov = Offset(v);
00185 uint32_t offset = BlockSize() * BlockSize() * (uBlocks * bv + bu);
00186 offset += BlockSize() * ov + ou;
00187 return data[offset];
00188 }
00189 void GetLinearArray(T *a) const {
00190 for (uint32_t v = 0; v < vRes; ++v)
00191 for (uint32_t u = 0; u < uRes; ++u)
00192 *a++ = (*this)(u, v);
00193 }
00194 private:
00195
00196 T *data;
00197 uint32_t uRes, vRes, uBlocks;
00198 };
00199
00200
00201
00202 #endif // PBRT_CORE_MEMORY_H