// ManagedArray.h : Interface of the CManagedArray class // // 'Managed Array' structure // ///////////////////////////////////////////////////////////////////////////// #ifndef _MANAGED_ARRAY_H #define _MANAGED_ARRAY_H ///////////////////////////////////////////////////////////////////////////// #include "UseBitmap.h" ///////////////////////////////////////////////////////////////////////////// // General Managed Array handler class CManagedArrayGeneral { private: // A use bitmap used to control allocation within the array CUseBitmapGeneral bitmap; // Size of each element of the array UINT32 element_size; // Length of array UINT32 array_len; // Ref. to the created array char* array; // Indication of wether additional arrays may be created when this one fills up bool create_links; // The next array in the group (when this array is full, another one can be automatically // created on the fly to accomodate the allocation request CManagedArrayGeneral* next_array; public: CManagedArrayGeneral(void) { array = NULL; next_array = NULL; } ~CManagedArrayGeneral(void) { delete[] array; // Clean up all linked arrays CManagedArrayGeneral* arr = next_array; while (arr) { CManagedArrayGeneral* arr_next = arr->next_array; delete arr; arr = arr_next; } } protected: ///////////////////////////////////////////////////////////////////////// // Calculate number of bytes needed to hold specified number of elements, // rounded to the next 32 bit boundry // // Parameters: // length - Number of elements to store in the managed array // size - Maximum size of each element of the array // // Returns: // Number of bytes required // UINT32 BytesRequired(const UINT32 length, const UINT32 size) { return (length * size); } ///////////////////////////////////////////////////////////////////////// // Create a managed array // // Parameters: // length - Number of elements to store in the managed array // size - Maximuum size of each element of the array // link - If true then additional arrays shall be created on the fly as this // one fills up. false = Additional arrays shall not be created // // Returns: // Success / Failure - true = fail, false = success // bool CreateArray(const UINT32 length, const UINT32 size, const bool link) { bool fail = true; element_size = size; array_len = length; create_links = link; array = new(char[BytesRequired(length, size)]); if (array) { fail = bitmap.AllocateBitmap(length); if (!fail) { delete[] array; array = NULL; } } return fail; } ///////////////////////////////////////////////////////////////////////// // Allocate element // // Parameters; // size - Size to allocate. Tnis must be less than or equal to the size // specified at initialisation // // Returns: // Address of allocated element. NULL if element could not be allocated // void* AllocElement(const UINT32 size) { void* addr = NULL; if (size <= element_size) { CManagedArrayGeneral* arr = this; bool stop = false; do { UINT32 slot = arr->bitmap.FindFreeBitGen(true); if (slot) { // Zero-base returned slot number slot--; addr = arr->array + (arr->element_size * slot); stop = true; } else { // No space in this array - if we have a link then try that if (arr->next_array) { arr = arr->next_array; } else { // No linked array available. If we can, create one if (arr->create_links) { arr->next_array = new (CManagedArrayGeneral); if (arr->next_array) { // Array created - initialise it if (!arr->next_array->CreateArray(arr->element_size, arr->array_len, arr->create_links)) { // Skip to the newly created array arr = arr->next_array; } else { // Failed - tidy up delete arr->next_array; arr->next_array = NULL; stop = true; } } else { stop = true; } } } } } while (!stop); } return addr; } ///////////////////////////////////////////////////////////////////////// // Free element // // Parameters; // addr - Address to de-allocate // // Returns: // Success status. false = success. true = error // bool FreeElement(const void* const addr) { bool fail = true; CManagedArrayGeneral* arr = this; bool stop = false; // Convert the address to an element number in the array do { if (addr >= arr->array) { UINT32 element = ((UINT32)addr - (UINT32)arr->array) / arr->element_size; if (element < arr->array_len) { // Address seems to be valid - de-allocate this element arr->bitmap.ResetBit(element); fail = false; stop = true; } } if (fail) { // Failed to de-allocate. If there are any linked arrays ten try them arr = arr->next_array; stop = !arr; } } while (!stop); return fail; } }; // End of CManagedArrayGeneral ///////////////////////////////////////////////////////////////////////////// #endif /////////////////////////////////////////////////////////////////////////////