Call constructors and destructors in List and IdList.
This is necessary to store non-POD classes in these containers. Note that List and IdList do not use MemRealloc anymore; this is necessarily (slightly) less efficient, but is the right semantics, as you cannot just move non-POD types, e.g. std::string, around in memory. All STL containers provide the same guarantees and share the performance hit. The slowdown is mostly mitigated by moving the contained objects, so that no additional heap allocations or copies occur beyond that of the object itself.
This commit is contained in:
parent
97fa6355cc
commit
c84a3b6de3
42
src/dsc.h
42
src/dsc.h
@ -152,20 +152,27 @@ public:
|
|||||||
void AllocForOneMore(void) {
|
void AllocForOneMore(void) {
|
||||||
if(n >= elemsAllocated) {
|
if(n >= elemsAllocated) {
|
||||||
elemsAllocated = (elemsAllocated + 32)*2;
|
elemsAllocated = (elemsAllocated + 32)*2;
|
||||||
elem = (T *)MemRealloc(elem, (size_t)elemsAllocated*sizeof(elem[0]));
|
T *newElem = (T *)MemAlloc((size_t)elemsAllocated*sizeof(elem[0]));
|
||||||
|
for(int i = 0; i < n; i++) {
|
||||||
|
new(&newElem[i]) T(std::move(elem[i]));
|
||||||
|
elem[i].~T();
|
||||||
|
}
|
||||||
|
MemFree(elem);
|
||||||
|
elem = newElem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Add(T *t) {
|
void Add(T *t) {
|
||||||
AllocForOneMore();
|
AllocForOneMore();
|
||||||
elem[n++] = *t;
|
new(&elem[n++]) T(*t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddToBeginning(T *t) {
|
void AddToBeginning(T *t) {
|
||||||
AllocForOneMore();
|
AllocForOneMore();
|
||||||
memmove(elem+1, elem, n*sizeof(elem[0]));
|
new(&elem[n]) T();
|
||||||
n++;
|
std::move_backward(elem, elem + 1, elem + n + 1);
|
||||||
elem[0] = *t;
|
elem[0] = *t;
|
||||||
|
n++;
|
||||||
}
|
}
|
||||||
|
|
||||||
T *First(void) {
|
T *First(void) {
|
||||||
@ -185,6 +192,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Clear(void) {
|
void Clear(void) {
|
||||||
|
for(int i = 0; i < n; i++)
|
||||||
|
elem[i].~T();
|
||||||
if(elem) MemFree(elem);
|
if(elem) MemFree(elem);
|
||||||
elem = NULL;
|
elem = NULL;
|
||||||
n = elemsAllocated = 0;
|
n = elemsAllocated = 0;
|
||||||
@ -203,12 +212,16 @@ public:
|
|||||||
dest++;
|
dest++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for(int i = dest; i < n; i++)
|
||||||
|
elem[i].~T();
|
||||||
n = dest;
|
n = dest;
|
||||||
// and elemsAllocated is untouched, because we didn't resize
|
// and elemsAllocated is untouched, because we didn't resize
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveLast(int cnt) {
|
void RemoveLast(int cnt) {
|
||||||
if(n < cnt) oops();
|
if(n < cnt) oops();
|
||||||
|
for(int i = n - cnt; i < n; i++)
|
||||||
|
elem[i].~T();
|
||||||
n -= cnt;
|
n -= cnt;
|
||||||
// and elemsAllocated is untouched, same as in RemoveTagged
|
// and elemsAllocated is untouched, same as in RemoveTagged
|
||||||
}
|
}
|
||||||
@ -251,7 +264,13 @@ public:
|
|||||||
void Add(T *t) {
|
void Add(T *t) {
|
||||||
if(n >= elemsAllocated) {
|
if(n >= elemsAllocated) {
|
||||||
elemsAllocated = (elemsAllocated + 32)*2;
|
elemsAllocated = (elemsAllocated + 32)*2;
|
||||||
elem = (T *)MemRealloc(elem, (size_t)elemsAllocated*sizeof(elem[0]));
|
T *newElem = (T *)MemAlloc((size_t)elemsAllocated*sizeof(elem[0]));
|
||||||
|
for(int i = 0; i < n; i++) {
|
||||||
|
new(&newElem[i]) T(std::move(elem[i]));
|
||||||
|
elem[i].~T();
|
||||||
|
}
|
||||||
|
MemFree(elem);
|
||||||
|
elem = newElem;
|
||||||
}
|
}
|
||||||
|
|
||||||
int first = 0, last = n;
|
int first = 0, last = n;
|
||||||
@ -268,9 +287,10 @@ public:
|
|||||||
oops();
|
oops();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int i = first;
|
|
||||||
|
|
||||||
memmove(elem+i+1, elem+i, (size_t)(n-i)*sizeof(elem[0]));
|
int i = first;
|
||||||
|
new(&elem[n]) T();
|
||||||
|
std::move_backward(elem + i, elem + n, elem + n + 1);
|
||||||
elem[i] = *t;
|
elem[i] = *t;
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
@ -338,6 +358,8 @@ public:
|
|||||||
dest++;
|
dest++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for(int i = dest; i < n; i++)
|
||||||
|
elem[i].~T();
|
||||||
n = dest;
|
n = dest;
|
||||||
// and elemsAllocated is untouched, because we didn't resize
|
// and elemsAllocated is untouched, because we didn't resize
|
||||||
}
|
}
|
||||||
@ -349,7 +371,7 @@ public:
|
|||||||
|
|
||||||
void MoveSelfInto(IdList<T,H> *l) {
|
void MoveSelfInto(IdList<T,H> *l) {
|
||||||
l->Clear();
|
l->Clear();
|
||||||
memcpy(l, this, sizeof(*this));
|
*l = *this;
|
||||||
elemsAllocated = n = 0;
|
elemsAllocated = n = 0;
|
||||||
elem = NULL;
|
elem = NULL;
|
||||||
}
|
}
|
||||||
@ -357,7 +379,8 @@ public:
|
|||||||
void DeepCopyInto(IdList<T,H> *l) {
|
void DeepCopyInto(IdList<T,H> *l) {
|
||||||
l->Clear();
|
l->Clear();
|
||||||
l->elem = (T *)MemAlloc(elemsAllocated * sizeof(elem[0]));
|
l->elem = (T *)MemAlloc(elemsAllocated * sizeof(elem[0]));
|
||||||
memcpy(l->elem, elem, elemsAllocated * sizeof(elem[0]));
|
for(int i = 0; i < n; i++)
|
||||||
|
new(&l->elem[i]) T(elem[i]);
|
||||||
l->elemsAllocated = elemsAllocated;
|
l->elemsAllocated = elemsAllocated;
|
||||||
l->n = n;
|
l->n = n;
|
||||||
}
|
}
|
||||||
@ -365,6 +388,7 @@ public:
|
|||||||
void Clear(void) {
|
void Clear(void) {
|
||||||
for(int i = 0; i < n; i++) {
|
for(int i = 0; i < n; i++) {
|
||||||
elem[i].Clear();
|
elem[i].Clear();
|
||||||
|
elem[i].~T();
|
||||||
}
|
}
|
||||||
elemsAllocated = n = 0;
|
elemsAllocated = n = 0;
|
||||||
if(elem) MemFree(elem);
|
if(elem) MemFree(elem);
|
||||||
|
@ -256,7 +256,6 @@ float CnfThawFloat(float v, const char *name);
|
|||||||
void *AllocTemporary(size_t n);
|
void *AllocTemporary(size_t n);
|
||||||
void FreeTemporary(void *p);
|
void FreeTemporary(void *p);
|
||||||
void FreeAllTemporary(void);
|
void FreeAllTemporary(void);
|
||||||
void *MemRealloc(void *p, size_t n);
|
|
||||||
void *MemAlloc(size_t n);
|
void *MemAlloc(size_t n);
|
||||||
void MemFree(void *p);
|
void MemFree(void *p);
|
||||||
void InitHeaps(void);
|
void InitHeaps(void);
|
||||||
|
@ -95,16 +95,6 @@ void FreeAllTemporary(void)
|
|||||||
Head = NULL;
|
Head = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *MemRealloc(void *p, size_t n) {
|
|
||||||
if(!p) {
|
|
||||||
return MemAlloc(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
p = realloc(p, n);
|
|
||||||
if(!p) oops();
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *MemAlloc(size_t n) {
|
void *MemAlloc(size_t n) {
|
||||||
void *p = malloc(n);
|
void *p = malloc(n);
|
||||||
if(!p) oops();
|
if(!p) oops();
|
||||||
|
@ -53,15 +53,6 @@ void FreeAllTemporary(void)
|
|||||||
vl();
|
vl();
|
||||||
}
|
}
|
||||||
|
|
||||||
void *MemRealloc(void *p, size_t n) {
|
|
||||||
if(!p) {
|
|
||||||
return MemAlloc(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
p = HeapReAlloc(PermHeap, HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY, p, n);
|
|
||||||
if(!p) oops();
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
void *MemAlloc(size_t n) {
|
void *MemAlloc(size_t n) {
|
||||||
void *p = HeapAlloc(PermHeap, HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY, n);
|
void *p = HeapAlloc(PermHeap, HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY, n);
|
||||||
if(!p) oops();
|
if(!p) oops();
|
||||||
@ -82,4 +73,4 @@ void InitHeaps(void) {
|
|||||||
// Create the heap that we use to store Exprs and other temp stuff.
|
// Create the heap that we use to store Exprs and other temp stuff.
|
||||||
FreeAllTemporary();
|
FreeAllTemporary();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user