mirror of https://github.com/buggins/dlangui.git
resource leak detection - always enable for debug builds
This commit is contained in:
parent
d34ffd75a1
commit
195a8587be
|
@ -153,3 +153,18 @@ synchronized class Log {
|
||||||
log(LogLevel.Fatal, args);
|
log(LogLevel.Fatal, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug {
|
||||||
|
private static __gshared bool _appShuttingDown = false;
|
||||||
|
|
||||||
|
@property bool appShuttingDown() { return _appShuttingDown; }
|
||||||
|
|
||||||
|
/// for debug purposes - sets shutdown flag to log widgets not destroyed in time.
|
||||||
|
void setAppShuttingDownFlag() {
|
||||||
|
_appShuttingDown = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onResourceDestroyWhileShutdown(string resourceName, string objname = null) {
|
||||||
|
Log.e("Resource leak: destroying resource while shutdown! ", resourceName, " ", objname);
|
||||||
|
}
|
||||||
|
|
|
@ -81,13 +81,13 @@ class DrawBuf : RefCountedObject {
|
||||||
version (USE_OPENGL) {
|
version (USE_OPENGL) {
|
||||||
_id = drawBufIdGenerator++;
|
_id = drawBufIdGenerator++;
|
||||||
}
|
}
|
||||||
debug(resalloc) _instanceCount++;
|
debug _instanceCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug(resalloc) private static int _instanceCount;
|
debug private static __gshared int _instanceCount;
|
||||||
debug(resalloc) @property static int instanceCount() { return _instanceCount; }
|
debug @property static int instanceCount() { return _instanceCount; }
|
||||||
~this() {
|
~this() {
|
||||||
debug(resalloc) _instanceCount--;
|
debug _instanceCount--;
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ private class FontFileItem {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FreeTypeFontFile {
|
class FreeTypeFontFile {
|
||||||
private string _filename;
|
private string _filename;
|
||||||
private string _faceName;
|
private string _faceName;
|
||||||
private FT_Library _library;
|
private FT_Library _library;
|
||||||
|
@ -112,6 +112,7 @@ private class FreeTypeFontFile {
|
||||||
@property bool italic() { return _italic; }
|
@property bool italic() { return _italic; }
|
||||||
|
|
||||||
debug private static __gshared int _instanceCount;
|
debug private static __gshared int _instanceCount;
|
||||||
|
debug @property static int instanceCount() { return _instanceCount; }
|
||||||
this(FT_Library library, string filename) {
|
this(FT_Library library, string filename) {
|
||||||
_library = library;
|
_library = library;
|
||||||
_filename = filename;
|
_filename = filename;
|
||||||
|
@ -119,12 +120,14 @@ private class FreeTypeFontFile {
|
||||||
_matrix.yy = 0x10000;
|
_matrix.yy = 0x10000;
|
||||||
_matrix.xy = 0;
|
_matrix.xy = 0;
|
||||||
_matrix.yx = 0;
|
_matrix.yx = 0;
|
||||||
debug(FontResources) Log.d("Created FreeTypeFontFile, count=", ++_instanceCount);
|
debug ++_instanceCount;
|
||||||
|
debug(FontResources) Log.d("Created FreeTypeFontFile, count=", _instanceCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
~this() {
|
~this() {
|
||||||
clear();
|
clear();
|
||||||
debug(FontResources) Log.d("Destroyed FreeTypeFontFile, count=", --_instanceCount);
|
debug --_instanceCount;
|
||||||
|
debug(FontResources) Log.d("Destroyed FreeTypeFontFile, count=", _instanceCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string familyName(FT_Face face)
|
private static string familyName(FT_Face face)
|
||||||
|
@ -329,25 +332,29 @@ private class FreeTypeFontFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Font implementation based on Win32 API system fonts.
|
* Font implementation based on FreeType.
|
||||||
*/
|
*/
|
||||||
class FreeTypeFont : Font {
|
class FreeTypeFont : Font {
|
||||||
private FontFileItem _fontItem;
|
private FontFileItem _fontItem;
|
||||||
private Collection!(FreeTypeFontFile, true) _files;
|
private Collection!(FreeTypeFontFile, true) _files;
|
||||||
|
|
||||||
debug(resalloc) static int _instanceCount;
|
debug static __gshared int _instanceCount;
|
||||||
|
debug @property static int instanceCount() { return _instanceCount; }
|
||||||
|
|
||||||
/// need to call create() after construction to initialize font
|
/// need to call create() after construction to initialize font
|
||||||
this(FontFileItem item, int size) {
|
this(FontFileItem item, int size) {
|
||||||
_fontItem = item;
|
_fontItem = item;
|
||||||
_size = size;
|
_size = size;
|
||||||
_height = size;
|
_height = size;
|
||||||
debug(resalloc) Log.d("Created font, count=", ++_instanceCount);
|
debug ++_instanceCount;
|
||||||
|
debug(resalloc) Log.d("Created font, count=", _instanceCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// do cleanup
|
/// do cleanup
|
||||||
~this() {
|
~this() {
|
||||||
clear();
|
clear();
|
||||||
debug(resalloc) Log.d("Destroyed font, count=", --_instanceCount);
|
debug --_instanceCount;
|
||||||
|
debug(resalloc) Log.d("Destroyed font, count=", _instanceCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int _size;
|
private int _size;
|
||||||
|
|
|
@ -211,12 +211,16 @@ immutable(ubyte[]) loadResourceBytes(string filename) {
|
||||||
}
|
}
|
||||||
|
|
||||||
class Drawable : RefCountedObject {
|
class Drawable : RefCountedObject {
|
||||||
//private static int _instanceCount;
|
debug static __gshared int _instanceCount;
|
||||||
|
debug @property static int instanceCount() { return _instanceCount; }
|
||||||
|
|
||||||
this() {
|
this() {
|
||||||
|
debug ++_instanceCount;
|
||||||
//Log.d("Created drawable, count=", ++_instanceCount);
|
//Log.d("Created drawable, count=", ++_instanceCount);
|
||||||
}
|
}
|
||||||
~this() {
|
~this() {
|
||||||
//Log.d("Destroyed drawable, count=", --_instanceCount);
|
//Log.d("Destroyed drawable, count=", --_instanceCount);
|
||||||
|
debug --_instanceCount;
|
||||||
}
|
}
|
||||||
abstract void drawTo(DrawBuf buf, Rect rc, uint state = 0, int tilex0 = 0, int tiley0 = 0);
|
abstract void drawTo(DrawBuf buf, Rect rc, uint state = 0, int tilex0 = 0, int tiley0 = 0);
|
||||||
@property abstract int width();
|
@property abstract int width();
|
||||||
|
@ -329,27 +333,21 @@ class ImageDrawable : Drawable {
|
||||||
protected DrawBufRef _image;
|
protected DrawBufRef _image;
|
||||||
protected bool _tiled;
|
protected bool _tiled;
|
||||||
|
|
||||||
debug(resalloc) private static int _instanceCount;
|
debug static __gshared int _instanceCount;
|
||||||
|
debug @property static int instanceCount() { return _instanceCount; }
|
||||||
|
|
||||||
this(ref DrawBufRef image, bool tiled = false, bool ninePatch = false) {
|
this(ref DrawBufRef image, bool tiled = false, bool ninePatch = false) {
|
||||||
_image = image;
|
_image = image;
|
||||||
_tiled = tiled;
|
_tiled = tiled;
|
||||||
if (ninePatch)
|
if (ninePatch)
|
||||||
_image.detectNinePatch();
|
_image.detectNinePatch();
|
||||||
debug(resalloc) {
|
debug _instanceCount++;
|
||||||
_instanceCount++;
|
debug(resalloc) Log.d("Created ImageDrawable, count=", _instanceCount);
|
||||||
Log.d("Created ImageDrawable, count=", _instanceCount);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
debug(resalloc) {
|
|
||||||
@property static int instanceCount() { return _instanceCount; }
|
|
||||||
}
|
|
||||||
~this() {
|
~this() {
|
||||||
_image.clear();
|
_image.clear();
|
||||||
debug(resalloc) {
|
debug _instanceCount--;
|
||||||
_instanceCount--;
|
debug(resalloc) Log.d("Destroyed ImageDrawable, count=", _instanceCount);
|
||||||
Log.d("Destroyed ImageDrawable, count=", _instanceCount);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@property override int width() {
|
@property override int width() {
|
||||||
if (_image.isNull)
|
if (_image.isNull)
|
||||||
|
@ -857,20 +855,23 @@ class DrawableCache {
|
||||||
DrawableRef _drawable;
|
DrawableRef _drawable;
|
||||||
DrawableRef[ColorTransform] _transformed;
|
DrawableRef[ColorTransform] _transformed;
|
||||||
|
|
||||||
debug(resalloc) private static int _instanceCount;
|
debug private static __gshared int _instanceCount;
|
||||||
|
debug @property static int instanceCount() { return _instanceCount; }
|
||||||
this(string id, string filename, bool tiled) {
|
this(string id, string filename, bool tiled) {
|
||||||
_id = id;
|
_id = id;
|
||||||
_filename = filename;
|
_filename = filename;
|
||||||
_tiled = tiled;
|
_tiled = tiled;
|
||||||
_error = filename is null;
|
_error = filename is null;
|
||||||
debug(resalloc) Log.d("Created DrawableCacheItem, count=", ++_instanceCount);
|
debug ++_instanceCount;
|
||||||
|
debug(resalloc) Log.d("Created DrawableCacheItem, count=", _instanceCount);
|
||||||
}
|
}
|
||||||
~this() {
|
~this() {
|
||||||
_drawable.clear();
|
_drawable.clear();
|
||||||
foreach(ref t; _transformed)
|
foreach(ref t; _transformed)
|
||||||
t.clear();
|
t.clear();
|
||||||
_transformed.destroy();
|
_transformed.destroy();
|
||||||
debug(resalloc) Log.d("Destroyed DrawableCacheItem, count=", --_instanceCount);
|
debug --_instanceCount;
|
||||||
|
debug(resalloc) Log.d("Destroyed DrawableCacheItem, count=", _instanceCount);
|
||||||
}
|
}
|
||||||
/// remove from memory, will cause reload on next access
|
/// remove from memory, will cause reload on next access
|
||||||
void compact() {
|
void compact() {
|
||||||
|
|
|
@ -873,6 +873,7 @@ class SDLPlatform : Platform {
|
||||||
Log.i("entering message loop");
|
Log.i("entering message loop");
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
bool quit = false;
|
bool quit = false;
|
||||||
|
bool skipNextQuit = false;
|
||||||
while(!quit) {
|
while(!quit) {
|
||||||
//redrawWindows();
|
//redrawWindows();
|
||||||
|
|
||||||
|
@ -882,9 +883,12 @@ class SDLPlatform : Platform {
|
||||||
//Log.d("Event.type = ", event.type);
|
//Log.d("Event.type = ", event.type);
|
||||||
|
|
||||||
if (event.type == SDL_QUIT) {
|
if (event.type == SDL_QUIT) {
|
||||||
Log.i("event.type == SDL_QUIT");
|
if (!skipNextQuit) {
|
||||||
quit = true;
|
Log.i("event.type == SDL_QUIT");
|
||||||
break;
|
quit = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
skipNextQuit = false;
|
||||||
}
|
}
|
||||||
if (_redrawEventId && event.type == _redrawEventId) {
|
if (_redrawEventId && event.type == _redrawEventId) {
|
||||||
// user defined redraw event
|
// user defined redraw event
|
||||||
|
@ -920,9 +924,13 @@ class SDLPlatform : Platform {
|
||||||
w.redraw();
|
w.redraw();
|
||||||
break;
|
break;
|
||||||
case SDL_WINDOWEVENT_CLOSE:
|
case SDL_WINDOWEVENT_CLOSE:
|
||||||
debug(DebugSDL) Log.d("SDL_WINDOWEVENT_CLOSE win=", event.window.windowID);
|
if (w.handleCanClose()) {
|
||||||
_windowMap.remove(windowID);
|
debug(DebugSDL) Log.d("SDL_WINDOWEVENT_CLOSE win=", event.window.windowID);
|
||||||
destroy(w);
|
_windowMap.remove(windowID);
|
||||||
|
destroy(w);
|
||||||
|
} else {
|
||||||
|
skipNextQuit = true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SDL_WINDOWEVENT_SHOWN:
|
case SDL_WINDOWEVENT_SHOWN:
|
||||||
debug(DebugSDL) Log.d("SDL_WINDOWEVENT_SHOWN");
|
debug(DebugSDL) Log.d("SDL_WINDOWEVENT_SHOWN");
|
||||||
|
@ -1344,15 +1352,13 @@ int sdlmain(string[] args) {
|
||||||
Platform.setInstance(null);
|
Platform.setInstance(null);
|
||||||
|
|
||||||
//
|
//
|
||||||
debug(resalloc) {
|
debug setAppShuttingDownFlag();
|
||||||
Widget.shuttingDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
currentTheme = null;
|
currentTheme = null;
|
||||||
drawableCache = null;
|
drawableCache = null;
|
||||||
imageCache = null;
|
imageCache = null;
|
||||||
FontManager.instance = null;
|
FontManager.instance = null;
|
||||||
debug(resalloc) {
|
debug {
|
||||||
if (DrawBuf.instanceCount > 0) {
|
if (DrawBuf.instanceCount > 0) {
|
||||||
Log.e("Non-zero DrawBuf instance count when exiting: ", DrawBuf.instanceCount);
|
Log.e("Non-zero DrawBuf instance count when exiting: ", DrawBuf.instanceCount);
|
||||||
}
|
}
|
||||||
|
@ -1365,6 +1371,14 @@ int sdlmain(string[] args) {
|
||||||
if (ImageDrawable.instanceCount > 0) {
|
if (ImageDrawable.instanceCount > 0) {
|
||||||
Log.e("Non-zero ImageDrawable instance count when exiting: ", ImageDrawable.instanceCount);
|
Log.e("Non-zero ImageDrawable instance count when exiting: ", ImageDrawable.instanceCount);
|
||||||
}
|
}
|
||||||
|
version (USE_FREETYPE) {
|
||||||
|
if (FreeTypeFontFile.instanceCount > 0) {
|
||||||
|
Log.e("Non-zero FreeTypeFontFile instance count when exiting: ", FreeTypeFontFile.instanceCount);
|
||||||
|
}
|
||||||
|
if (FreeTypeFont.instanceCount > 0) {
|
||||||
|
Log.e("Non-zero FreeTypeFont instance count when exiting: ", FreeTypeFont.instanceCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Log.d("Exiting main");
|
Log.d("Exiting main");
|
||||||
|
|
||||||
|
|
|
@ -150,6 +150,9 @@ class ComboBoxBase : HorizontalLayout, OnClickHandler {
|
||||||
addChild(_body);
|
addChild(_body);
|
||||||
addChild(_button);
|
addChild(_button);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~this() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -234,6 +237,13 @@ class ComboBox : ComboBoxBase {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~this() {
|
||||||
|
if (_adapter) {
|
||||||
|
destroy(_adapter);
|
||||||
|
_adapter = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Editable ComboBox with list of strings. */
|
/** Editable ComboBox with list of strings. */
|
||||||
|
|
|
@ -699,14 +699,14 @@ class Style {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug(resalloc) private static int _instanceCount;
|
debug private static __gshared int _instanceCount;
|
||||||
debug(resalloc) @property static int instanceCount() { return _instanceCount; }
|
debug @property static int instanceCount() { return _instanceCount; }
|
||||||
|
|
||||||
this(Theme theme, string id) {
|
this(Theme theme, string id) {
|
||||||
_theme = theme;
|
_theme = theme;
|
||||||
_parentStyle = theme;
|
_parentStyle = theme;
|
||||||
_id = id;
|
_id = id;
|
||||||
debug(resalloc) _instanceCount++;
|
debug _instanceCount++;
|
||||||
//Log.d("Created style ", _id, ", count=", ++_instanceCount);
|
//Log.d("Created style ", _id, ", count=", ++_instanceCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -725,7 +725,7 @@ class Style {
|
||||||
_children.destroy();
|
_children.destroy();
|
||||||
_backgroundDrawable.clear();
|
_backgroundDrawable.clear();
|
||||||
_font.clear();
|
_font.clear();
|
||||||
debug(resalloc) _instanceCount--;
|
debug _instanceCount--;
|
||||||
//Log.d("Destroyed style ", _id, ", parentId=", _parentId, ", state=", _stateMask, ", count=", --_instanceCount);
|
//Log.d("Destroyed style ", _id, ", parentId=", _parentId, ", state=", _stateMask, ", count=", --_instanceCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -174,9 +174,8 @@ class Widget {
|
||||||
return CursorType.Arrow;
|
return CursorType.Arrow;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug(resalloc) {
|
debug {
|
||||||
private static int _instanceCount = 0;
|
private static __gshared int _instanceCount = 0;
|
||||||
private static bool _appShuttingDown = false;
|
|
||||||
}
|
}
|
||||||
/// empty parameter list constructor - for usage by factory
|
/// empty parameter list constructor - for usage by factory
|
||||||
this() {
|
this() {
|
||||||
|
@ -186,15 +185,15 @@ class Widget {
|
||||||
this(string ID) {
|
this(string ID) {
|
||||||
_id = ID;
|
_id = ID;
|
||||||
_state = State.Enabled;
|
_state = State.Enabled;
|
||||||
debug(resalloc) _instanceCount++;
|
debug _instanceCount++;
|
||||||
//Log.d("Created widget, count = ", ++_instanceCount);
|
//Log.d("Created widget, count = ", ++_instanceCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
~this() {
|
~this() {
|
||||||
debug(resalloc) {
|
debug {
|
||||||
//Log.v("destroying widget ", _id);
|
//Log.v("destroying widget ", _id, " ", this.classinfo.name);
|
||||||
if (_appShuttingDown)
|
if (appShuttingDown)
|
||||||
Log.e("Destroying widget ", _id, " after app shutdown: probably, resource leak");
|
onResourceDestroyWhileShutdown(_id, this.classinfo.name);
|
||||||
_instanceCount--;
|
_instanceCount--;
|
||||||
}
|
}
|
||||||
if (_ownStyle !is null)
|
if (_ownStyle !is null)
|
||||||
|
@ -203,13 +202,9 @@ class Widget {
|
||||||
//Log.d("Destroyed widget, count = ", --_instanceCount);
|
//Log.d("Destroyed widget, count = ", --_instanceCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug(resalloc) {
|
debug {
|
||||||
/// for debug purposes - number of created widget objects, not yet destroyed
|
/// for debug purposes - number of created widget objects, not yet destroyed
|
||||||
static @property int instanceCount() { return _instanceCount; }
|
static @property int instanceCount() { return _instanceCount; }
|
||||||
/// for debug purposes - sets shutdown flag to log widgets not destroyed in time.
|
|
||||||
static void shuttingDown() {
|
|
||||||
_appShuttingDown = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// accessor to style - by lookup in theme by styleId (if style id is not set, theme base style will be used).
|
/// accessor to style - by lookup in theme by styleId (if style id is not set, theme base style will be used).
|
||||||
|
|
Loading…
Reference in New Issue