[common] vector: eliminate double allocation when possible

This commit creates two constructor/destructor pairs for vector:
* vector_alloc/vector_free dynamically allocates the vector itself
* vector_create/vector_destroy uses existing Vector objects
This commit is contained in:
Quantum 2021-08-27 00:27:16 -04:00 committed by Geoffrey McRae
parent ba527761ef
commit e6df0acad9
5 changed files with 61 additions and 44 deletions

View File

@ -38,7 +38,7 @@ static const EGL_FilterOps * EGL_Filters[] =
struct EGL_PostProcess struct EGL_PostProcess
{ {
Vector * filters; Vector filters;
GLuint output; GLuint output;
unsigned int outputX, outputY; unsigned int outputX, outputY;
_Atomic(bool) modified; _Atomic(bool) modified;
@ -74,8 +74,8 @@ static void configUI(void * opaque, int * id)
igGetWindowPos(&window); igGetWindowPos(&window);
igGetMousePos(&pos); igGetMousePos(&pos);
EGL_Filter ** filters = vector_data(this->filters); EGL_Filter ** filters = vector_data(&this->filters);
size_t count = vector_size(this->filters); size_t count = vector_size(&this->filters);
for (size_t i = 0; i < count; ++i) for (size_t i = 0; i < count; ++i)
{ {
EGL_Filter * filter = filters[i]; EGL_Filter * filter = filters[i];
@ -144,8 +144,7 @@ bool egl_postProcessInit(EGL_PostProcess ** pp)
return false; return false;
} }
this->filters = vector_create(sizeof(EGL_Filter *), ARRAY_LENGTH(EGL_Filters)); if (!vector_create(&this->filters, sizeof(EGL_Filter *), ARRAY_LENGTH(EGL_Filters)))
if (!this->filters)
{ {
DEBUG_ERROR("Failed to allocate the filter list"); DEBUG_ERROR("Failed to allocate the filter list");
goto error_this; goto error_this;
@ -164,7 +163,7 @@ bool egl_postProcessInit(EGL_PostProcess ** pp)
return true; return true;
error_filters: error_filters:
vector_free(this->filters); vector_destroy(&this->filters);
error_this: error_this:
free(this); free(this);
@ -178,13 +177,10 @@ void egl_postProcessFree(EGL_PostProcess ** pp)
EGL_PostProcess * this = *pp; EGL_PostProcess * this = *pp;
if (this->filters) EGL_Filter ** filter;
{ vector_forEachRef(filter, &this->filters)
EGL_Filter ** filter; egl_filterFree(filter);
vector_forEachRef(filter, this->filters) vector_destroy(&this->filters);
egl_filterFree(filter);
vector_free(this->filters);
}
egl_modelFree(&this->model); egl_modelFree(&this->model);
free(this); free(this);
@ -197,7 +193,7 @@ bool egl_postProcessAdd(EGL_PostProcess * this, const EGL_FilterOps * ops)
if (!egl_filterInit(ops, &filter)) if (!egl_filterInit(ops, &filter))
return false; return false;
vector_push(this->filters, &filter); vector_push(&this->filters, &filter);
return true; return true;
} }
@ -219,7 +215,7 @@ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
atomic_store(&this->modified, false); atomic_store(&this->modified, false);
EGL_Filter * filter; EGL_Filter * filter;
vector_forEach(filter, this->filters) vector_forEach(filter, &this->filters)
{ {
egl_filterSetOutputResHint(filter, targetX, targetY); egl_filterSetOutputResHint(filter, targetX, targetY);
egl_filterSetup(filter, tex->format.pixFmt, sizeX, sizeY); egl_filterSetup(filter, tex->format.pixFmt, sizeX, sizeY);

View File

@ -36,7 +36,7 @@ typedef struct TexDMABUF
TextureBuffer base; TextureBuffer base;
EGLDisplay display; EGLDisplay display;
Vector * images; Vector images;
} }
TexDMABUF; TexDMABUF;
@ -47,9 +47,9 @@ EGL_TextureOps EGL_TextureDMABUF;
static void egl_texDMABUFCleanup(TexDMABUF * this) static void egl_texDMABUFCleanup(TexDMABUF * this)
{ {
struct FdImage * image; struct FdImage * image;
vector_forEachRef(image, this->images) vector_forEachRef(image, &this->images)
eglDestroyImage(this->display, image->image); eglDestroyImage(this->display, image->image);
vector_clear(this->images); vector_clear(&this->images);
} }
// dmabuf functions // dmabuf functions
@ -59,8 +59,7 @@ static bool egl_texDMABUFInit(EGL_Texture ** texture, EGLDisplay * display)
TexDMABUF * this = calloc(1, sizeof(*this)); TexDMABUF * this = calloc(1, sizeof(*this));
*texture = &this->base.base; *texture = &this->base.base;
this->images = vector_create(sizeof(struct FdImage), 2); if (!vector_create(&this->images, sizeof(struct FdImage), 2))
if (!this->images)
{ {
free(this); free(this);
*texture = NULL; *texture = NULL;
@ -70,7 +69,7 @@ static bool egl_texDMABUFInit(EGL_Texture ** texture, EGLDisplay * display)
EGL_Texture * parent = &this->base.base; EGL_Texture * parent = &this->base.base;
if (!egl_texBufferStreamInit(&parent, display)) if (!egl_texBufferStreamInit(&parent, display))
{ {
vector_free(this->images); vector_destroy(&this->images);
free(this); free(this);
*texture = NULL; *texture = NULL;
return false; return false;
@ -86,7 +85,7 @@ static void egl_texDMABUFFree(EGL_Texture * texture)
TexDMABUF * this = UPCAST(TexDMABUF , parent); TexDMABUF * this = UPCAST(TexDMABUF , parent);
egl_texDMABUFCleanup(this); egl_texDMABUFCleanup(this);
free(this->images); vector_destroy(&this->images);
egl_texBufferFree(&parent->base); egl_texBufferFree(&parent->base);
free(this); free(this);
@ -113,7 +112,7 @@ static bool egl_texDMABUFUpdate(EGL_Texture * texture,
EGLImage image = EGL_NO_IMAGE; EGLImage image = EGL_NO_IMAGE;
struct FdImage * fdImage; struct FdImage * fdImage;
vector_forEachRef(fdImage, this->images) vector_forEachRef(fdImage, &this->images)
if (fdImage->fd == update->dmaFD) if (fdImage->fd == update->dmaFD)
{ {
image = fdImage->image; image = fdImage->image;
@ -146,7 +145,7 @@ static bool egl_texDMABUFUpdate(EGL_Texture * texture,
return false; return false;
} }
if (!vector_push(this->images, &(struct FdImage) { if (!vector_push(&this->images, &(struct FdImage) {
.fd = update->dmaFD, .fd = update->dmaFD,
.image = image, .image = image,
})) }))

View File

@ -31,9 +31,14 @@ typedef struct Vector
} }
Vector; Vector;
Vector * vector_create(size_t itemSize, size_t capacity); // Dynamically allocates the vector
Vector * vector_alloc(size_t itemSize, size_t capacity);
void vector_free(Vector * vector); void vector_free(Vector * vector);
// Uses existing vector, but dynamically allocates storage
bool vector_create(Vector * vector, size_t itemSize, size_t capacity);
void vector_destroy(Vector * vector);
inline static size_t vector_size(Vector * vector) inline static size_t vector_size(Vector * vector)
{ {
return vector->size; return vector->size;

View File

@ -79,13 +79,13 @@ bool ivshmemInit(struct IVSHMEM * dev)
PSP_DEVICE_INTERFACE_DETAIL_DATA infData = NULL; PSP_DEVICE_INTERFACE_DETAIL_DATA infData = NULL;
SP_DEVINFO_DATA devInfoData = {0}; SP_DEVINFO_DATA devInfoData = {0};
SP_DEVICE_INTERFACE_DATA devInterfaceData = {0}; SP_DEVICE_INTERFACE_DATA devInterfaceData = {0};
Vector devices;
devInfoSet = SetupDiGetClassDevs(&GUID_DEVINTERFACE_IVSHMEM, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); devInfoSet = SetupDiGetClassDevs(&GUID_DEVINTERFACE_IVSHMEM, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
Vector * devices = vector_create(sizeof(struct IVSHMEMData), 1); if (!vector_create(&devices, sizeof(struct IVSHMEMData), 1))
if (!devices)
{ {
DEBUG_ERROR("Failed to allocate memory"); DEBUG_ERROR("Failed to allocate memory");
return false; return false;
@ -93,7 +93,7 @@ bool ivshmemInit(struct IVSHMEM * dev)
for (int i = 0; SetupDiEnumDeviceInfo(devInfoSet, i, &devInfoData); ++i) for (int i = 0; SetupDiEnumDeviceInfo(devInfoSet, i, &devInfoData); ++i)
{ {
struct IVSHMEMData * device = vector_push(devices, NULL); struct IVSHMEMData * device = vector_push(&devices, NULL);
DWORD bus, addr; DWORD bus, addr;
if (!SetupDiGetDeviceRegistryProperty(devInfoSet, &devInfoData, SPDRP_BUSNUMBER, if (!SetupDiGetDeviceRegistryProperty(devInfoSet, &devInfoData, SPDRP_BUSNUMBER,
@ -121,10 +121,10 @@ bool ivshmemInit(struct IVSHMEM * dev)
} }
const int shmDevice = option_get_int("os", "shmDevice"); const int shmDevice = option_get_int("os", "shmDevice");
qsort(vector_data(devices), vector_size(devices), sizeof(struct IVSHMEMData), ivshmemComparator); qsort(vector_data(&devices), vector_size(&devices), sizeof(struct IVSHMEMData), ivshmemComparator);
struct IVSHMEMData * device; struct IVSHMEMData * device;
vector_forEachRefIdx(i, device, devices) vector_forEachRefIdx(i, device, &devices)
{ {
DWORD bus = device->busAddr >> 32; DWORD bus = device->busAddr >> 32;
DWORD addr = device->busAddr & 0xFFFFFFFF; DWORD addr = device->busAddr & 0xFFFFFFFF;
@ -132,9 +132,9 @@ bool ivshmemInit(struct IVSHMEM * dev)
i == shmDevice ? '*' : ' ', bus, addr >> 16, addr & 0xFFFF); i == shmDevice ? '*' : ' ', bus, addr >> 16, addr & 0xFFFF);
} }
device = vector_ptrTo(devices, shmDevice); device = vector_ptrTo(&devices, shmDevice);
memcpy(&devInfoData, &device->devInfoData, sizeof(SP_DEVINFO_DATA)); memcpy(&devInfoData, &device->devInfoData, sizeof(SP_DEVINFO_DATA));
vector_free(devices); vector_destroy(&devices);
if (SetupDiEnumDeviceInterfaces(devInfoSet, &devInfoData, &GUID_DEVINTERFACE_IVSHMEM, 0, &devInterfaceData) == FALSE) if (SetupDiEnumDeviceInterfaces(devInfoSet, &devInfoData, &GUID_DEVINTERFACE_IVSHMEM, 0, &devInterfaceData) == FALSE)
{ {

View File

@ -25,22 +25,16 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
Vector * vector_create(size_t itemSize, size_t capacity) Vector * vector_alloc(size_t itemSize, size_t capacity)
{ {
Vector * vector = calloc(1, sizeof(Vector)); Vector * vector = malloc(sizeof(Vector));
if (!vector) if (!vector)
return NULL; return NULL;
vector->itemSize = itemSize; if (!vector_create(vector, itemSize, capacity))
vector->capacity = capacity;
if (capacity)
{ {
vector->data = malloc(itemSize * capacity); free(vector);
if (!vector->data) return NULL;
{
free(vector);
return NULL;
}
} }
return vector; return vector;
} }
@ -49,10 +43,33 @@ void vector_free(Vector * vector)
{ {
if (!vector) if (!vector)
return; return;
free(vector->data); vector_destroy(vector);
free(vector); free(vector);
} }
bool vector_create(Vector * vector, size_t itemSize, size_t capacity)
{
vector->itemSize = itemSize;
vector->capacity = capacity;
vector->size = 0;
vector->data = NULL;
if (capacity)
{
vector->data = malloc(itemSize * capacity);
if (!vector->data)
return false;
}
return true;
}
void vector_destroy(Vector * vector)
{
free(vector->data);
vector->capacity = 0;
vector->itemSize = 0;
}
void * vector_push(Vector * vector, void * item) void * vector_push(Vector * vector, void * item)
{ {
if (vector->size >= vector->capacity) if (vector->size >= vector->capacity)