Introduce new Lt

master
rexim 2019-05-13 00:30:18 +07:00
parent 9e7a466c79
commit c8ad98bcee
5 changed files with 96 additions and 249 deletions

View File

@ -34,12 +34,9 @@ add_library(system STATIC
src/system/log.h
src/system/log_script.c
src/system/log_script.h
src/system/lt.c
src/system/lt.h
src/system/lt/lt_adapters.c
src/system/lt/lt_adapters.h
src/system/lt/lt_slot.c
src/system/lt/lt_slot.h
src/system/nth_alloc.c
src/system/nth_alloc.h
src/system/stacktrace.c

View File

@ -1,126 +0,0 @@
#include "system/stacktrace.h"
#include <stdio.h>
#include <stdlib.h>
#include "lt.h"
#include "lt/lt_slot.h"
#include "system/nth_alloc.h"
#define INITIAL_FRAME_BUFFER_SIZE 16
struct Lt
{
Lt_slot **frames;
size_t capacity;
size_t size;
};
Lt *create_lt()
{
Lt *lt = nth_calloc(1, sizeof(Lt));
if(lt == NULL) {
goto nth_alloc_lt_fail;
}
lt->frames = nth_calloc(1, sizeof(Lt_slot*) * INITIAL_FRAME_BUFFER_SIZE);
if (lt->frames == NULL) {
goto nth_alloc_lt_slots_fail;
}
lt->capacity = INITIAL_FRAME_BUFFER_SIZE;
lt->size = 0;
return lt;
nth_alloc_lt_slots_fail:
free(lt);
nth_alloc_lt_fail:
return NULL;
}
void destroy_lt(Lt *lt)
{
trace_assert(lt);
while (lt->size-- > 0) {
if (lt->frames[lt->size]) {
destroy_lt_slot(lt->frames[lt->size]);
}
}
free(lt->frames);
free(lt);
}
void *lt_push(Lt *lt, void *resource, Lt_destroy resource_destroy)
{
trace_assert(lt);
trace_assert(resource_destroy);
trace_assert(lt != resource);
if (resource == NULL) {
return NULL;
}
if (lt->size >= lt->capacity) {
lt->capacity *= 2;
if ((lt->frames = nth_realloc(lt->frames, sizeof(Lt_slot*) * lt->capacity)) == NULL) {
return NULL;
}
}
if ((lt->frames[lt->size++] = create_lt_slot(resource, resource_destroy)) == NULL) {
return NULL;
}
return resource;
}
void* lt_reset(Lt *lt, void *old_resource, void *new_resource)
{
trace_assert(lt);
trace_assert(old_resource);
trace_assert(new_resource);
trace_assert(old_resource != new_resource);
for (size_t i = 0; i < lt->size; ++i) {
if (lt->frames[i] && lt_slot_contains_resource(lt->frames[i], old_resource)) {
lt_slot_reset_resource(lt->frames[i], new_resource);
return new_resource;
}
}
return old_resource;
}
void *lt_release(Lt *lt, void *resource)
{
trace_assert(lt);
trace_assert(resource);
for (size_t i = 0; i < lt->size; ++i) {
if (lt->frames[i] && lt_slot_contains_resource(lt->frames[i], resource)) {
release_lt_slot(lt->frames[i]);
lt->frames[i] = NULL;
return resource;
}
}
return resource;
}
void *lt_replace(Lt *lt, void *old_resource, void *new_resource)
{
trace_assert(lt);
trace_assert(old_resource);
trace_assert(new_resource);
for (size_t i = 0; i < lt->size; ++i) {
if (lt->frames[i] && lt_slot_contains_resource(lt->frames[i], old_resource)) {
lt_slot_replace_resource(lt->frames[i], new_resource);
return new_resource;
}
}
return old_resource;
}

View File

@ -1,50 +1,112 @@
#ifndef LT_H_
#define LT_H_
#define PUSH_LT(lt, resource, resource_destroy) \
lt_push(lt, (void*)resource, (Lt_destroy)resource_destroy)
#include <assert.h>
#include <string.h>
#define RESET_LT(lt, old_resource, new_resource) \
lt_reset(lt, (void*)old_resource, (void*)new_resource)
#define LT_INITIAL_CAPACITY 2
#define REPLACE_LT(lt, old_resource, new_resource) \
lt_replace(lt, (void*)old_resource, (void*)new_resource)
typedef void (*Dtor)(void*);
#define RELEASE_LT(lt, resource) \
lt_release(lt, (void*) resource)
typedef struct {
void *res;
Dtor dtor;
} Slot;
#define RETURN_LT(lt, result) \
do { \
destroy_lt(lt); \
return result; \
} while (0)
typedef struct {
size_t size;
size_t capacity;
Slot *slots;
} Lt;
#define RETURN_LT0(lt) \
do { \
destroy_lt(lt); \
return; \
} while (0)
static inline void destroy_lt(Lt lt)
{
for (size_t i = lt.size; i > 0; --i) {
if (lt.slots[i - 1].res) {
lt.slots[i - 1].dtor(lt.slots[i - 1].res);
}
}
typedef struct Lt Lt;
typedef void (*Lt_destroy)(void*);
free(lt.slots);
}
Lt *create_lt(void);
void destroy_lt(Lt *lt);
#define PUSH_LT(lt, res, dtor) \
lt_push(&lt, (void*)res, (Dtor)dtor)
/** \brief Pushes the resource onto the Life Time creating a new Life Time frame.
*/
void *lt_push(Lt *lt, void *resource, Lt_destroy resource_destroy);
static inline void *lt_push(Lt *lt, void *res, Dtor dtor)
{
if (lt->size >= lt->capacity) {
if (lt->capacity == 0) {
lt->capacity = LT_INITIAL_CAPACITY;
lt->slots = calloc(LT_INITIAL_CAPACITY, sizeof(Slot));
} else {
lt->capacity *= 2;
lt->slots = realloc(lt->slots, lt->capacity * sizeof(Slot));
}
}
/** \brief Destroys old_resource preserving its LT frame and assigns the new_resource to the LT frame.
*/
void *lt_reset(Lt *lt, void *old_resource, void *new_resource);
lt->slots[lt->size].res = res;
lt->slots[lt->size].dtor = dtor;
lt->size++;
/** \brief Replaces old_resource with new_resource in the LT frame without destroying old_resource.
*/
void *lt_replace(Lt *lt, void *old_resource, void *new_resource);
return res;
}
/** \brief Removes the LT frame of resource without destroying the resource.
*/
void *lt_release(Lt *lt, void *resource);
#define RETURN_LT(lt, result) \
return (destroy_lt(lt), result)
#define RETURN_LT0(lt) (destroy_lt(lt), return)
#define RESET_LT(lt, old_res, new_res) \
lt_reset(&lt, (void*) old_res, (void*) new_res)
static inline void *lt_reset(Lt *lt, void *old_res, void *new_res)
{
assert(old_res != new_res);
for (size_t i = 0; i < lt->size; ++i) {
if (lt->slots[i].res == old_res) {
lt->slots[i].dtor(old_res);
lt->slots[i].res = new_res;
return new_res;
}
}
return NULL;
}
#define REPLACE_LT(lt, old_res, new_res) \
lt_replace(&lt, (void *)old_res, (void*)new_res)
static inline void *lt_replace(Lt *lt, void *old_res, void *new_res)
{
for (size_t i = 0; i < lt->size; ++i) {
if (lt->slots[i].res == old_res) {
lt->slots[i].res = new_res;
return new_res;
}
}
return NULL;
}
#define RELEASE_LT(lt, res) \
lt_release(&lt, (void*)res)
static inline void *lt_release(Lt *lt, void *res)
{
for (size_t i = 0; i < lt->size; ++i) {
if (lt->slots[i].res == res) {
memmove(
&lt->slots[i],
&lt->slots[i + 1],
(lt->size - i - 1) * sizeof(Slot));
lt->size--;
return res;
}
}
return NULL;
}
#endif // LT_H_

View File

@ -1,70 +0,0 @@
#include "system/stacktrace.h"
#include <stdio.h>
#include <stdlib.h>
#include "lt_slot.h"
#include "system/nth_alloc.h"
struct Lt_slot
{
void *resource;
Lt_destroy resource_destroy;
};
Lt_slot *create_lt_slot(void *resource, Lt_destroy resource_destroy)
{
trace_assert(resource);
trace_assert(resource_destroy);
Lt_slot *lt_slot = nth_calloc(1, sizeof(Lt_slot));
if (lt_slot == NULL) {
return NULL;
}
lt_slot->resource = resource;
lt_slot->resource_destroy = resource_destroy;
return lt_slot;
}
void *release_lt_slot(Lt_slot *lt_slot)
{
trace_assert(lt_slot);
void *resource = lt_slot->resource;
free(lt_slot);
return resource;
}
void destroy_lt_slot(Lt_slot *lt_slot)
{
trace_assert(lt_slot);
lt_slot->resource_destroy(lt_slot->resource);
free(lt_slot);
}
void lt_slot_reset_resource(Lt_slot *lt_slot, void *resource)
{
trace_assert(lt_slot);
trace_assert(resource);
lt_slot->resource_destroy(lt_slot->resource);
lt_slot->resource = resource;
}
void lt_slot_replace_resource(Lt_slot *lt_slot, void *resource)
{
trace_assert(lt_slot);
trace_assert(resource);
lt_slot->resource = resource;
}
int lt_slot_contains_resource(const Lt_slot *lt_slot, void *resource)
{
trace_assert(lt_slot);
trace_assert(resource);
return lt_slot->resource == resource;
}

View File

@ -1,16 +0,0 @@
#ifndef LT_SLOT_H_
#define LT_SLOT_H_
#include "../lt.h"
typedef struct Lt_slot Lt_slot;
Lt_slot *create_lt_slot(void *resource, Lt_destroy resource_destroy);
void *release_lt_slot(Lt_slot *lt_slot);
void destroy_lt_slot(Lt_slot *lt_slot);
void lt_slot_reset_resource(Lt_slot *lt_slot, void *resource);
void lt_slot_replace_resource(Lt_slot *lt_slot, void *resource);
int lt_slot_contains_resource(const Lt_slot *lt_slot, void *resource);
#endif // LT_SLOT_H_