Application Layer memory management for memory-constrained devices (III)

Source: Internet
Author: User

Application Layer memory management for memory-constrained devices (III)

Raveendran vadakkoot and neeraj S. Sharma

Translated by Guo shilong

6. C ++ framework

The C ++ memory management framework discussed here is the memmanager class. It must be ensured that at any point in time, only one memmangager class instance (making the memmanager class a single instance class) is active. A good old technique for using a friend function is that this class becomes a single instance, this is because it is not only a single instance but also a unique memmanager instance that can only be created when the user needs to dynamically allocate some space. Other technologies, like constructing a single instance with a static member variable, are not as effective as using a friend function.

 

Note:This framework does not discuss thread security of this class.

 

class MemManager{private:   MemManager();    // suppress the constructor and copy the                    // constructor   MemManager (MemManager&);   void operator= (MemManager&);                    // and the overloaded '=' operatorpublic:   friend MemManager& getInstance();};
In the getinatance () method implementation, you must create a static member and return a reference as shown in the following code snippet.
MemManager::MemManager(){   init();}MemManager& getInstance(){   static MemManager theInstance;   return theInstance;}
Once the single-instance mode framework is available, you must provide a basic allocation and recovery function. Allocate and recycle functions to complete necessary memory management. The init () function initializes the data structure. Once the user ensures that there is only one memory management instance activity during program execution, the user must ensure that improper use is not intentionally or unintentionally performed during code execution. Set constructor, copy constructor, and "=" operator to private to restrict their behaviors. This ensures that you cannot create any other instances of this class at any time.
class MemManager{private:   MemManager();    // suppress the constructor                    // and copy the constructor   MemManager(MemManager&);   void operator=(MemManager&);                    // and the overloaded '=' operatorpublic:   friend MemManager& getInstance();   void* allocate(size_t s);   void deAllocate(void* ptr);};
C ++ provides a mechanism to intercept all new and delete calls. You can reload the global new, new [], delete, and delete [] operators to redirect all operating systems (OS) the memory management system calls the allocate () and deallocate () Functions of the memory management framework.
void* operator new(size_t s){   return getInstance().allocate(s);}void operator delete(void* ptr){   return getInstance().deAllocate(ptr);}void* operator new[](size_t s){   return getInstance().allocate(s);}void operator delete(void* ptr){   return getInstance().deAllocate(ptr);}
All page information is kept in the cell class. The basic structure of the cell class is as follows.
struct Cell   {      long    dataSize;      void    *data;      long    noOfElements;      long    bitmap;      Cell    *prev;      Cell    *next;      Cell    *header;    // boundary tag   };
Data points to the actual memory location, where the newly allocated objects are saved. Bitmap specifies whether a specific location in a unit/page is occupied by a new object (created. Datasize indicates the size of each object on the page (it is always a multiple of 2 ). The header field is used to reach the first page in case of multiple pages. Before actual allocation and collection, the init () function must do a lot of work. Including: 1) Create an idle linked list (the idle linked list is a large block of memory allocated from the operating system at the beginning of the system, and further allocation and recovery will occur on this idle block ). 2) initialize the data structure used by note. 3) divide the idle linked list into units/pages of the same size. Figure 16: Data Structure of notes
Static char buffer[MAX_BUFFER];// align it to a word boundary if desiredConst int noOfPages = MAX_BUFFER / PAGESIZE;Void MemManager::init(){   // 1. Allocate a big chunk. This has to be a preferably   //    a static block. For example:- buffer;   // 2. Divide it into cells/pages of equal size. This can   //    be done by setting the 'Cell' datastructure point   //    to the buffer

 

for(int i=0;i<noOfPages;i++) Cell[i].data = &buffer + i*PAGESIZE; Cell[0].dataSize = noOfPages*PAGESIZE; // This is required because intially, it's a big chunk/block // of data. Later it gets fragmented into smaller chunks. // 3. Also set the category list to null, as it would // initially not contain any page for(int j=0; j<noOfCategories;j++) CellCategory[j].head = CellCategory[j].tail = 0;}

Figure 17: bitmap indicates idle and allocated Blocks
In this case, a unit/page can have up to four objects. In Figure 17, the bitmap clearly shows that Unit 1 and 3 are used and units 2 and 4 are idle. Assume that the size of each unit is 256 bytes. In this case, the size of each inner segment is 256/4 = 64 bytes. The size allocated to each split should be 33 to 64 bytes. In case of better granularity, the worst case is that the object size is 33 bytes (31 bytes will be wasted ). You can use the cellcategory class to classify and link large and small pages.

class CellCategory{   Cell *head;   Cell *tail;};

Figure 18: any calls to dynamic memory in the memory structure, such as new char [17], will be intercepted by the allocate () function in the memory manager. The allocate function first identifies the class to which the object falls. As shown in 18, this category is 2. In other words, this is an object in the size of 17 to 32. If the class head node has free space, the new object will be assigned to this specific location and return its address. In addition, bitmap also identifies the bitmap.

Figure 19: the memory structure and bitmap show that the idle and allocated blocks are moved to the end of the category linked list once the header (head) page/unit is full. This ensures that the linked list is available at the beginning or the memory manager must allocate a new page from the idle linked list. Generally, the allocate () function does the following:
Void* MemManager::allocate(size_t s){   // 1. Find the category to which the object falls.   // 2. If a free 'partition' is available at the 'head',   //    grab it immediately.   // 3. If not, then grab a new cell/page from the free list.   //    Put it at the 'head' of the category list.   // 4. Allocate space for the object, from the cell   // 5. Set the bitmap accordingly.   // 6. Return the address.}
Multi-page/multi-unit block and single-page block must be processed separately
Void* MemManager::allocate(size_t s){   // 1. Find the category to which the object falls.   // 2. If the object is a multi-page or a single-page object,   //    then grab fresh cells/pages.   // 3. Add them to the category list.   // 4. If the object doesn't span the whole page/multi page,   //    then if a free 'partition' is available at the 'head',   //    grab it immediately.   // 3. If not, grab a new cell/page from the free list.   //    Put it at the 'head' of the category list.   // 4. Allocate space for the object, from the cell   // 5. Set the bitmap accordingly.   // 6. Return the address.}
The release of any dynamically allocated memory, such as Delete [] OBJ, will be intercepted by the deallocate () function in the memory manager. The deallocate () function first identifies the class in which the object falls. This is easy because the unit/page is always fixed. The boundary address of a unit can be obtained through simple arithmetic operations. Cellnum = (objectaddress-baseaddress)/cellsize the cell boundary of the activity can be obtained through the following formula boundaryaddress = baseaddress) + cellnum * cellsize; with all this information, it is easy to release an allocated space. Set the bitmap of the space to 0. Figure 20: Memory Structure and bitmap before release fig 21: the memory structure and bitmap after release once an object is released from the unit, the entire unit/page is idle, this is a very likely situation. Once a unit/page is completely idle, it must be returned to the idle linked list. This can also be done through the deallocate () function.
Void MemManager::deAllocate(void* ptr){   // 1. Find the category and the cell to which the   //    object falls.   // 2. Set the bitmap to '0' for the partition being freed.   // 3. If the whole cell/page is free, delete the page from   //    the category list and return it to the free list.   // 4. If not, put the object at the 'head' of the list as   //    it guarantees that there is always a free cell at   //    the head of the list}Void MemManager::deAllocate(void* ptr){   // 1. Find the category and the cell to which the object falls.   // 2. Set the bitmap to '0' for the partition being freed.   // 3. If the whole cell/page is free, delete the page from   //    the category list and return it to the free list.   // 3-1. During the return to the free list, try to coalesce   //      it with the adjacent blocks.   // 4. If not, put the object at the 'head' of the list as   //    it guarantees that there is always a free cell at the   //    head of the list}Void MemManager::coalesce(void* ptr){   // 1. Check if the immediate previous block is free.   //    Let us call that 'p'.   // 2. If its free, it's quite simple. Just add the size of   //    the current block (lets call this 'curr') to the   //    previous block's capacity.   //    ie. p->size += curr->size; curr = p;   // 3. Next, check if the adjacent 'next' block is free.   //    Let us call that 'n'   // 4. If the next block is free, it gets quite complicated.   // 4-1. Find the 'next' block of 'n'. Make that the 'next'   //      of the 'curr' block.   //      ie curr->next = n->next;   //      curr->size += n->size;}
7. Summary
In short, the "power of 2 buddy-System" algorithm, together with the separated linked list of a specific size object, enables the application to achieve excellent performance and memory management. 8. References
  • Dynamic Storage Allocation for realtime systemsBy M. masmano, I. repoll, and A. Crespo.
  • Dynamic Storage Allocation-A survey and critical reviewBy Paul R. Wilson, Mark S. Johnstone, Michael Neely, and David Boles.
  • Art of computer programming-Fundamentals of computer algorithmsBy Donald E knuth.
  • More effective tive C ++By Scott Meyers.

Original

Application Layer memory management for memory-constrained devices (I)

Application Layer memory management for memory-constrained devices (2)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.