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