public VSFreeSpaceManager(VSpace _sp) { Space = _sp; vm = Space.VM; long hdr_address = Space.GetFirstAddress(DEFS.POOL_FREE_SPACE); if (hdr_address == 0) { // Initialization // 1. Create H-block (header) H_Object = new VSAllocation(vm, DEFS.FBQE_HEADER_ADDRESS, DEFS.FBQE_HEADER_LENGTH_FULL, 0); H_Object.Write(0, DEFS.FBQE_HEADER_SIGNATURE); this.MAX = DEFS.FBQE_ALLOCATION_NUMBER; // Max number of FBQE this.FREE = MAX; this.FIRST = -1; this.LAST = -1; this.FIRST_Q = 0; this.LAST_Q = FREE - 1; // 2. Save H-block address (1st object) Space.SetFirstAddress(DEFS.POOL_FREE_SPACE, H_Object.DescriptorAddress); // 1st object // 3. Create 1st FBQE block F_Object = new VSAllocation(vm, H_Object.DescriptorAddress + H_Object.FullLength, (DEFS.FBQE_ALLOCATION_LENGTH + DEFS.BaseDescriptorLength), 0); // 4. Set initial size F_Object.SetSize(DEFS.FBQE_ALLOCATION_LENGTH); buffer = new byte[F_Object.Size]; // Create buffer // 5. Set references F_Object.PREV = H_Object.DescriptorAddress; H_Object.NEXT = F_Object.DescriptorAddress; // Address of the 1st block F-block // 6. Save F-block address (last object) Space.SetLastAddress(DEFS.POOL_FREE_SPACE, F_Object.DescriptorAddress); //last object // 1.3 Initiate Free queue for (int i = 0; i < FREE; i++) { CreateFBQE(i); } BuildBTrees(); // 1.4 Create initial FBQE long fa = F_Object.DescriptorAddress + F_Object.FullLength; // 1st free address AddFBQE(fa, (Space.vm.Size - fa), -1, -1); // Create 1st FBQE } else { H_Object = Space.GetAllocationByDescriptor(hdr_address); F_Object = Space.GetAllocationByDescriptor(H_Object.NEXT); byte[] b = H_Object.ReadBytes(0, FBQE_HEADER_LENGTH); this.v_MAX = VSLib.ConvertByteToInt(VSLib.GetByteArray(b, MAX_POS, MAX_LEN)); this.v_FREE = VSLib.ConvertByteToInt(VSLib.GetByteArray(b, FREE_POS, FREE_LEN)); this.v_FIRST = VSLib.ConvertByteToInt(VSLib.GetByteArray(b, FIRST_POS, FIRST_LEN)); this.v_LAST = VSLib.ConvertByteToInt(VSLib.GetByteArray(b, LAST_POS, LAST_LEN)); this.v_FIRST_Q = VSLib.ConvertByteToInt(VSLib.GetByteArray(b, FIRST_Q_POS, FIRST_Q_LEN)); this.v_LAST_Q = VSLib.ConvertByteToInt(VSLib.GetByteArray(b, LAST_Q_POS, LAST_Q_LEN)); buffer = F_Object.ReadBytes(0, F_Object.Size); // Read buffer BuildBTrees(); } }
/************************************************************************************/ /************************ Memory management (system methods)***********************/ /************************************************************************************/ /// <summary> /// Allocate space (system method) /// </summary> /// <param name="size">Allocation size</param> /// <param name="pool">Allocation pool. 0 if base_address != 0</param> /// <param name="generateID">True id ID is required. false if base_address != 0</param> /// <param name="base_address"> 1st allocated address (extend)</param> /// <returns> /// 0 - address /// 1 - ID (or 0) /// </returns> internal VSAllocation AllocateSpaceSegment(long size, short pool, bool generateID = true, VSAllocation base_alloc = null) { #if (DEBUG) __TIMER.START("alloc:main"); #endif if ((base_alloc != null) & ((pool != 0) | (generateID == true))) { throw new VSException(DEFS.E0020_INVALID_EXTENSION_PARAMETERS_ERROR_CODE); } //VSFreeSpaceManager.FBQE f; long alloc_addr = 0; long length_desc = (base_alloc == null)? DEFS.BaseDescriptorLength: DEFS.ExpansionDescriptorLength; // Descriptor length // Calculate allocation size) long length = size / DEFS.MIN_SPACE_ALLOCATION_CHUNK; if (length == 0) { length++; } else if ((length * DEFS.MIN_SPACE_ALLOCATION_CHUNK) < size) { length++; } long length_use = (length * DEFS.MIN_SPACE_ALLOCATION_CHUNK); length = length_use + length_desc; // Acquire free space location alloc_addr = FreeSpaceMgr.AcquireSpace(length); while (alloc_addr == 0) { if (vm.Extend() != 0) { throw new VSException(DEFS.E0013_SPACE_NOT_AVAILABLE_CODE, "Requested size: " + length.ToString()); } else { this.VerifySpaceChanges(); //Process new if space is successfully extended } alloc_addr = FreeSpaceMgr.AcquireSpace(length); } short new_pool = pool; // If base_address != 0 - take pool# from the root descriptor if (base_alloc != null) { new_pool = base_alloc.Pool; } // Create allocated space descriptor VSAllocation new_obj = new VSAllocation(vm, alloc_addr, length, new_pool); long last_obj = GetLastAddress(new_pool); VSAllocation prev_obj; if (base_alloc == null) { // Initial allocation #if (DEBUG) __TIMER.START("alloc:new_alloc"); #endif #if (DEBUG) __TIMER.START("alloc:gen_id"); #endif if (generateID) { new_obj.Id = key_manager.Add(new_obj); // Generate ID if required } #if (DEBUG) __TIMER.END("alloc:gen_id"); #endif if (last_obj == 0) { // First allocation for pool SetFirstAddress(new_pool, alloc_addr); SetLastAddress(new_pool, alloc_addr); } else { prev_obj = GetAllocationByDescriptor(last_obj); prev_obj.NEXT = new_obj.DescriptorAddress; new_obj.PREV = prev_obj.DescriptorAddress; SetLastAddress(new_pool, new_obj.DescriptorAddress); // New Last } #if (DEBUG) __TIMER.END("alloc:new_alloc"); #endif } else { //Extend #if (DEBUG) __TIMER.START("alloc:extend_obj"); #endif prev_obj = base_alloc; if (base_alloc.Chunk == 0) { base_alloc.Chunk = 1; new_obj.Chunk = -2; } else { prev_obj = GetAllocationByDescriptor(base_alloc.LAST); short ch = (short)(prev_obj.Chunk * -1); if (ch == DEFS.MAX_SPACE_ALLOCATION_CHUNKS) { throw new VSException(DEFS.E0021_MAX_ALLOCATION_CHUNKS_REACHED_CODE, "- " + DEFS.MAX_SPACE_ALLOCATION_CHUNKS.ToString()); } prev_obj.Chunk = ch; new_obj.Chunk = (short)((ch + 1) * -1); } base_alloc.LAST = new_obj.DescriptorAddress; // New pointer to last if (prev_obj.NEXT == 0) { prev_obj.NEXT = new_obj.DescriptorAddress; new_obj.PREV = prev_obj.DescriptorAddress; SetLastAddress(new_pool, new_obj.DescriptorAddress); // New last } else { VSAllocation next_obj = GetAllocationByDescriptor(prev_obj.NEXT); prev_obj.NEXT = new_obj.DescriptorAddress; new_obj.NEXT = next_obj.DescriptorAddress; new_obj.PREV = prev_obj.DescriptorAddress; next_obj.PREV = new_obj.DescriptorAddress; } #if (DEBUG) __TIMER.END("alloc:extend_obj"); #endif } if (base_alloc == null) { new_obj.SetSize(length_use); } else { base_alloc.SetSize(base_alloc.Size + length_use); } #if (DEBUG) __TIMER.END("alloc:main"); #endif return(new_obj); }