]> git.lizzy.rs Git - nothing.git/commitdiff
Merge pull request #1236 from tsoding/remove-realloc-stack
authorAlexey Kutepov <reximkut@gmail.com>
Sun, 5 Jan 2020 18:45:17 +0000 (01:45 +0700)
committerGitHub <noreply@github.com>
Sun, 5 Jan 2020 18:45:17 +0000 (01:45 +0700)
Remove realloc stack

12 files changed:
CMakeLists.txt
nothing.c
src/config.h
src/game.c
src/game/level/level_editor.c
src/game/level/level_editor/undo_history.c
src/game/level/level_editor/undo_history.h
src/ring_buffer.c [new file with mode: 0644]
src/ring_buffer.h [new file with mode: 0644]
src/stack.h [deleted file]
src/system/nth_alloc.c
src/system/nth_alloc.h

index 23e623e45922095de400dfd251ff40efec0804b6..2c702734189446c3169ad0e3a2717f95917f8d70 100644 (file)
@@ -160,6 +160,8 @@ add_executable(nothing
   src/dynarray.c
   src/system/file.h
   src/system/file.c
+  src/ring_buffer.h
+  src/ring_buffer.c
 )
 target_link_libraries(nothing ${SDL2_LIBRARIES})
 
index ba503438a35e219ff976c0f7c86a638fd992bb31..0c0a9482bc4147c48b2690d8fb296b234c675131 100644 (file)
--- a/nothing.c
+++ b/nothing.c
@@ -50,3 +50,4 @@
 #include "src/system/str.c"
 #include "src/dynarray.c"
 #include "src/system/file.c"
+#include "src/ring_buffer.c"
index b062ebca04cc38bb20bfd2ebab04dae1d27d3931..1431bb0b8ebc8a7cf61585835e7e928cb703c0d3 100644 (file)
@@ -31,4 +31,6 @@
 // #define RENDERER_CONFIG SDL_RENDERER_SOFTWARE
 #define RENDERER_CONFIG (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC)
 
+#define UNDO_HISTORY_CAPACITY 256
+
 #endif  // CONFIG_H_
index 2dd84e4c46cf364a7269cff4c04a57b7cb945400..7e59f094b5dccccd2476bb10a8a54adf6f105bdb 100644 (file)
@@ -413,7 +413,8 @@ int game_event(Game *game, const SDL_Event *event)
     } break;
 
     case SDL_KEYDOWN: {
-        if (event->key.keysym.sym == SDLK_q && event->key.keysym.mod & KMOD_CTRL) {
+        if ((event->key.keysym.sym == SDLK_q && event->key.keysym.mod & KMOD_CTRL) ||
+            (event->key.keysym.sym == SDLK_F4 && event->key.keysym.mod & KMOD_ALT)) {
             game_switch_state(game, GAME_STATE_QUIT);
             return 0;
         }
index 36f80f45ae80d86fb832cf3ada2464040feab5e9..7101150138cd59e762d232e5c229ab1444d420dc 100644 (file)
@@ -140,6 +140,8 @@ LevelEditor *create_level_editor(Cursor *cursor)
 
     level_editor->camera_scale = 1.0f;
 
+    level_editor->undo_history = create_undo_history();
+
     return level_editor;
 }
 
@@ -228,7 +230,7 @@ LevelEditor *create_level_editor_from_file(const char *file_name, Cursor *cursor
 
     level_editor->camera_scale = 1.0f;
 
-    log_info("%ld bytes of tmp memory consumed during parsing the level\n", tmpmem.size);
+    level_editor->undo_history = create_undo_history();
 
     free(tmpmem.buffer);
 
index 7a51aaba9e62a87d5643bd631e5ca252b1e9b03d..e5b6d428bb3c0bb4d25f96840e0cde87901545b4 100644 (file)
@@ -7,10 +7,29 @@
 #include "system/lt.h"
 #include "system/stacktrace.h"
 #include "undo_history.h"
+#include "config.h"
 
 typedef struct {
     RevertAction revert;
-} HistoryAction;
+    void *context_data;
+    size_t context_data_size;
+} HistoryItem;
+
+static
+void undo_history_destroy_item(void *item)
+{
+    free(((HistoryItem*)item)->context_data);
+}
+
+UndoHistory create_undo_history(void)
+{
+    UndoHistory result;
+    result.actions = create_ring_buffer(
+        sizeof(HistoryItem),
+        UNDO_HISTORY_CAPACITY,
+        undo_history_destroy_item);
+    return result;
+}
 
 void undo_history_push(UndoHistory *undo_history,
                        RevertAction revert,
@@ -19,26 +38,24 @@ void undo_history_push(UndoHistory *undo_history,
 {
     trace_assert(undo_history);
 
-    HistoryAction action = {
+    HistoryItem item = {
         .revert = revert,
+        .context_data = malloc(context_data_size),
+        .context_data_size = context_data_size
     };
+    trace_assert(item.context_data);
+    memcpy(item.context_data, context_data, context_data_size);
 
-    stack_push(&undo_history->actions, context_data, context_data_size);
-    stack_push(&undo_history->actions, &action, sizeof(action));
+    ring_buffer_push(&undo_history->actions, &item);
 }
 
 void undo_history_pop(UndoHistory *undo_history)
 {
     trace_assert(undo_history);
 
-    if (stack_empty(&undo_history->actions) > 0) {
-        HistoryAction action = *(HistoryAction *)stack_top_element(&undo_history->actions);
-        stack_pop(&undo_history->actions);
-
-        size_t context_size = stack_top_size(&undo_history->actions);
-        void *context = stack_top_element(&undo_history->actions);
-
-        action.revert(context, context_size);
-        stack_pop(&undo_history->actions);
+    if (undo_history->actions.count > 0) {
+        HistoryItem *item = ring_buffer_top(&undo_history->actions);
+        item->revert(item->context_data, item->context_data_size);
+        ring_buffer_pop(&undo_history->actions);
     }
 }
index bb671d123afbe16840872d4de33652c339b06bf1..e5af7ccbefd655566bf38133f085426640bf0a2d 100644 (file)
@@ -1,18 +1,20 @@
 #ifndef UNDO_HISTORY_H_
 #define UNDO_HISTORY_H_
 
-#include "stack.h"
+#include "ring_buffer.h"
 
 typedef void (*RevertAction)(void *context, size_t context_size);
 
 typedef struct {
-    Stack actions;
+    RingBuffer actions;
 } UndoHistory;
 
+UndoHistory create_undo_history(void);
+
 static inline
 void destroy_undo_history(UndoHistory undo_history)
 {
-    destroy_stack(undo_history.actions);
+    destroy_ring_buffer(undo_history.actions);
 }
 
 void undo_history_push(UndoHistory *undo_history,
@@ -24,7 +26,7 @@ void undo_history_pop(UndoHistory *undo_history);
 static inline
 int undo_history_empty(UndoHistory *undo_history)
 {
-    return undo_history->actions.size == 0;
+    return undo_history->actions.count == 0;
 }
 
 #endif  // UNDO_HISTORY_H_
diff --git a/src/ring_buffer.c b/src/ring_buffer.c
new file mode 100644 (file)
index 0000000..905d177
--- /dev/null
@@ -0,0 +1,50 @@
+#include "ring_buffer.h"
+#include "system/stacktrace.h"
+
+void ring_buffer_push(RingBuffer *buffer,
+                      void *element)
+{
+    trace_assert(buffer);
+    trace_assert(element);
+
+    size_t i = (buffer->begin + buffer->count) % buffer->capacity;
+
+    if (buffer->count < buffer->capacity) {
+        memcpy(
+            buffer->data + i * buffer->element_size,
+            element,
+            buffer->element_size);
+        buffer->count += 1;
+    } else {
+        if (buffer->dtor) buffer->dtor(buffer->data + i * buffer->element_size);
+        memcpy(
+            buffer->data + i * buffer->element_size,
+            element,
+            buffer->element_size);
+        buffer->begin = (buffer->begin + 1) % buffer->capacity;
+    }
+}
+
+int ring_buffer_pop(RingBuffer *buffer)
+{
+    trace_assert(buffer);
+
+    if (buffer->count == 0) return 0;
+
+    if (buffer->dtor) {
+        size_t i = (buffer->begin + buffer->count - 1) % buffer->capacity;
+        buffer->dtor(buffer->data + i * buffer->element_size);
+    }
+
+    buffer->count--;
+
+    return 1;
+}
+
+void *ring_buffer_top(RingBuffer *buffer)
+{
+    trace_assert(buffer);
+    if (buffer->count == 0) return NULL;
+    size_t i = (buffer->begin + buffer->count - 1) % buffer->capacity;
+    return buffer->data + i * buffer->element_size;
+}
diff --git a/src/ring_buffer.h b/src/ring_buffer.h
new file mode 100644 (file)
index 0000000..acb86e2
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef RING_BUFFER_H_
+#define RING_BUFFER_H_
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+typedef void (*RingBufferDtor)(void *element);
+
+typedef struct {
+    size_t element_size;
+    size_t capacity;
+    size_t count;
+    size_t begin;
+    uint8_t *data;
+    RingBufferDtor dtor;
+} RingBuffer;
+
+static inline
+RingBuffer create_ring_buffer(size_t element_size,
+                              size_t capacity,
+                              RingBufferDtor dtor)
+{
+    RingBuffer result = {0};
+    result.element_size = element_size;
+    result.capacity = capacity;
+    result.dtor = dtor;
+    result.data = malloc(result.element_size * result.capacity);
+    return result;
+}
+
+static inline
+void destroy_ring_buffer(RingBuffer buffer)
+{
+    free(buffer.data);
+}
+
+void ring_buffer_push(RingBuffer *buffer, void *element);
+int ring_buffer_pop(RingBuffer *buffer);
+void *ring_buffer_top(RingBuffer *buffer);
+
+#endif  // RING_BUFFER_H_
diff --git a/src/stack.h b/src/stack.h
deleted file mode 100644 (file)
index 3ab4454..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-#ifndef STACK_H_
-#define STACK_H_
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <system/stacktrace.h>
-
-typedef struct {
-    size_t capacity;
-    size_t size;
-    char *bottom;
-} Stack;
-
-static inline
-void destroy_stack(Stack stack)
-{
-    free(stack.bottom);
-}
-
-static inline
-void stack_grow(Stack *stack, size_t new_capacity)
-{
-    trace_assert(stack);
-    trace_assert(stack->capacity < new_capacity);
-
-    stack->bottom = realloc(stack->bottom, new_capacity);
-    stack->capacity = new_capacity;
-}
-
-static inline
-void stack_push(Stack *stack, const void *element, size_t element_size)
-{
-    trace_assert(stack);
-    trace_assert(element);
-    trace_assert(element_size > 0);
-
-    size_t frame_size = element_size + sizeof(element_size);
-
-    if (frame_size >= (stack->capacity - stack->size)) {
-        stack_grow(stack, stack->capacity * 2 + frame_size);
-    }
-
-    trace_assert(stack->bottom);
-
-    memcpy(stack->bottom + stack->size, element, element_size);
-    stack->size += element_size;
-    memcpy(stack->bottom + stack->size, &element_size, sizeof(element_size));
-    stack->size += sizeof(element_size);
-}
-
-static inline
-size_t stack_top_size(const Stack *stack)
-{
-    trace_assert(stack);
-    trace_assert(stack->size > 0);
-    trace_assert(stack->bottom);
-    size_t stack_size = 0;
-    memcpy(&stack_size, stack->bottom + stack->size - sizeof(size_t), sizeof(size_t));
-    return stack_size;
-}
-
-static inline
-void *stack_top_element(const Stack *stack)
-{
-    trace_assert(stack);
-    trace_assert(stack->size > 0);
-    trace_assert(stack->bottom);
-    size_t element_size = stack_top_size(stack);
-    return stack->bottom + stack->size - element_size - sizeof(size_t);
-}
-
-static inline
-void stack_pop(Stack *stack)
-{
-    trace_assert(stack);
-    trace_assert(stack->size > 0);
-    size_t element_size = stack_top_size(stack);
-    stack->size -= element_size + sizeof(size_t);
-}
-
-static inline
-int stack_empty(Stack *stack)
-{
-    trace_assert(stack);
-    return stack->size > 0;
-}
-
-#endif  // STACK_H_
index bcf946c6f219005ead768a942d166838abdf47ef..59bc7cb7ca1a35394d2893268639482954ea0d32 100644 (file)
@@ -12,14 +12,3 @@ void *nth_calloc(size_t num, size_t size)
 
     return mem;
 }
-
-void *nth_realloc(void *ptr, size_t new_size)
-{
-    void *mem = realloc(ptr, new_size);
-
-    if (mem == NULL) {
-        log_fail("nth_realloc(0x%x, %lu) failed", ptr, new_size);
-    }
-
-    return mem;
-}
index 8968b34b203ccb7a1f3655aa7d54e31251e2e121..63ac3f747530dbb7948134b3afbfc7f089a05609 100644 (file)
@@ -4,6 +4,5 @@
 #include <stdlib.h>
 
 void *nth_calloc(size_t num, size_t size);
-void *nth_realloc(void *ptr, size_t new_size);
 
 #endif  // NTH_ALLOC_H_