Data Memory Management

From reSIProcate
Jump to navigation Jump to search

States[edit]

Data is in one of three states with respect to its contents' memory.

  Data::Share
  Data::Borrow
  Data::Take

Share[edit]

'Share' means that the instance contents' memory is overlayed from someone else's memory. It must be guaranteed that the shared memory will not be reclaimed or modified while the Data instance exists. The instance will not write to its shared contents. Responsibility for deleting the memory is outside of the Data instance.

The Share state is typically used when parsing a SipMessage. The SipMessage's buffers of text are shared to the Data instances rather than copied.

Usually, sharing occurs under the hood during parsing. However, sharing can be made to occur with ParseBuffer::data(...).

Borrow[edit]

'Borrow' means that the instance contents' memory is from an outside scope but may be modified through the Data instance. It must be guaranteed that the borrowed memory will not be reclaimed or modified while the Data instance exists. Again, responibility for deleting the memory is elsewhere.

The Borrow state is often used for short strings. Each Data instance has a small inline buffer that can be borrowed to handle small strings without additional heap allocation. The size of this internal buffer is determined at compile time. A typical value is 16.

Borrow state can also be useful to explicitly allocate a Data instance's memory from the stack rather than from the heap. Note that if the stack allocation proves too small, the Data instance will transition to using heap memory at the cost of copying the contents.

 void f()
 {
   char buffer[256]; 
   Data cmd(Data::Borrow, buffer, sizeof(buffer));
   cmd.clear(); // or cmd will be full of stack junk
 }

Take[edit]

'Take' means that the instance contents' memory is owned by the Data instance and can be modified as needed. In this state, the Data instance has responsibility for deleting the memory.

Transitions[edit]

An instance of Data can transition from Share to Take or from Borrow to Take or from Take to Take. In each transition, new memory is allocated for the contents. Only in the Take to Take transition is the old memory deleted. A Take to Take transition occcurs when, for example, the content length exceeds the current memory allocation.

From / ToShareBorrowTake
ShareX-Alloc + Copy
Borrow-XAlloc + Copy
Take--Alloc + Copy + Free