00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef _terimber_byterep_hpp_
00029 #define _terimber_byterep_hpp_
00030
00031 #include "base/memory.hpp"
00032 #include "smart/byterep.h"
00033
00034 BEGIN_TERIMBER_NAMESPACE
00035 #pragma pack(4)
00036
00037
00038
00039
00040
00041
00042 template < unsigned char N >
00043 byte_tank< N >::byte_tank(byte_allocator& all) : _states(0)
00044 {
00045 _head = (char*)all.allocate(ROOMS * LENGTH);
00046 }
00047
00048 template < unsigned char N >
00049 bool
00050 byte_tank< N >::full() const
00051 {
00052 return _states == 0;
00053 }
00054
00055 template < unsigned char N >
00056 bool
00057 byte_tank< N >::empty() const
00058 {
00059 return _states == ~(rooms_type_t)0;
00060 }
00061
00062 template < unsigned char N >
00063 char*
00064 byte_tank< N >::get_chunk()
00065 {
00066 #ifdef _DEBUG
00067 if (empty())
00068 {
00069 assert(false);
00070 return 0;
00071 }
00072 #endif
00073
00074
00075 unsigned char offset = 0x0;
00076
00077 rooms_type_t lowbit = ~_states & ~(~_states - 1);
00078 _states |= lowbit;
00079
00080 if (!(lowbit & 0x00000000ffffffff))
00081 {
00082 offset += 32;
00083 lowbit >>= 32;
00084 }
00085
00086 if (!(lowbit & 0x000000000000ffff))
00087 {
00088 offset += 16;
00089 lowbit >>= 16;
00090 }
00091
00092 if (!(lowbit & 0x00000000000000ff))
00093 {
00094 offset += 8;
00095 lowbit >>= 8;
00096 }
00097
00098 if (!(lowbit & 0x000000000000000f))
00099 {
00100 offset += 4;
00101 lowbit >>= 4;
00102 }
00103
00104 switch (lowbit & 0x000000000000000f)
00105 {
00106 case 0:
00107 assert(false);
00108 break;
00109 case 1:
00110 case 3:
00111 case 5:
00112 case 7:
00113 case 9:
00114 case 11:
00115 case 13:
00116 case 15:
00117 break;
00118 case 2:
00119 case 6:
00120 case 10:
00121 case 14:
00122 offset += 1;
00123 break;
00124 case 4:
00125 case 12:
00126 offset += 2;
00127 break;
00128 case 8:
00129 offset += 3;
00130 break;
00131 }
00132
00133
00134 char* ret = _head + (offset * LENGTH);
00135 *ret = (char)N;
00136 *(ret + 1) = (char)offset;
00137
00138 return ret;
00139 }
00140
00141 template < unsigned char N >
00142 void
00143 byte_tank< N >::put_chunk(char* ptr)
00144 {
00145 unsigned char* chunk = (unsigned char*)(ptr - 4);
00146 unsigned char offset = *(chunk + 1);
00147
00148 #ifdef _DEBUG
00149 if (*chunk != N)
00150 {
00151 assert(false);
00152 return;
00153 }
00154
00155 if (offset > 63)
00156 {
00157 assert(false);
00158 return;
00159 }
00160 #endif
00161
00162 rooms_type_t one = 1;
00163 rooms_type_t mask = one << offset;
00164
00165 #ifdef _DEBUG
00166 if (!(_states & mask))
00167 {
00168 assert(false);
00169 return;
00170 }
00171 #endif
00172
00173 _states &= ~mask;
00174 }
00175
00176 template < unsigned char N >
00177 void
00178 byte_tank< N >::reset()
00179 {
00180 _states = 0;
00181 }
00182
00183 template < unsigned char N, ub4_t M >
00184 byte_backet< N, M >::byte_backet() : _all( byte_tank< N >::LENGTH * M), _page(0)
00185 {
00186 reset();
00187 }
00188
00189 template < unsigned char N, ub4_t M >
00190 byte_backet< N, M >::~byte_backet()
00191 {
00192 }
00193
00194 template < unsigned char N, ub4_t M >
00195 char*
00196 byte_backet< N, M >::allocate()
00197 {
00198 char* ret = 0;
00199
00200 while (_page < M && _pages[_page] && _pages[_page]->empty())
00201 ++_page;
00202
00203 if (_page == M)
00204 return 0;
00205
00206 if (!_pages[_page])
00207 {
00208 _pages[_page] = new (_all.allocate(sizeof(byte_tank< N >))) byte_tank< N >(_all);
00209 if (!_pages[_page])
00210 return 0;
00211 }
00212
00213 ret = _pages[_page]->get_chunk();
00214
00215 #ifdef _DEBUG
00216 assert(ret != 0);
00217 #endif
00218
00219 *(ret + 2) = (char)((_page & 0xff00) >> 8);
00220 *(ret + 3) = (char)(_page & 0x00ff);
00221
00222 ret += 4;
00223 return ret;
00224 }
00225
00226 template < unsigned char N, ub4_t M >
00227 void
00228 byte_backet< N, M >::deallocate(char* ptr)
00229 {
00230 unsigned char* backet = (unsigned char*)ptr - 4;
00231 #ifdef _DEBUG
00232 if (*backet != N)
00233 {
00234 assert(false);
00235 return;
00236 }
00237 #endif
00238 unsigned short page_high = (unsigned short)*(backet + 2) & 0x00ff;
00239 unsigned short page_low = (unsigned short)*(backet + 3) & 0x00ff;
00240 unsigned short p = (page_high << 8 | page_low);
00241
00242 #ifdef _DEBUG
00243 if (p >= M || !_pages[p])
00244 {
00245 assert(false);
00246 return;
00247 }
00248 #endif
00249 _pages[p]->put_chunk(ptr);
00250 if (p < _page)
00251 _page = p;
00252 }
00253
00254 template < unsigned char N, ub4_t M >
00255 void
00256 byte_backet< N, M >::reset()
00257 {
00258 memset(_pages, 0, sizeof(void*) * M);
00259 _all.clear_extra();
00260 _page = 0;
00261 }
00262
00263 template < unsigned char N, ub4_t M >
00264 void
00265 byte_backet< N, M >::release()
00266 {
00267 for (ub2_t p = M; p > 0; --p)
00268 if (_pages[p - 1] && !_pages[p - 1]->full())
00269 return;
00270
00271 reset();
00272 }
00273
00275 inline
00276 char*
00277 byte_repository::allocate(size_t len)
00278 {
00279 if (!len)
00280 return 0;
00281
00282 char* ret = 0;
00283 size_t rounded_size = 4;
00284 size_t shift = len >> rounded_size;
00285
00286 while (shift > 0)
00287 {
00288 ++rounded_size;
00289 shift >>= 1;
00290 }
00291
00292 switch (rounded_size)
00293 {
00294 case 4:
00295 if (ret = _backet4.allocate())
00296 break;
00297 case 5:
00298 if (ret = _backet5.allocate())
00299 break;
00300 case 6:
00301 if (ret = _backet6.allocate())
00302 break;
00303 case 7:
00304 if (ret = _backet7.allocate())
00305 break;
00306 case 8:
00307 if (ret = _backet8.allocate())
00308 break;
00309 case 9:
00310 if (ret = _backet9.allocate())
00311 break;
00312 case 10:
00313 if (ret = _backet10.allocate())
00314 break;
00315 case 11:
00316 if (ret = _backet11.allocate())
00317 break;
00318 case 12:
00319 if (ret = _backet12.allocate())
00320 break;
00321 case 13:
00322 if (ret = _backet13.allocate())
00323 break;
00324 default:
00325 ret = new char[len + 4];
00326 if (ret)
00327 {
00328 memset(ret, 0, 4);
00329 ret += 4;
00330 }
00331 }
00332
00333 return ret;
00334 }
00335
00336 inline
00337 void
00338 byte_repository::deallocate(char* ptr)
00339 {
00340 unsigned char* backet = (unsigned char*)ptr - 4;
00341 switch (*backet)
00342 {
00343 case 4:
00344 _backet4.deallocate(ptr);
00345 break;
00346 case 5:
00347 _backet5.deallocate(ptr);
00348 break;
00349 case 6:
00350 _backet6.deallocate(ptr);
00351 break;
00352 case 7:
00353 _backet7.deallocate(ptr);
00354 break;
00355 case 8:
00356 _backet8.deallocate(ptr);
00357 break;
00358 case 9:
00359 _backet9.deallocate(ptr);
00360 break;
00361 case 10:
00362 _backet10.deallocate(ptr);
00363 break;
00364 case 11:
00365 _backet11.deallocate(ptr);
00366 break;
00367 case 12:
00368 _backet12.deallocate(ptr);
00369 break;
00370 case 13:
00371 _backet13.deallocate(ptr);
00372 break;
00373 case 0:
00374 delete [] backet;
00375 break;
00376 default:
00377 assert(false);
00378 }
00379 }
00380
00382 inline
00383 void
00384 byte_repository::reset()
00385 {
00386 _backet4.reset();
00387 _backet5.reset();
00388 _backet6.reset();
00389 _backet7.reset();
00390 _backet8.reset();
00391 _backet9.reset();
00392 _backet10.reset();
00393 _backet11.reset();
00394 _backet12.reset();
00395 _backet13.reset();
00396 }
00397
00398
00400 inline
00401 bool
00402 byte_repository_factory::is_ready() const
00403 {
00404 return _repository != 0;
00405 }
00406
00407 inline
00408 byte_repository*
00409 byte_repository_factory::operator->()
00410 {
00411 assert(_repository != 0);
00412 return _repository;
00413 }
00414
00415 #pragma pack()
00416 END_TERIMBER_NAMESPACE
00417
00418 #endif // _terimber_byterep_hpp_