#57 closed defect (fixed)
Store deallocator in memBlock
| Reported by: | Owned by: | eugene | |
|---|---|---|---|
| Priority: | high | Milestone: | |
| Component: | PSLib SDRS | Version: | unspecified |
| Severity: | normal | Keywords: | |
| Cc: | rhl@… |
Description
To ensure that the proper ps*Free function is called for any given pointer, I
propose that, at the time of allocation, a pointer be set in the memBlock for
the cooresponding ps*Free function. The user, then, need only ever use psFree
and psFree could call the ps*Free function required, if any.
I propose the addition of two functions:
void p_psSetFreeFcn(void* ptr);
/< sets the fcn pointer to the appropriate ps*Free function. If NULL,
/< then a generic free functionality is used (i.e., the old psFree
/< functionality).
freeFcn p_psGetFreeFcn(void* ptr);
/< retrieves the function pointer to the higher-level free function to be
/< used. If NULL, then the traditional psFree functionality shall be used.
All ps*Free functions could now be private, and psFree would be the sole means
for users to free any pointer generated by psLib. These functions need to all
have the same prototype. I suggest it be the same as p_psFree, i.e., containing
the file and lineno of the originating call (psFree would pass that along when
it invokes it).
This also solves issues with the reference counter, as psMemDecrRefCounter would
be smart enough to properly free complex containers as well as simple buffers
from psAlloc.
Change History (6)
comment:1 by , 22 years ago
| Cc: | added |
|---|
comment:2 by , 22 years ago
| Status: | new → assigned |
|---|
comment:3 by , 22 years ago
I implemented this in the main trunk of CVS. The new psMemBlock is:
/ typedef for deallocator.
typedef void (*psFreeFcn)(void* ptr);
/ Book-keeping data for storage allocator.
- N.b. sizeof(psMemBlock) must be chosen such that if ptr is a pointer
- returned by malloc, then ((char *)ptr + sizeof(psMemBlock)) is properly
- aligned for all storage types. */
typedef struct psMemBlock
{
const void* startblock; /< initialised to p_psMEMMAGIC
struct psMemBlock* previousBlock; /< previous block in allocation list
struct psMemBlock* nextBlock; /< next block allocation list
psFreeFcn freeFcn; /< deallocator. If NULL, use generic
deallocation.
size_t userMemorySize; /< the size of the user-portion of the
memory block
const psMemoryId id; /< a unique ID for this allocation
const char* file; /< set from FILE in e.g. p_psAlloc
const int lineno; /< set from LINE in e.g. p_psAlloc
pthread_mutex_t refCounterMutex; /< mutex to ensure exclusive access to
reference counter
psReferenceCount refCounter; /< how many times pointer is referenced
const void* endblock; /< initialised to p_psMEMMAGIC
}
psMemBlock;
the freeFcn is not strictly the old ps_Free functions as psFree always handles
the primary psMemBlock. I went through the code and removed the ps_Free
functions as to not add confusion, e.g., to free a psVector/psList/etc., one
would just use psFree(...)
Here is an example:
typedef struct {
psElemType type;
void* data;
} psFoo;
psFoo* psFooAlloc(void* value, psElemType type) {
psFoo* newFoo = psAlloc(sizeof(psFoo));
p_psMemSetDeallocator(newFoo,(psFreeFcn)fooFree);
newFoo->data = psMemIncrRefCounter(value);
newFoo->type = type;
return newFoo;
}
static void fooFree(psFoo* ptr) {
if (ptr != NULL) {
psFree(ptr->data);
}
}
int main() {
psFoo* foo;
int* val = psAlloc(sizeof(int));
*val = 4;
foo = psFooAlloc(val,PS_TYPE_INT);
psFree(val); free my reference (foo still has a reference)
...
psFree(foo); calls the fooFree function, but I need not know that detail.
}
comment:4 by , 22 years ago
I've updated the SDRS to follow the implementation, but I didn't understand the
plan for these two functions. perhaps you can write out a few sentences
describing them that I can paste in the SDRS. the comments are not sufficiently
clear here.
void p_psSetFreeFcn(void* ptr);
freeFcn p_psGetFreeFcn(void* ptr);
I've also changed all instances of psFooFree to p_psFooFree in the document and
clarified their use to refer to the associated data rather than the data
structure itself. you might review the document and see if it makes sense at
some point
comment:5 by , 22 years ago
As far as the psFooFree being renamed to p_psFooFree, I'd recommend not
defining psFoo specific free functions, public or private, at all. I
implemented the psFoo's free functions as a static function in the
implementation file containing psFooAlloc (i.e., psFoo.c), as only psFooAlloc
needs to have access to the function by name (psFree uses just a function
pointer set by psFooAlloc, remember).
As far as the other issue:
void p_psSetFreeFcn(psFreeFcn ptr);
psFreeFcn p_psGetFreeFcn(psFreeFcn ptr);
A free function handles any deallocation procedures of an object in which a
pointer refers to, excluding the freeing of the memory block of the pointer
reference itself. If the pointer refers to an object that references other
memory blocks this free function would insure the freeing of any encapsulated
memory block references. For example, psList references a series of node
objects of a linked list, so its free function would free these node objects
and the node object's free function would free the data element references they
may contain.
The p_psSetFreeFcn is used to associated a free function to a memory block,
while p_psGetFreeFcn retrieves the last free function set. To remove a free
function from a memory block, the p_psSetFreeFcn should be invoked with a NULL
psFreeFcn. If no free function is set, p_psGetFreeFcn shall return NULL.

this sounds good. don't your functions need to have a pointer to a psMemBlock?