From 9a73b698d4045fcf19a46193cecde62bb9626bae Mon Sep 17 00:00:00 2001 From: rubidium Date: Sun, 13 Apr 2008 19:25:14 +0000 Subject: (svn r12695) -Codechange: only allocate window structs when needed. Based on a patch by Alberth. --- src/core/alloc_func.hpp | 52 ------------------------ src/core/alloc_type.hpp | 102 ++++++++++++++++++++++++++++++++++++++++++++++++ src/misc.cpp | 2 +- src/pathfind.cpp | 2 +- src/viewport.cpp | 2 +- src/window.cpp | 36 ++++------------- src/window_gui.h | 3 +- 7 files changed, 114 insertions(+), 85 deletions(-) create mode 100644 src/core/alloc_type.hpp (limited to 'src') diff --git a/src/core/alloc_func.hpp b/src/core/alloc_func.hpp index 57a5fc3d4..2a31f8637 100644 --- a/src/core/alloc_func.hpp +++ b/src/core/alloc_func.hpp @@ -90,56 +90,4 @@ template FORCEINLINE T* ReallocT(T *t_ptr, size_t num_elements) return t_ptr; } -/** - * A small 'wrapper' for allocations that can be done on most OSes on the - * stack, but are just too large to fit in the stack on devices with a small - * stack such as the NDS. - * So when it is possible a stack allocation is made, otherwise a heap - * allocation is made and this is freed once the struct goes out of scope. - * @param T the type to make the allocation for - * @param length the amount of items to allocate - */ -template -struct SmallStackSafeStackAlloc { -#if !defined(__NDS__) - /** Storing the data on the stack */ - T data[length]; -#else - /** Storing it on the heap */ - T *data; - /** The length (in elements) of data in this allocator. */ - size_t len; - - /** Allocating the memory */ - SmallStackSafeStackAlloc() : data(MallocT(length)), len(length) {} - /** And freeing when it goes out of scope */ - ~SmallStackSafeStackAlloc() { free(data); } -#endif - - /** - * Gets a pointer to the data stored in this wrapper. - * @return the pointer. - */ - inline operator T* () { return data; } - - /** - * Gets a pointer to the data stored in this wrapper. - * @return the pointer. - */ - inline T* operator -> () { return data; } - - /** - * Gets a pointer to the last data element stored in this wrapper. - * @note needed because endof does not work properly for pointers. - * @return the 'endof' pointer. - */ - inline T* EndOf() { -#if !defined(__NDS__) - return endof(data); -#else - return &data[len]; -#endif - } -}; - #endif /* ALLOC_FUNC_HPP */ diff --git a/src/core/alloc_type.hpp b/src/core/alloc_type.hpp new file mode 100644 index 000000000..4146e5ca3 --- /dev/null +++ b/src/core/alloc_type.hpp @@ -0,0 +1,102 @@ + +/* $Id$ */ + +/** @file alloc_type.hpp Helper types related to the allocation of memory */ + +#ifndef ALLOC_TYPE_HPP +#define ALLOC_TYPE_HPP + +#include "alloc_func.hpp" + +/** + * A small 'wrapper' for allocations that can be done on most OSes on the + * stack, but are just too large to fit in the stack on devices with a small + * stack such as the NDS. + * So when it is possible a stack allocation is made, otherwise a heap + * allocation is made and this is freed once the struct goes out of scope. + * @param T the type to make the allocation for + * @param length the amount of items to allocate + */ +template +struct SmallStackSafeStackAlloc { +#if !defined(__NDS__) + /** Storing the data on the stack */ + T data[length]; +#else + /** Storing it on the heap */ + T *data; + /** The length (in elements) of data in this allocator. */ + size_t len; + + /** Allocating the memory */ + SmallStackSafeStackAlloc() : data(MallocT(length)), len(length) {} + /** And freeing when it goes out of scope */ + ~SmallStackSafeStackAlloc() { free(data); } +#endif + + /** + * Gets a pointer to the data stored in this wrapper. + * @return the pointer. + */ + inline operator T* () { return data; } + + /** + * Gets a pointer to the data stored in this wrapper. + * @return the pointer. + */ + inline T* operator -> () { return data; } + + /** + * Gets a pointer to the last data element stored in this wrapper. + * @note needed because endof does not work properly for pointers. + * @return the 'endof' pointer. + */ + inline T* EndOf() { +#if !defined(__NDS__) + return endof(data); +#else + return &data[len]; +#endif + } +}; + +/** + * Base class that provides memory initialization on dynamically created objects. + * All allocated memory will be zeroed. + */ +class ZeroedMemoryAllocator +{ +public: + ZeroedMemoryAllocator() {} + virtual ~ZeroedMemoryAllocator() {} + + /** + * Memory allocator for a single class instance. + * @param size the amount of bytes to allocate. + * @return the given amounts of bytes zeroed. + */ + void *operator new(size_t size) { return CallocT(size); } + + /** + * Memory allocator for an array of class instances. + * @param size the amount of bytes to allocate. + * @return the given amounts of bytes zeroed. + */ + void *operator new[](size_t size) { return CallocT(size); } + + /** + * Memory release for a single class instance. + * @param ptr the memory to free. + * @param size the amount of allocated memory (unused). + */ + void operator delete(void *ptr, size_t size) { free(ptr); } + + /** + * Memory release for an array of class instances. + * @param ptr the memory to free. + * @param size the amount of allocated memory (unused). + */ + void operator delete[](void *ptr, size_t size) { free(ptr); } +}; + +#endif /* ALLOC_TYPE_HPP */ diff --git a/src/misc.cpp b/src/misc.cpp index a9c65b774..6a3d199ed 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -24,7 +24,7 @@ #include "texteff.hpp" #include "string_func.h" #include "gfx_func.h" -#include "core/alloc_func.hpp" +#include "core/alloc_type.hpp" #include "table/strings.h" #include "table/sprites.h" diff --git a/src/pathfind.cpp b/src/pathfind.cpp index e16836b17..89435aa39 100644 --- a/src/pathfind.cpp +++ b/src/pathfind.cpp @@ -17,7 +17,7 @@ #include "depot.h" #include "tunnelbridge_map.h" #include "core/random_func.hpp" -#include "core/alloc_func.hpp" +#include "core/alloc_type.hpp" #include "tunnelbridge.h" /* remember which tiles we have already visited so we don't visit them again. */ diff --git a/src/viewport.cpp b/src/viewport.cpp index 8f7a1df2d..008d949a9 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -27,7 +27,7 @@ #include "player_func.h" #include "settings_type.h" #include "station_func.h" -#include "core/alloc_func.hpp" +#include "core/alloc_type.hpp" #include "table/sprites.h" #include "table/strings.h" diff --git a/src/window.cpp b/src/window.cpp index 082f1c302..ac5ec8022 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -25,14 +25,12 @@ static Point _drag_delta; ///< delta between mouse cursor and upper left corner of dragged window static Window *_mouseover_last_w = NULL; ///< Window of the last MOUSEOVER event -static Window _windows[MAX_NUMBER_OF_WINDOWS]; - /** * List of windows opened at the screen. * Uppermost window is at _z_windows[_last_z_window - 1], * bottom window is at _z_windows[0] */ -Window *_z_windows[lengthof(_windows)]; +Window *_z_windows[MAX_NUMBER_OF_WINDOWS]; Window **_last_z_window; ///< always points to the next free space in the z-array Point _cursorpos_drag_start; @@ -433,6 +431,8 @@ void DeleteWindow(Window *w) if (wz == NULL) return; memmove(wz, wz + 1, (byte*)_last_z_window - (byte*)wz); _last_z_window--; + + delete w; } /** @@ -655,28 +655,6 @@ void AssignWidgetToWindow(Window *w, const Widget *widget) } } -static Window *FindFreeWindow() -{ - Window *w; - - for (w = _windows; w < endof(_windows); w++) { - Window* const *wz; - bool window_in_use = false; - - FOR_ALL_WINDOWS(wz) { - if (*wz == w) { - window_in_use = true; - break; - } - } - - if (!window_in_use) return w; - } - - assert(_last_z_window == endof(_z_windows)); - return NULL; -} - /** Open a new window. * This function is called from AllocateWindow() or AllocateWindowDesc() * See descriptions for those functions for usage @@ -697,17 +675,18 @@ static Window *FindFreeWindow() static Window *LocalAllocateWindow(int x, int y, int min_width, int min_height, int def_width, int def_height, WindowProc *proc, WindowClass cls, const Widget *widget, int window_number, void *data) { - Window *w = FindFreeWindow(); + Window *w; /* We have run out of windows, close one and use that as the place for our new one */ - if (w == NULL) { + if (_last_z_window == endof(_z_windows)) { w = FindDeletableWindow(); if (w == NULL) w = ForceFindDeletableWindow(); DeleteWindow(w); } + w = new Window; + /* Set up window properties */ - memset(w, 0, sizeof(*w)); w->window_class = cls; w->flags4 = WF_WHITE_BORDER_MASK; // just opened windows have a white border w->caption_color = 0xFF; @@ -1057,7 +1036,6 @@ void InitWindowSystem() { IConsoleClose(); - memset(&_windows, 0, sizeof(_windows)); _last_z_window = _z_windows; InitViewports(); _no_scroll = 0; diff --git a/src/window_gui.h b/src/window_gui.h index 330a6f6e9..665bcde22 100644 --- a/src/window_gui.h +++ b/src/window_gui.h @@ -10,6 +10,7 @@ #include "viewport_type.h" #include "player_type.h" #include "strings_type.h" +#include "core/alloc_type.hpp" /** * The maximum number of windows that can be opened. @@ -289,7 +290,7 @@ struct WindowMessage { /** * Data structure for an opened window */ -struct Window { +struct Window : ZeroedMemoryAllocator { uint16 flags4; ///< Window flags, @see WindowFlags WindowClass window_class; ///< Window class WindowNumber window_number; ///< Window number within the window class -- cgit v1.2.3-54-g00ecf