mirror of
https://github.com/QB64-Phoenix-Edition/QB64pe.git
synced 2024-09-20 06:44:44 +00:00
parent
0da86b61a5
commit
a891a6b255
4 changed files with 190 additions and 168 deletions
|
@ -30,6 +30,7 @@
|
||||||
#include "http.h"
|
#include "http.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
#include "keyhandler.h"
|
#include "keyhandler.h"
|
||||||
|
#include "qblist.h"
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#include "mutex.h"
|
#include "mutex.h"
|
||||||
#include "qbs.h"
|
#include "qbs.h"
|
||||||
|
@ -426,174 +427,6 @@ int64 display_frame_order_next = 1;
|
||||||
int64 last_rendered_hardware_display_frame_order = 0;
|
int64 last_rendered_hardware_display_frame_order = 0;
|
||||||
int64 last_hardware_display_frame_order = 0;
|
int64 last_hardware_display_frame_order = 0;
|
||||||
|
|
||||||
// List Interface
|
|
||||||
// Purpose: Unify and optimize the way QB64 references lists of objects (such as handles)
|
|
||||||
// Notes: Does not use index 0
|
|
||||||
struct list {
|
|
||||||
ptrszint user_structure_size;
|
|
||||||
ptrszint internal_structure_size;
|
|
||||||
uint8 *structure; // block of structures of user-specified size
|
|
||||||
ptrszint structures;
|
|
||||||
ptrszint structures_last;
|
|
||||||
ptrszint *structure_freed; // quickly re-reference available structures after they have been removed
|
|
||||||
ptrszint *structure_freed_cleanup; // the previous *structure_freed memory block
|
|
||||||
ptrszint structures_freed;
|
|
||||||
ptrszint structures_freed_last;
|
|
||||||
ptrszint structure_base[64]; // every time the 'structure' block is full a new and larger block is allocated
|
|
||||||
// because the list doubles each time, 64 entries will never be exceeded
|
|
||||||
ptrszint structure_bases;
|
|
||||||
ptrszint *index; // pointers to the structures referred to by each index value
|
|
||||||
ptrszint *index_cleanup;
|
|
||||||
ptrszint indexes;
|
|
||||||
ptrszint indexes_last;
|
|
||||||
struct libqb_mutex *lock_add;
|
|
||||||
struct libqb_mutex *lock_remove;
|
|
||||||
};
|
|
||||||
|
|
||||||
// fwd refs
|
|
||||||
void *list_get(list *L, ptrszint i);
|
|
||||||
|
|
||||||
list *list_new(ptrszint structure_size) {
|
|
||||||
list *L;
|
|
||||||
L = (list *)calloc(1, sizeof(list));
|
|
||||||
L->structure = (uint8 *)malloc(sizeof(uint8 *));
|
|
||||||
L->structure_base[1] = (ptrszint)L->structure;
|
|
||||||
L->structure_bases = 1;
|
|
||||||
L->structure_freed = (ptrszint *)malloc(sizeof(ptrszint *));
|
|
||||||
L->index = (ptrszint *)malloc(sizeof(ptrszint *));
|
|
||||||
L->user_structure_size = structure_size;
|
|
||||||
L->internal_structure_size = structure_size + sizeof(ptrszint);
|
|
||||||
return L;
|
|
||||||
}
|
|
||||||
|
|
||||||
list *list_new_threadsafe(ptrszint structure_size) {
|
|
||||||
list *L = list_new(structure_size);
|
|
||||||
L->lock_add = libqb_mutex_new();
|
|
||||||
L->lock_remove = libqb_mutex_new();
|
|
||||||
return L;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptrszint list_add(list *L) {
|
|
||||||
if (L->lock_add)
|
|
||||||
libqb_mutex_lock(L->lock_add);
|
|
||||||
|
|
||||||
ptrszint i;
|
|
||||||
if (L->structures_freed) { // retrieve index from freed list if possible
|
|
||||||
if (L->lock_remove)
|
|
||||||
libqb_mutex_lock(L->lock_remove);
|
|
||||||
|
|
||||||
i = L->structure_freed[L->structures_freed--];
|
|
||||||
uint8 *structure;
|
|
||||||
structure = (uint8 *)L->index[i];
|
|
||||||
memset(structure, 0, L->user_structure_size);
|
|
||||||
*(ptrszint *)(structure + L->user_structure_size) = i;
|
|
||||||
|
|
||||||
if (L->lock_remove)
|
|
||||||
libqb_mutex_unlock(L->lock_remove);
|
|
||||||
} else {
|
|
||||||
// create new buffer?
|
|
||||||
if ((L->structures + 1) > L->structures_last) {
|
|
||||||
ptrszint new_structures_last;
|
|
||||||
new_structures_last = (L->structures_last * 2) + 1;
|
|
||||||
// note: L->structure is only modified by list_add
|
|
||||||
L->structure = (uint8 *)calloc(1, L->internal_structure_size * (new_structures_last + 1));
|
|
||||||
if (L->structure == NULL) {
|
|
||||||
gui_alert("list_add: failed to allocate new buffer, structure size: %lld", (int64_t)L->internal_structure_size);
|
|
||||||
}
|
|
||||||
L->structures_last = new_structures_last;
|
|
||||||
L->structures = 0;
|
|
||||||
L->structure_base[++L->structure_bases] = (ptrszint)L->structure;
|
|
||||||
}
|
|
||||||
i = ++L->indexes;
|
|
||||||
*(ptrszint *)(L->structure + (L->internal_structure_size * (++L->structures)) + L->user_structure_size) = i;
|
|
||||||
// allocate new index
|
|
||||||
if (L->indexes > L->indexes_last) {
|
|
||||||
if (L->index_cleanup != NULL)
|
|
||||||
free(L->index_cleanup);
|
|
||||||
L->index_cleanup = L->index;
|
|
||||||
int32 new_indexes_last = (L->indexes_last * 2) + 1;
|
|
||||||
ptrszint *temp = (ptrszint *)malloc(sizeof(ptrszint) * (new_indexes_last + 1));
|
|
||||||
memcpy(temp, L->index, sizeof(ptrszint) * (L->indexes_last + 1));
|
|
||||||
L->index = temp;
|
|
||||||
L->index[i] = (ptrszint)(L->structure + (L->internal_structure_size * L->structures));
|
|
||||||
L->indexes_last = new_indexes_last;
|
|
||||||
} else {
|
|
||||||
L->index[i] = (ptrszint)(L->structure + (L->internal_structure_size * L->structures));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (L->lock_add)
|
|
||||||
libqb_mutex_unlock(L->lock_add);
|
|
||||||
|
|
||||||
return i;
|
|
||||||
} // list_add
|
|
||||||
|
|
||||||
ptrszint list_remove(list *L, ptrszint i) { // returns -1 on success, 0 on failure
|
|
||||||
if (L->lock_remove)
|
|
||||||
libqb_mutex_lock(L->lock_remove);
|
|
||||||
|
|
||||||
if ((i < 1) || (i > L->indexes)) {
|
|
||||||
if (L->lock_remove)
|
|
||||||
libqb_mutex_unlock(L->lock_remove);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
uint8 *structure;
|
|
||||||
structure = (uint8 *)(L->index[i]);
|
|
||||||
if (!*(ptrszint *)(structure + L->user_structure_size)) {
|
|
||||||
if (L->lock_remove)
|
|
||||||
libqb_mutex_unlock(L->lock_remove);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
// expand buffer?
|
|
||||||
if ((L->structures_freed + 1) > L->structures_freed_last) {
|
|
||||||
ptrszint new_structures_freed_last;
|
|
||||||
new_structures_freed_last = (L->structures_freed_last * 2) + 1;
|
|
||||||
ptrszint *temp = (ptrszint *)malloc(sizeof(ptrszint) * (new_structures_freed_last + 1));
|
|
||||||
memcpy(temp, L->structure_freed, sizeof(ptrszint) * (L->structures_freed + 1));
|
|
||||||
if (L->structure_freed_cleanup != NULL)
|
|
||||||
free(L->structure_freed_cleanup);
|
|
||||||
L->structure_freed_cleanup = L->structure_freed;
|
|
||||||
L->structure_freed = temp;
|
|
||||||
L->structures_freed_last = new_structures_freed_last;
|
|
||||||
}
|
|
||||||
L->structure_freed[L->structures_freed + 1] = i;
|
|
||||||
*(ptrszint *)(structure + L->user_structure_size) = 0;
|
|
||||||
L->structures_freed++;
|
|
||||||
|
|
||||||
if (L->lock_remove)
|
|
||||||
libqb_mutex_unlock(L->lock_remove);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
void list_destroy(list *L) {
|
|
||||||
ptrszint i;
|
|
||||||
for (i = 1; i <= L->structure_bases; i++) {
|
|
||||||
free((void *)L->structure_base[i]);
|
|
||||||
}
|
|
||||||
free(L->structure_base);
|
|
||||||
free(L->structure_freed);
|
|
||||||
free(L);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *list_get(list *L, ptrszint i) { // Returns a pointer to an index's structure
|
|
||||||
if ((i < 1) || (i > L->indexes)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
uint8 *structure;
|
|
||||||
structure = (uint8 *)(L->index[i]);
|
|
||||||
if (!*(ptrszint *)(structure + L->user_structure_size))
|
|
||||||
return NULL;
|
|
||||||
return (void *)structure;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptrszint list_get_index(list *L, void *structure) { // Retrieves the index value of a structure
|
|
||||||
ptrszint i = *(ptrszint *)(((uint8 *)structure) + L->user_structure_size);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class special_handle_type {
|
enum class special_handle_type {
|
||||||
Invalid,
|
Invalid,
|
||||||
Stream,
|
Stream,
|
||||||
|
|
|
@ -7,6 +7,7 @@ libqb-objs-y += $(PATH_LIBQB)/src/filesystem.o
|
||||||
libqb-objs-y += $(PATH_LIBQB)/src/datetime.o
|
libqb-objs-y += $(PATH_LIBQB)/src/datetime.o
|
||||||
libqb-objs-y += $(PATH_LIBQB)/src/error_handle.o
|
libqb-objs-y += $(PATH_LIBQB)/src/error_handle.o
|
||||||
libqb-objs-y += $(PATH_LIBQB)/src/gfs.o
|
libqb-objs-y += $(PATH_LIBQB)/src/gfs.o
|
||||||
|
libqb-objs-y += $(PATH_LIBQB)/src/qblist.o
|
||||||
libqb-objs-y += $(PATH_LIBQB)/src/mem.o
|
libqb-objs-y += $(PATH_LIBQB)/src/mem.o
|
||||||
libqb-objs-y += $(PATH_LIBQB)/src/rounding.o
|
libqb-objs-y += $(PATH_LIBQB)/src/rounding.o
|
||||||
libqb-objs-y += $(PATH_LIBQB)/src/qbs.o
|
libqb-objs-y += $(PATH_LIBQB)/src/qbs.o
|
||||||
|
|
39
internal/c/libqb/include/qblist.h
Normal file
39
internal/c/libqb/include/qblist.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "mutex.h"
|
||||||
|
|
||||||
|
// List Interface
|
||||||
|
// Purpose: Unify and optimize the way QB64 references lists of objects (such as handles)
|
||||||
|
// Notes: Does not use index 0
|
||||||
|
struct list {
|
||||||
|
intptr_t user_structure_size;
|
||||||
|
intptr_t internal_structure_size;
|
||||||
|
uint8_t *structure; // block of structures of user-specified size
|
||||||
|
intptr_t structures;
|
||||||
|
intptr_t structures_last;
|
||||||
|
intptr_t *structure_freed; // quickly re-reference available structures after they have been removed
|
||||||
|
intptr_t *structure_freed_cleanup; // the previous *structure_freed memory block
|
||||||
|
intptr_t structures_freed;
|
||||||
|
intptr_t structures_freed_last;
|
||||||
|
intptr_t structure_base[64]; // every time the 'structure' block is full a new and larger block is allocated
|
||||||
|
// because the list doubles each time, 64 entries will never be exceeded
|
||||||
|
intptr_t structure_bases;
|
||||||
|
intptr_t *index; // pointers to the structures referred to by each index value
|
||||||
|
intptr_t *index_cleanup;
|
||||||
|
intptr_t indexes;
|
||||||
|
intptr_t indexes_last;
|
||||||
|
struct libqb_mutex *lock_add;
|
||||||
|
struct libqb_mutex *lock_remove;
|
||||||
|
};
|
||||||
|
|
||||||
|
list *list_new(intptr_t structure_size);
|
||||||
|
list *list_new_threadsafe(intptr_t structure_size);
|
||||||
|
void list_destroy(list *L);
|
||||||
|
|
||||||
|
intptr_t list_add(list *L);
|
||||||
|
intptr_t list_remove(list *L, intptr_t i); // returns -1 on success, 0 on failure
|
||||||
|
//
|
||||||
|
void *list_get(list *L, intptr_t i); // Returns a pointer to an index's structure
|
||||||
|
//
|
||||||
|
intptr_t list_get_index(list *L, void *structure); // Retrieves the index value of a structure
|
149
internal/c/libqb/src/qblist.cpp
Normal file
149
internal/c/libqb/src/qblist.cpp
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
|
||||||
|
#include "libqb-common.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "gui.h"
|
||||||
|
#include "qblist.h"
|
||||||
|
|
||||||
|
list *list_new(intptr_t structure_size) {
|
||||||
|
list *L;
|
||||||
|
L = (list *)calloc(1, sizeof(list));
|
||||||
|
L->structure = (uint8_t *)malloc(sizeof(uint8_t *));
|
||||||
|
L->structure_base[1] = (intptr_t)L->structure;
|
||||||
|
L->structure_bases = 1;
|
||||||
|
L->structure_freed = (intptr_t *)malloc(sizeof(intptr_t *));
|
||||||
|
L->index = (intptr_t *)malloc(sizeof(intptr_t *));
|
||||||
|
L->user_structure_size = structure_size;
|
||||||
|
L->internal_structure_size = structure_size + sizeof(intptr_t);
|
||||||
|
return L;
|
||||||
|
}
|
||||||
|
|
||||||
|
list *list_new_threadsafe(intptr_t structure_size) {
|
||||||
|
list *L = list_new(structure_size);
|
||||||
|
L->lock_add = libqb_mutex_new();
|
||||||
|
L->lock_remove = libqb_mutex_new();
|
||||||
|
return L;
|
||||||
|
}
|
||||||
|
|
||||||
|
intptr_t list_add(list *L) {
|
||||||
|
if (L->lock_add)
|
||||||
|
libqb_mutex_lock(L->lock_add);
|
||||||
|
|
||||||
|
intptr_t i;
|
||||||
|
if (L->structures_freed) { // retrieve index from freed list if possible
|
||||||
|
if (L->lock_remove)
|
||||||
|
libqb_mutex_lock(L->lock_remove);
|
||||||
|
|
||||||
|
i = L->structure_freed[L->structures_freed--];
|
||||||
|
uint8_t *structure;
|
||||||
|
structure = (uint8_t *)L->index[i];
|
||||||
|
memset(structure, 0, L->user_structure_size);
|
||||||
|
*(intptr_t *)(structure + L->user_structure_size) = i;
|
||||||
|
|
||||||
|
if (L->lock_remove)
|
||||||
|
libqb_mutex_unlock(L->lock_remove);
|
||||||
|
} else {
|
||||||
|
// create new buffer?
|
||||||
|
if ((L->structures + 1) > L->structures_last) {
|
||||||
|
intptr_t new_structures_last;
|
||||||
|
new_structures_last = (L->structures_last * 2) + 1;
|
||||||
|
// note: L->structure is only modified by list_add
|
||||||
|
L->structure = (uint8_t *)calloc(1, L->internal_structure_size * (new_structures_last + 1));
|
||||||
|
if (L->structure == NULL) {
|
||||||
|
gui_alert("list_add: failed to allocate new buffer, structure size: %lld", (int64_t)L->internal_structure_size);
|
||||||
|
}
|
||||||
|
L->structures_last = new_structures_last;
|
||||||
|
L->structures = 0;
|
||||||
|
L->structure_base[++L->structure_bases] = (intptr_t)L->structure;
|
||||||
|
}
|
||||||
|
i = ++L->indexes;
|
||||||
|
*(intptr_t *)(L->structure + (L->internal_structure_size * (++L->structures)) + L->user_structure_size) = i;
|
||||||
|
// allocate new index
|
||||||
|
if (L->indexes > L->indexes_last) {
|
||||||
|
if (L->index_cleanup != NULL)
|
||||||
|
free(L->index_cleanup);
|
||||||
|
L->index_cleanup = L->index;
|
||||||
|
int32_t new_indexes_last = (L->indexes_last * 2) + 1;
|
||||||
|
intptr_t *temp = (intptr_t *)malloc(sizeof(intptr_t) * (new_indexes_last + 1));
|
||||||
|
memcpy(temp, L->index, sizeof(intptr_t) * (L->indexes_last + 1));
|
||||||
|
L->index = temp;
|
||||||
|
L->index[i] = (intptr_t)(L->structure + (L->internal_structure_size * L->structures));
|
||||||
|
L->indexes_last = new_indexes_last;
|
||||||
|
} else {
|
||||||
|
L->index[i] = (intptr_t)(L->structure + (L->internal_structure_size * L->structures));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (L->lock_add)
|
||||||
|
libqb_mutex_unlock(L->lock_add);
|
||||||
|
|
||||||
|
return i;
|
||||||
|
} // list_add
|
||||||
|
|
||||||
|
intptr_t list_remove(list *L, intptr_t i) { // returns -1 on success, 0 on failure
|
||||||
|
if (L->lock_remove)
|
||||||
|
libqb_mutex_lock(L->lock_remove);
|
||||||
|
|
||||||
|
if ((i < 1) || (i > L->indexes)) {
|
||||||
|
if (L->lock_remove)
|
||||||
|
libqb_mutex_unlock(L->lock_remove);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint8_t *structure;
|
||||||
|
structure = (uint8_t *)(L->index[i]);
|
||||||
|
if (!*(intptr_t *)(structure + L->user_structure_size)) {
|
||||||
|
if (L->lock_remove)
|
||||||
|
libqb_mutex_unlock(L->lock_remove);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// expand buffer?
|
||||||
|
if ((L->structures_freed + 1) > L->structures_freed_last) {
|
||||||
|
intptr_t new_structures_freed_last;
|
||||||
|
new_structures_freed_last = (L->structures_freed_last * 2) + 1;
|
||||||
|
intptr_t *temp = (intptr_t *)malloc(sizeof(intptr_t) * (new_structures_freed_last + 1));
|
||||||
|
memcpy(temp, L->structure_freed, sizeof(intptr_t) * (L->structures_freed + 1));
|
||||||
|
if (L->structure_freed_cleanup != NULL)
|
||||||
|
free(L->structure_freed_cleanup);
|
||||||
|
L->structure_freed_cleanup = L->structure_freed;
|
||||||
|
L->structure_freed = temp;
|
||||||
|
L->structures_freed_last = new_structures_freed_last;
|
||||||
|
}
|
||||||
|
L->structure_freed[L->structures_freed + 1] = i;
|
||||||
|
*(intptr_t *)(structure + L->user_structure_size) = 0;
|
||||||
|
L->structures_freed++;
|
||||||
|
|
||||||
|
if (L->lock_remove)
|
||||||
|
libqb_mutex_unlock(L->lock_remove);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
void list_destroy(list *L) {
|
||||||
|
intptr_t i;
|
||||||
|
for (i = 1; i <= L->structure_bases; i++) {
|
||||||
|
free((void *)L->structure_base[i]);
|
||||||
|
}
|
||||||
|
free(L->structure_base);
|
||||||
|
free(L->structure_freed);
|
||||||
|
free(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *list_get(list *L, intptr_t i) { // Returns a pointer to an index's structure
|
||||||
|
if ((i < 1) || (i > L->indexes)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
uint8_t *structure;
|
||||||
|
structure = (uint8_t *)(L->index[i]);
|
||||||
|
if (!*(intptr_t *)(structure + L->user_structure_size))
|
||||||
|
return NULL;
|
||||||
|
return (void *)structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
intptr_t list_get_index(list *L, void *structure) { // Retrieves the index value of a structure
|
||||||
|
intptr_t i = *(intptr_t *)(((uint8_t *)structure) + L->user_structure_size);
|
||||||
|
return i;
|
||||||
|
}
|
Loading…
Reference in a new issue