📄 pooled_allocator.h
字号:
mem_space::allocator_addr_t alloc_addr=0> Chunk* Pool<T,alloc_key,alloc_addr>::chunks = 0; // list of allocated chunks //////////////////////////////////////////////////////////////////// ////// Class Pool //////////////////////////////////////////////////////////////////// ////// ////// Pool Function Definitions start here. ////// //////////////////////////////////////////////////////////////////// // constructor template<class T, mem_space::allocator_key_t alloc_key, mem_space::allocator_addr_t alloc_addr>// Pool<alloc_type,alloc_key,alloc_addr>::Pool(const int& size) : Pool<T,alloc_key,alloc_addr>::Pool() : element_size(sizeof(T)), mem(pooled_allocator::num_of_pages, pooled_allocator::page_size) {#ifdef DEBUG std::cerr << __FILE__ << ':' << __LINE__ << ':' << " Pool() : constructor. " << std::endl;#endif // instantiate the first chunk on the chunk list if (!chunks) { grow(); } // chunks=0;// ref_count = 0; }; // constructor // destructor template<class T, mem_space::allocator_key_t alloc_key, mem_space::allocator_addr_t alloc_addr> Pool<T,alloc_key,alloc_addr>::~Pool() { // mem.~shared();// if (chunks) {// int proj_id = chunks->get_proj_id();// mem_space::memory_index_t mem_idx = mem.allocate(proj_id);// mem_space::shared_memory_header_t* smh =// static_cast<mem_space::shared_memory_header_t*>(mem_idx.get_memory_ptr());// smh->lock(chunks->get_segment_page_num());// int count = smh->get_ref_count();// smh->set_ref_count(count-ref_count);// smh->unlock(chunks->get_segment_page_num());// #ifdef DEBUG// std::cerr << __FILE__ << ':' << __LINE__// << ": Pool<>::~Pool() count - ref_count: " <<// std::endl;// std::cerr << count << " - " << ref_count << " = " <<// count-ref_count << std::endl;// #endif// } }; // destructor // copy constructor template<class T, mem_space::allocator_key_t alloc_key, mem_space::allocator_addr_t alloc_addr> Pool<T,alloc_key,alloc_addr>::Pool(const Pool<T, alloc_key, alloc_addr>& t) : element_size(t.element_size), mem(pooled_allocator::num_of_pages, pooled_allocator::page_size) {// ref_count = 0; // chunks=t.chunks; }; // copy constructor // assignment operator template<class T, mem_space::allocator_key_t alloc_key, mem_space::allocator_addr_t alloc_addr> Pool<T,alloc_key, alloc_addr>::Pool<T,alloc_key, alloc_addr>& Pool<T, alloc_key, alloc_addr>::operator=(const Pool<T, alloc_key,alloc_addr>& t) {// if (this != &t) { // avoid self assignment: t=t// chunks=t.chunks;// } return *this; }; // assignment operator // equality operator template<class T, mem_space::allocator_key_t alloc_key, mem_space::allocator_addr_t alloc_addr> bool Pool<T,alloc_key,alloc_addr>::operator==(const Pool<T, alloc_key, alloc_addr>& t) const { bool return_val=true; Chunk* this_chunk = chunks; Chunk* other_chunk = t.chunks; if (element_size!=t.element_size) return_val=false; // test the chunk lists for equality while ((return_val) && (this_chunk) && (other_chunk)) { if (!(*this_chunk==*other_chunk)) return_val=false; else { this_chunk = this_chunk->get_next(); other_chunk = other_chunk->get_next(); } } return return_val; }; // Pool<T,alloc_type,alloc_key,alloc_addr>::operator==() //////////////////////////////////////////////////////////////////// ////// Pool::get_last_chunk() //////////////////////////////////////////////////////////////////// ////// ////// Retrieve the last chunk on the list, return 0 if none. ////// //////////////////////////////////////////////////////////////////// template<class T, mem_space::allocator_key_t alloc_key, mem_space::allocator_addr_t alloc_addr> Chunk* Pool<T,alloc_key,alloc_addr>::get_last_chunk() { // Retrieve the last chunk on the list, return 0 if none. Chunk* last_chunk = chunks; // if chunks have already been allocated // get last chunk and square previous request while ((last_chunk) && (last_chunk->get_next())) { last_chunk = last_chunk->get_next(); } return last_chunk; }; // Chunk* Pool::get_last_chunk() //////////////////////////////////////////////////////////////////// ////// Chunk* Pool::find_chunk() //////////////////////////////////////////////////////////////////// ////// ////// global_element_num - chunk sought contains this ////// element number. ////// ////// Returns the chunk pointer if found, 0 otherwise. ////// //////////////////////////////////////////////////////////////////// // find chunk associated with global_element_num template<class T, mem_space::allocator_key_t alloc_key, mem_space::allocator_addr_t alloc_addr> Chunk* Pool<T,alloc_key,alloc_addr>::find_chunk(int global_element_num) { bool found = false; Chunk* current_chunk = chunks; while((!found) && (current_chunk != 0)) { const int& lower_bound = current_chunk->get_first_elem_num(); const int& upper_bound = lower_bound + current_chunk->get_num_of_elements(); if ((lower_bound <= global_element_num) && (global_element_num < upper_bound)) found = true; else current_chunk = current_chunk->get_next(); } return current_chunk; }; // Chunk* Pool::find_chunk(int global_element_num) //////////////////////////////////////////////////////////////////// ////// Pool::find_chunk(const unsigned char* p) //////////////////////////////////////////////////////////////////// ////// ////// p - pointer to allocated memory. ////// ////// Find the chunk and element number corresponding to the ////// pointer, p. Returns a pair with a pointer to the ////// corresponding chunk and the element number within that ////// chunk. If not found, return pair<>(0,-1). ////// //////////////////////////////////////////////////////////////////// template<class T, mem_space::allocator_key_t alloc_key, mem_space::allocator_addr_t alloc_addr> std::pair<Chunk*,int> Pool<T, alloc_key, alloc_addr>::find_chunk(const unsigned char* p) { bool found = false; Chunk* current_chunk = chunks; int element_num; while((!found) && (current_chunk != 0)) { element_num = current_chunk->pointer_to_element_num(p); if (element_num != -1) found = true; else current_chunk = current_chunk->get_next(); } // while((!found) && (current_chunk != 0)) return std::pair<Chunk*,int>(current_chunk,element_num); }; // std::pair<Chunk*,int> find_chunk(const unsigned char* p) //////////////////////////////////////////////////////////////////// ////// int Pool::find() //////////////////////////////////////////////////////////////////// ////// ////// num_of_elements - finds free, available memory to ////// store this number of elements. ////// ////// Returns the starting global element number which ////// indicates the beginning of the available space. If ////// the memory is unavailable, returns (0,-1). ////// //////////////////////////////////////////////////////////////////// template<class T, mem_space::allocator_key_t alloc_key, mem_space::allocator_addr_t alloc_addr> std::pair<Chunk*,int> Pool<T,alloc_key,alloc_addr>::find(int num_of_elements) { // Search through the list of chunks to find the requested num_of_elements. Chunk* current_chunk = chunks; int start_element=-1; while ((current_chunk != 0)&&(start_element == -1)) { // The chunk find routine returns the global block number if the // element is in this chunk, -1 otherwise. start_element = current_chunk->find(num_of_elements); if (start_element == -1) { // memory was not available in the current chunk, try next if (!current_chunk->get_next()) { // end of the line, try to grow more grow(); } if (current_chunk->get_next()) { current_chunk = current_chunk->get_next(); } else { // Memory appears to be exhausted for this shared // segment, throw. std::clog << "Error: " << __FILE__ << ':' << __LINE__ ; std::clog << ": project id out of range (1 <= proj_id < 128): " << std::endl; throw (Alloc_Exception::mem_exhausted_exception(0)); } } } return std::pair<Chunk*,int>(current_chunk,start_element); }; // int Pool::find(int num_of_elements) //////////////////////////////////////////////////////////////////// ////// void Pool::mark() //////////////////////////////////////////////////////////////////// ////// ////// start_element - global first element number of set ////// of elements to be marked. ////// num_of_elements - how many elements to be marked. ////// ////// Mark elements as in use. The elements may NOT span ////// more than one chunk. This is due to the bytes used by ////// the header information which prevents a contiguous ////// allocation of memory across multiple chunks. Chunks, ////// however, can be composed of multiple pages from a ////// segment, and the allocated memory can span those ////// subpages which do not have header information. ////// //////////////////////////////////////////////////////////////////// template<class T, mem_space::allocator_key_t alloc_key, mem_space::allocator_addr_t alloc_addr> void Pool<T,alloc_key,alloc_addr>::mark(int global_start_element, int num_of_elements) { // elements can NOT be allocated across chunks, so we must be // working within one chunk. Find it and mark the elements. The // chunk routines recieve global_start_element addresses. Chunk* current_chunk = find_chunk(global_start_element); if (current_chunk) current_chunk->mark(global_start_element,num_of_elements); return; }; // void mark(int start_element,int num_of_elements) //////////////////////////////////////////////////////////////////// ////// void Pool::clear() //////////////////////////////////////////////////////////////////// ////// ////// start_element - global first element number of set ////// of elements to be cleared. ////// num_of_elements - how many elements to be cleared. ////// ////// Clear elements for reuse. ////// //////////////////////////////////////////////////////////////////// template<class T, mem_space::allocator_key_t alloc_key, mem_space::allocator_addr_t alloc_addr> void Pool<T,alloc_key,alloc_addr>::clear(int global_start_element, int num_of_elements) { // elements can NOT be allocated across chunks, so we must be // working within one chunk. Find it and clear the elements. The // chunk routines recieve global_start_element addresses. Chunk* current_chunk = find_chunk(global_start_element); if (current_chunk) current_chunk->clear(global_start_element,num_of_elements); return; }; // void clear(int start_element,int num_of_elements) //////////////////////////////////////////////////////////////////// ////// Pool::compute_chunk_pages() //////////////////////////////////////////////////////////////////// ////// ////// Determine the size of a new chunk to be created. Find ////// the last chunk which was created. That chunk, if it ////// exists, contains information which will help to create ////// the next chunk. For example, if the last chunk used ////// by this process contained num_pages, the next chunk ////// should contain 2*num_pages. If no chunk exists, ////// enough space is allocated for initial_num_of_elems. ////// The function automatically computes the required pages ////// for element storage plus the regular chunk overhead. ////// //////////////////////////////////////////////////////////////////// template<class T, mem_space::allocator_key_t alloc_key, mem_space::allocator_addr_t alloc_addr> int Pool<T,alloc_key,alloc_addr>::compute_chunk_pages() { int request_pages; Chunk* last_chunk = get_last_chunk(); // // The total size of the last chunk is used to determine what the // current requested chunk size should be. //
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -