RawStorage.h
Go to the documentation of this file.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
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #ifndef __RAWSTORAGE_H_8AC69FC602CD2C__
00041 #define __RAWSTORAGE_H_8AC69FC602CD2C__
00042
00043
00044 #include <stdint.h>
00045
00046 #include "debug.h"
00047 #include "config/type_traits/SmallestUnsignedTypeSelector.h"
00048
00049
00050 namespace object {
00051
00073 template <uint64_t size>
00074 class RawStorage {
00075 public:
00077 typedef typename SmallestUnsignedTypeSelector<size>::type SizeT;
00078
00079 protected:
00081 uint8_t data [size];
00082
00084 SizeT first_allocated;
00085
00087 struct AllocInfo {
00089 SizeT block_length;
00090
00092 SizeT next_allocated;
00093 };
00094
00096 AllocInfo * get_ai(SizeT offset) {
00097 return reinterpret_cast<AllocInfo *>(data + offset);
00098 }
00099
00107 SizeT * find_first_fit(SizeT bytes, SizeT & to_allocate) {
00108 if (!bytes || bytes > size - sizeof(AllocInfo))
00109 return 0;
00110
00111 if (bytes + sizeof(AllocInfo) <= first_allocated) {
00112
00113 to_allocate = 0;
00114 return &first_allocated;
00115 } else {
00116
00117
00118
00119 bytes += 2 * sizeof(AllocInfo);
00120
00121
00122 SizeT curr_ai = first_allocated;
00123 AllocInfo * ai = get_ai(curr_ai);
00124 while (curr_ai < size) {
00125
00126 if (curr_ai + ai->block_length + bytes <= ai->next_allocated) {
00127 to_allocate = curr_ai + sizeof(AllocInfo) + ai->block_length;
00128 return &ai->next_allocated;
00129 }
00130
00131 curr_ai = ai->next_allocated;
00132 ai = get_ai(curr_ai);
00133 }
00134
00135
00136
00137 FAMOUSO_ASSERT(curr_ai == size);
00138
00139
00140 return 0;
00141 }
00142 }
00143
00150 SizeT * find_allocated_block(uint8_t * p) {
00151 p -= sizeof(AllocInfo);
00152
00153 SizeT * prev_ai_na_p = &first_allocated;
00154 AllocInfo * ai = get_ai(first_allocated);
00155 while (*prev_ai_na_p < size) {
00156
00157 if (ai == reinterpret_cast<AllocInfo *>(p))
00158 return prev_ai_na_p;
00159
00160 prev_ai_na_p = &ai->next_allocated;
00161 ai = get_ai(ai->next_allocated);
00162 }
00163
00164
00165
00166 FAMOUSO_ASSERT(*prev_ai_na_p == size);
00167
00168 return 0;
00169 }
00170
00171 public:
00173 RawStorage() : first_allocated(size) {
00174 }
00175
00181 uint8_t * alloc(SizeT bytes) {
00182 SizeT * next_allocated;
00183 SizeT to_allocate;
00184 uint8_t * mem;
00185
00186
00187 next_allocated = find_first_fit(bytes, to_allocate);
00188
00189 if (next_allocated) {
00190
00191 AllocInfo * ai = get_ai(to_allocate);
00192 ai->block_length = bytes;
00193 ai->next_allocated = *next_allocated;
00194
00195
00196 *next_allocated = to_allocate;
00197
00198
00199 mem = reinterpret_cast<uint8_t *>(ai) + sizeof(AllocInfo);
00200
00201 #ifdef RAWSTORAGE_LOG_USAGE
00202 ::logging::log::emit() << PROGMEMSTRING("RawStorage: alloc ")
00203 << ::logging::log::dec << (int)(bytes)
00204 << PROGMEMSTRING(" bytes -> offset ") << (int)to_allocate
00205 << ::logging::log::hex << PROGMEMSTRING(", address ")
00206 << reinterpret_cast<unsigned long>(mem) << ::logging::log::endl;
00207 #endif
00208 } else {
00209
00210 mem = 0;
00211 #ifdef RAWSTORAGE_LOG_USAGE
00212 ::logging::log::emit() << PROGMEMSTRING("RawStorage: alloc ")
00213 << ::logging::log::dec << (int)(bytes)
00214 << PROGMEMSTRING(" bytes failed") << ::logging::log::endl;
00215
00216 #endif
00217 }
00218
00219 #ifdef RAWSTORAGE_FULL_MEM_INFO
00220 print_mem_info();
00221 #endif
00222
00223 return mem;
00224 }
00225
00232 void free(uint8_t * p) {
00233 SizeT * next_allocated = find_allocated_block(p);
00234
00235
00236 FOR_FAMOUSO_ASSERT_ONLY(bool valid_pointer = next_allocated);
00237 #ifdef RAWSTORAGE_LOG_USAGE
00238 if (!valid_pointer) {
00239 ::logging::log::emit() << PROGMEMSTRING("RawStorage: free address ")
00240 << ::logging::log::hex << reinterpret_cast<unsigned long>(p)
00241 << PROGMEMSTRING(" failed. Not alloced or freed previously.")
00242 << ::logging::log::endl;
00243 }
00244 #endif
00245 FAMOUSO_ASSERT(valid_pointer);
00246
00247
00248 AllocInfo * ai_to_free = get_ai(*next_allocated);
00249
00250
00251 *next_allocated = ai_to_free->next_allocated;
00252
00253 #ifdef RAWSTORAGE_LOG_USAGE
00254 ::logging::log::emit() << PROGMEMSTRING("RawStorage: free address ")
00255 << ::logging::log::hex << reinterpret_cast<unsigned long>(p)
00256 << PROGMEMSTRING(", offset ") << ::logging::log::dec
00257 << (int)(p - data - sizeof(AllocInfo))
00258 << PROGMEMSTRING(" (") << (int)ai_to_free->block_length
00259 << PROGMEMSTRING(" bytes)") << ::logging::log::endl;
00260 #endif
00261 #ifdef RAWSTORAGE_FULL_MEM_INFO
00262 print_mem_info();
00263 #endif
00264 }
00265
00272 SizeT get_length(uint8_t * p) {
00273 AllocInfo * ai = get_ai(p - data - sizeof(AllocInfo));
00274 return ai->block_length;
00275 }
00276
00277 #ifdef RAWSTORAGE_FULL_MEM_INFO
00278 private:
00279
00281 void print_empty(SizeT first, SizeT last) {
00282 ::logging::log::emit() << ::logging::log::tab
00283 << ::logging::log::dec << (int)first << '-'
00284 << (int)last << PROGMEMSTRING(" Empty") << ::logging::log::endl;
00285 }
00286
00288 void print_ai(SizeT first) {
00289 AllocInfo * ai = get_ai(first);
00290 SizeT last = first + sizeof(AllocInfo) + ai->block_length - 1;
00291 ::logging::log::emit() << ::logging::log::tab
00292 << ::logging::log::dec << (int)first << '-' << (int)last
00293 << ::logging::log::hex << PROGMEMSTRING(" Allocated (address=")
00294 << reinterpret_cast<unsigned long>(data + first + sizeof(AllocInfo))
00295 << ::logging::log::dec << PROGMEMSTRING(", length=")
00296 << (int)ai->block_length
00297 << PROGMEMSTRING(", next_allocated=") << (int)ai->next_allocated
00298 << ')' << ::logging::log::endl;
00299
00300 }
00301
00302 public:
00304 void print_mem_info() {
00305 ::logging::log::emit() << PROGMEMSTRING("RawStorage: size=")
00306 << size << PROGMEMSTRING(", sizeof(SizeT)=") << sizeof(SizeT)
00307 << PROGMEMSTRING(", first_allocated=") << (int)first_allocated
00308 << ::logging::log::endl;
00309
00310 if (first_allocated != 0)
00311 print_empty(0, first_allocated - 1);
00312
00313 SizeT curr_ai = first_allocated;
00314 AllocInfo * ai = get_ai(curr_ai);
00315 while (curr_ai < size) {
00316
00317 print_ai(curr_ai);
00318
00319 SizeT behind = curr_ai + sizeof(AllocInfo) + ai->block_length;
00320 if (behind != ai->next_allocated)
00321 print_empty(behind, ai->next_allocated - 1);
00322
00323 curr_ai = ai->next_allocated;
00324 ai = get_ai(curr_ai);
00325 }
00326 FAMOUSO_ASSERT(curr_ai == size);
00327
00328 ::logging::log::emit() << ::logging::log::endl;
00329 }
00330 #endif
00331 };
00332
00333
00334
00335
00336 }
00337
00338
00339 #endif // __RAWSTORAGE_H_8AC69FC602CD2C__
00340