Author: rolf
Date: 2007-08-30 15:02:25 -0400 (Thu, 30 Aug 2007)
New Revision: 85065

Added:
   trunk/moon/src/debug.cpp
   trunk/moon/src/debug.h
Modified:
   trunk/moon/ChangeLog
   trunk/moon/moon.mdp
   trunk/moon/plugin/ChangeLog
   trunk/moon/plugin/downloader.cpp
   trunk/moon/plugin/plugin-class.cpp
   trunk/moon/plugin/plugin-class.h
   trunk/moon/plugin/plugin-glue.cpp
   trunk/moon/src/ChangeLog
   trunk/moon/src/Makefile.am
   trunk/moon/src/animation.cpp
   trunk/moon/src/animation.h
   trunk/moon/src/clock.cpp
   trunk/moon/src/dependencyobject.cpp
   trunk/moon/src/dependencyobject.h
   trunk/moon/src/runtime.cpp
   trunk/moon/src/type.cpp
   trunk/moon/src/type.cpp.in
   trunk/moon/src/xaml.cpp
Log:
* src/xaml.cpp: Unref the namescope.
* src/debug.h, src/debug.cpp: Added. Implemented get_stack_trace and
  print_stack_trace.
* src/clock.cpp: Unref the _instance.
* src/dependencyobject.h, src/dependencyobject.cpp: Implement object
  tracking for debug purposes. It's able to log to console object
  creation, destruction, ref/unrefs with a stacktrace with C++
  unmangled function names, file and line number. Keep a count of
  created and destroyed objects, and a list of objects still alive.
  Ref and unref attached objects, and free the attachees when we're
  deleted.
* src/animation.h, src/animation.cpp: Add animation_destroy, and
  destroy the default dependency property for a few properties.
* src/type.cpp, src/type.cpp.in: Initialize Type::types to NULL.
* src/runtime.cpp: Add a g_type_inited to avoid initializing g_types
  several types. Call animation_destroy on shutdown, and add some
  object tracking output to runtime_init and runtime_shutdown.
* src/Makefile.am, moon.mdp: Added debug.*.
* plugin/downloader.cpp: Added downloader_destroy.
* plugin/plugin-class.cpp, plugin/plugin-class.h: Add
  plugin_destroy_classes, and remove a duplicate creation of
  MoonlightPointClass.
* plugin/plugin-glue.cpp: Try shutting down everything correctly, if it
  can be shutdown, if not, don't initialize twice (vm and gtk).

Modified: trunk/moon/ChangeLog
===================================================================
--- trunk/moon/ChangeLog        2007-08-30 18:24:28 UTC (rev 85064)
+++ trunk/moon/ChangeLog        2007-08-30 19:02:25 UTC (rev 85065)
@@ -1,3 +1,7 @@
+2007-08-30  Rolf Bjarne Kvinge <[EMAIL PROTECTED]> 
+
+       * moon.mdp: Added debug.*.
+
 2007-08-29  Rolf Bjarne Kvinge <[EMAIL PROTECTED]> 
 
        * moon.mdp, moon.mds: Created a MonoDevelop project with the source 
files.

Modified: trunk/moon/moon.mdp
===================================================================
--- trunk/moon/moon.mdp 2007-08-30 18:24:28 UTC (rev 85064)
+++ trunk/moon/moon.mdp 2007-08-30 19:02:25 UTC (rev 85065)
@@ -168,6 +168,8 @@
     <File name="./TODO" subtype="Code" buildaction="Nothing" />
     <File name="./wishlist" subtype="Code" buildaction="Nothing" />
     <File name="./AUTHORS" subtype="Code" buildaction="Nothing" />
+    <File name="./src/debug.cpp" subtype="Code" buildaction="Nothing" />
+    <File name="./src/debug.h" subtype="Code" buildaction="Nothing" />
   </Contents>
   <MonoDevelop.Autotools.MakefileInfo IntegrationEnabled="True" 
RelativeMakefileName="./Makefile.am" BuildTargetName="install" 
IsAutotoolsProject="True" RelativeConfigureInPath="./">
     <BuildFilesVar />

Modified: trunk/moon/plugin/ChangeLog
===================================================================
--- trunk/moon/plugin/ChangeLog 2007-08-30 18:24:28 UTC (rev 85064)
+++ trunk/moon/plugin/ChangeLog 2007-08-30 19:02:25 UTC (rev 85065)
@@ -1,3 +1,11 @@
+2007-08-30  Rolf Bjarne Kvinge <[EMAIL PROTECTED]> 
+
+       * downloader.cpp: Added downloader_destroy.
+       * plugin-class.cpp, plugin-class.h: Add plugin_destroy_classes, and 
remove a
+         duplicate creation of MoonlightPointClass.
+       * plugin-glue.cpp: Try shutting down everything correctly, if it can be
+         shutdown, if not, don't initialize twice (vm and gtk).
+
 2007-08-29  Rolf Bjarne Kvinge <[EMAIL PROTECTED]> 
 
        * plugin-class.cpp: Javascript expects the sender of a FullScreenChange

Modified: trunk/moon/plugin/downloader.cpp
===================================================================
--- trunk/moon/plugin/downloader.cpp    2007-08-30 18:24:28 UTC (rev 85064)
+++ trunk/moon/plugin/downloader.cpp    2007-08-30 19:02:25 UTC (rev 85065)
@@ -110,3 +110,7 @@
                        p_downloader_abort);
 }
 
+void 
+downloader_destroy ()
+{
+}
\ No newline at end of file

Modified: trunk/moon/plugin/plugin-class.cpp
===================================================================
--- trunk/moon/plugin/plugin-class.cpp  2007-08-30 18:24:28 UTC (rev 85064)
+++ trunk/moon/plugin/plugin-class.cpp  2007-08-30 19:02:25 UTC (rev 85065)
@@ -3370,9 +3370,36 @@
        MoonlightStoryboardClass = new MoonlightStoryboardType ();
        MoonlightTextBlockClass = new MoonlightTextBlockType ();
        MoonlightRectClass = new MoonlightRectType ();
-       MoonlightPointClass = new MoonlightPointType ();
        MoonlightDurationClass = new MoonlightDurationType ();
        MoonlightTimeSpanClass = new MoonlightTimeSpanType ();
        MoonlightEventListenerClass = new MoonlightEventListenerType ();
 }
 
+void
+plugin_destroy_classes ()
+{
+       
+       delete MoonlightCollectionClass; MoonlightCollectionClass = NULL;
+       delete MoonlightContentClass; MoonlightContentClass = NULL;
+       delete MoonlightControlClass; MoonlightControlClass = NULL;
+       delete MoonlightEventObjectClass; MoonlightEventObjectClass = NULL;
+       delete MoonlightDependencyObjectClass; MoonlightDependencyObjectClass = 
NULL;
+       delete MoonlightDownloaderClass; MoonlightDownloaderClass = NULL;
+       delete MoonlightErrorEventArgsClass; MoonlightErrorEventArgsClass = 
NULL;
+       delete MoonlightImageBrushClass; MoonlightImageBrushClass = NULL;
+       delete MoonlightImageClass; MoonlightImageClass = NULL;
+       delete MoonlightMediaElementClass; MoonlightMediaElementClass = NULL;
+       delete MoonlightMouseEventArgsClass; MoonlightMouseEventArgsClass = 
NULL;
+       delete MoonlightKeyboardEventArgsClass; MoonlightKeyboardEventArgsClass 
= NULL;
+       delete MoonlightObjectClass; MoonlightObjectClass = NULL;
+       delete MoonlightScriptableObjectClass; MoonlightScriptableObjectClass = 
NULL;
+       delete MoonlightScriptControlClass; MoonlightScriptControlClass = NULL;
+       delete MoonlightSettingsClass; MoonlightSettingsClass = NULL;
+       delete MoonlightStoryboardClass; MoonlightStoryboardClass = NULL;
+       delete MoonlightTextBlockClass; MoonlightTextBlockClass = NULL;
+       delete MoonlightRectClass; MoonlightRectClass = NULL;
+       delete MoonlightPointClass; MoonlightPointClass = NULL;
+       delete MoonlightDurationClass; MoonlightDurationClass = NULL;
+       delete MoonlightTimeSpanClass; MoonlightTimeSpanClass = NULL;
+       delete MoonlightEventListenerClass; MoonlightEventListenerClass = NULL;
+}

Modified: trunk/moon/plugin/plugin-class.h
===================================================================
--- trunk/moon/plugin/plugin-class.h    2007-08-30 18:24:28 UTC (rev 85064)
+++ trunk/moon/plugin/plugin-class.h    2007-08-30 19:02:25 UTC (rev 85065)
@@ -19,6 +19,7 @@
 
 
 void plugin_init_classes (void);
+void plugin_destroy_classes (void);
 
 /*** EventListenerProxy */
 typedef void (*EventArgsWrapper)(NPP instance, gpointer calldata, NPVariant 
*value);

Modified: trunk/moon/plugin/plugin-glue.cpp
===================================================================
--- trunk/moon/plugin/plugin-glue.cpp   2007-08-30 18:24:28 UTC (rev 85064)
+++ trunk/moon/plugin/plugin-glue.cpp   2007-08-30 19:02:25 UTC (rev 85065)
@@ -180,23 +180,33 @@
 }
 
 void downloader_initialize ();
+void downloader_destroy ();
 
+static bool vm_initialized = false;
+static bool gtk_initialized = false;
 static bool already_initialized = false;
+static bool runtime_initialized = false;
 
 NPError
 NPP_Initialize (void)
 {
        // We dont need to initialize mono vm and gtk more than one time.
-       if (!already_initialized) {
-               already_initialized = true;
+       if (!gtk_initialized) {
+               gtk_initialized = true;
                gtk_init (0, 0);
-               downloader_initialize ();
+       }
+       if (!vm_initialized) {
+               vm_initialized = true;
                vm_init ();
+       }
+       downloader_initialize ();
+       
+       if (!runtime_initialized) {
+               runtime_initialized = true;
                runtime_init ();
-
-               plugin_init_classes ();
        }
-       TimeManager::Instance()->Start();
+       
+       plugin_init_classes ();
 
        return NPERR_NO_ERROR;
 }
@@ -204,8 +214,11 @@
 void
 NPP_Shutdown (void)
 {
+       plugin_destroy_classes ();
        // runtime_shutdown is broken at moment so let us just shutdown 
TimeManager,
        // when fixed please uncomment above line and remove time manger 
shutdown.
-       //runtime_shutdown ();
-       TimeManager::Instance()->Shutdown ();
+       runtime_shutdown ();
+       //TimeManager::Instance()->Shutdown ();
+       runtime_initialized = false;
+       downloader_destroy ();
 }

Modified: trunk/moon/src/ChangeLog
===================================================================
--- trunk/moon/src/ChangeLog    2007-08-30 18:24:28 UTC (rev 85064)
+++ trunk/moon/src/ChangeLog    2007-08-30 19:02:25 UTC (rev 85065)
@@ -1,3 +1,23 @@
+2007-08-30  Rolf Bjarne Kvinge <[EMAIL PROTECTED]> 
+
+       * xaml.cpp: Unref the namescope.
+       * debug.h, debug.cpp: Added. Implemented get_stack_trace and
+         print_stack_trace.
+       * clock.cpp: Unref the _instance.
+       * dependencyobject.h, dependencyobject.cpp: Implement object tracking 
for
+         debug purposes. It's able to log to console object creation,
+         destruction, ref/unrefs with a stacktrace with C++ unmangled function
+         names, file and line number. Keep a count of created and destroyed
+         objects, and a list of objects still alive. Ref and unref attached
+         objects, and free the attachees when we're deleted.
+       * animation.h, animation.cpp: Add animation_destroy, and destroy the 
default
+         dependency property for a few properties.
+       * type.cpp, type.cpp.in: Initialize Type::types to NULL.
+       * runtime.cpp: Add a g_type_inited to avoid initializing g_types several
+         types. Call animation_destroy on shutdown, and add some object 
tracking
+         output to runtime_init and runtime_shutdown.
+       * Makefile.am: Added debug.*.
+
 2007-08-30  Sebastien Pouliot  <[EMAIL PROTECTED]> 
 
        * shape.cpp: In some degenerate cases Radius[X|Y] can be ignored 

Modified: trunk/moon/src/Makefile.am
===================================================================
--- trunk/moon/src/Makefile.am  2007-08-30 18:24:28 UTC (rev 85064)
+++ trunk/moon/src/Makefile.am  2007-08-30 19:02:25 UTC (rev 85065)
@@ -15,6 +15,7 @@
        clock.h         \
        collection.h    \
        control.h       \
+       debug.h         \
        dependencyobject.h \
        downloader.h    \
        error.h         \
@@ -53,6 +54,7 @@
        clock.cpp       \
        collection.cpp  \
        control.cpp     \
+       debug.cpp       \
        dependencyobject.cpp    \
        dirty.h \
        dirty.cpp       \

Modified: trunk/moon/src/animation.cpp
===================================================================
--- trunk/moon/src/animation.cpp        2007-08-30 18:24:28 UTC (rev 85064)
+++ trunk/moon/src/animation.cpp        2007-08-30 19:02:25 UTC (rev 85065)
@@ -1612,6 +1612,13 @@
        PointAnimationUsingKeyFrames::KeyFramesProperty = 
DependencyObject::Register (Type::POINTANIMATIONUSINGKEYFRAMES, "KeyFrames", 
Type::POINTKEYFRAME_COLLECTION);
 }
 
+void
+animation_destroy ()
+{
+       
SplineDoubleKeyFrame::KeySplineProperty->default_value->AsDependencyObject 
()->unref ();
+       
SplineColorKeyFrame::KeySplineProperty->default_value->AsDependencyObject 
()->unref ();
+       
SplinePointKeyFrame::KeySplineProperty->default_value->AsDependencyObject 
()->unref ();
+}
 
 /* The nullable setters/getters for the various animation types */
 SET_NULLABLE_FUNC(double)

Modified: trunk/moon/src/animation.h
===================================================================
--- trunk/moon/src/animation.h  2007-08-30 18:24:28 UTC (rev 85064)
+++ trunk/moon/src/animation.h  2007-08-30 19:02:25 UTC (rev 85065)
@@ -612,6 +612,7 @@
 
 
 void animation_init (void);
+void animation_destroy (void);
 
 G_END_DECLS
 

Modified: trunk/moon/src/clock.cpp
===================================================================
--- trunk/moon/src/clock.cpp    2007-08-30 18:24:28 UTC (rev 85064)
+++ trunk/moon/src/clock.cpp    2007-08-30 19:02:25 UTC (rev 85065)
@@ -121,6 +121,9 @@
        }
        
        child_clocks = NULL;
+       
+       _instance->unref ();
+       _instance = NULL;
 }
 
 gboolean

Added: trunk/moon/src/debug.cpp
===================================================================
--- trunk/moon/src/debug.cpp    2007-08-30 18:24:28 UTC (rev 85064)
+++ trunk/moon/src/debug.cpp    2007-08-30 19:02:25 UTC (rev 85065)
@@ -0,0 +1,234 @@
+/*
+ * debug.cpp: 
+ *
+ * Copyright 2007 Novell, Inc. (http://www.novell.com)
+ *
+ * See the LICENSE file included with the distribution for details.
+ * 
+ */
+ 
+#include "debug.h"
+ 
+#if STACK_DEBUG
+
+char* get_stack_trace () 
+{
+       return get_stack_trace_prefix ("\t"); 
+}
+void print_stack_trace ()
+{
+       print_stack_trace_prefix ("\t");
+}
+
+typedef struct Addr2LineData Addr2LineData;
+
+struct Addr2LineData {
+       Addr2LineData *next;
+       FILE *pipein;
+       FILE *pipeout;
+       char *binary;
+       int child_pid;
+       gpointer base;
+};
+
+static Addr2LineData *addr2line_pipes = NULL;
+
+static char*
+library_of_ip (gpointer ip, gpointer* base_address)
+{
+       /* non-linux platforms will need different code here */
+       
+       FILE* maps = fopen ("/proc/self/maps", "r");
+       char * buffer = NULL;
+       size_t buffer_length = 0;
+       char* result = NULL;
+       char* current_library = NULL;
+       gpointer current_base_address = NULL; 
+       gpointer start, end;
+       
+       while (true) {
+               gint64 buffer_read = getline (&buffer, &buffer_length, maps);
+               
+               if (buffer_read < 0)
+                       break;
+               
+               if (buffer_read < 20)
+                       continue;
+                       
+               buffer [buffer_read - 1] = 0; // Strip off the newline.
+               
+               const char delimiters[] = " ";
+               char* range = strtok (buffer, delimiters);
+               char* dummy = strtok (NULL, delimiters);
+               dummy = strtok (NULL, delimiters);
+               dummy = strtok (NULL, delimiters);
+               dummy = strtok (NULL, delimiters);
+               char* lib = strtok (NULL, delimiters);
+               
+               if (lib == NULL) {
+                       current_library = NULL;
+                       continue;
+               }
+
+               char* start_range = strtok (range, "-");
+               char* end_range = strtok (NULL, "-");
+               
+               char* tail;
+               start = (gpointer) strtoull (start_range, &tail, 16);
+               end = (gpointer) strtoull (end_range, &tail, 16);
+               
+               if (current_library == NULL || strcmp (lib, current_library) != 
0) {
+                       current_library = lib;
+                       current_base_address = start;
+               }
+               
+               if (start <= ip && end >= ip) {
+                       result = g_strdup (lib);
+                       *base_address = current_base_address;
+                       // printf ("IP %p is in library %s\n", ip, result);
+                       break;
+               }
+       }
+       
+       free (buffer);
+       fclose (maps);
+       
+       return result;
+}
+
+
+static char*
+addr2line (gpointer ip)
+{
+       char *res;
+       Addr2LineData *addr2line;
+       gpointer base_address;
+       
+       char* binary = library_of_ip (ip, &base_address);
+       
+       if (binary == NULL)
+               return NULL;
+
+       for (addr2line = addr2line_pipes; addr2line; addr2line = 
addr2line->next) {
+               if (strcmp (binary, addr2line->binary) == 0)
+                       break;
+       }
+
+       if (!addr2line) {
+               const char *addr_argv[] = {"addr2line", "-f", "-e", binary, 
"-C", NULL};
+               int child_pid;
+               int ch_in, ch_out;
+               
+               if (!g_spawn_async_with_pipes (NULL, (char**)addr_argv, NULL, 
G_SPAWN_SEARCH_PATH, NULL, NULL,
+                               &child_pid, &ch_in, &ch_out, NULL, NULL)) {
+                       return g_strdup (binary);
+               }
+               
+               addr2line = g_new0 (Addr2LineData, 1);
+               addr2line->base = base_address;
+               addr2line->child_pid = child_pid;
+               addr2line->binary = g_strdup (binary);
+               addr2line->pipein = fdopen (ch_in, "w");
+               addr2line->pipeout = fdopen (ch_out, "r");
+               addr2line->next = addr2line_pipes;
+               addr2line_pipes = addr2line;
+       }
+               
+       gpointer offset;
+       offset = (gpointer) (((size_t) ip) - ((size_t) addr2line->base));
+       
+       // printf ("Checking ip: %p, offset: %p, base: %p\n", ip, offset, 
addr2line->base);
+       fprintf (addr2line->pipein, "%p\n", offset);
+       fflush (addr2line->pipein);
+       
+       /* we first get the func name and then file:lineno in a second line */
+       char buf [1024];
+       char* first;
+       char* second;
+       char* result;
+       int result_length;
+               
+       result = fgets (buf, sizeof (buf), addr2line->pipeout);
+       
+       if (result == NULL)
+               return g_strdup (binary);
+       
+       if (result [0] == '?' || result [0] == 0)
+               return g_strdup (binary);
+
+       result_length = strlen (result);
+       result [result_length - 1] = 0;
+       first = result;
+               
+       result = fgets (buf + result_length, sizeof (buf) - result_length, 
addr2line->pipeout);
+       
+       if (result == NULL)
+               return g_strdup (first);
+
+       result_length = strlen (result);
+       result [result_length - 1] = 0;
+       second = result;
+       
+       res = g_strdup_printf ("%s [%p] %s %s", addr2line->binary, ip, first, 
second);
+
+       // printf ("Final result: %s\n", res);
+
+       return res;
+}
+
+char* 
+get_stack_trace_prefix (const char* prefix)
+{
+       int address_count;
+       gpointer ip;
+       int total_length = 0;
+       int prefix_length = strlen (prefix);
+       void *ips [MAX_STACK_FRAMES];
+       char *frames [MAX_STACK_FRAMES];
+       char **names;
+       
+       address_count = backtrace (ips, MAX_STACK_FRAMES);
+
+       for (int i = 2; i < address_count; i++) {
+               ip = ips [i];
+
+               char* frame = addr2line (ip);
+               
+               if (frame == NULL || strlen (frame) == 0 || strcmp ("??", 
frame) == 0) {
+                       g_free (frame); 
+                       names = backtrace_symbols (&ip, 1);
+                       frame = g_strdup (names [0]);
+                       free (names);
+               }
+               frames [i] = frame;
+               total_length += prefix_length + strlen (frame) + 1;
+       }
+       
+       char* result = (char*) g_malloc0 (total_length);
+       int position = 0;
+       for (int i = 2; i < address_count; i++) {
+               char* frame = frames [i];
+               size_t frame_length = strlen (frame);
+
+               memcpy (result + position, prefix, prefix_length);
+               position += prefix_length;
+               memcpy (result + position, frame, frame_length);
+               position += frame_length;
+               memcpy (result + position, "\n", 1);
+               position ++;
+               
+               g_free (frame);
+       }
+       
+       return result;
+}
+
+void
+print_stack_trace_prefix (const char* prefix)
+{
+       char* st = get_stack_trace_prefix (prefix);
+       printf (st);
+       g_free (st);
+}
+
+#endif

Added: trunk/moon/src/debug.h
===================================================================
--- trunk/moon/src/debug.h      2007-08-30 18:24:28 UTC (rev 85064)
+++ trunk/moon/src/debug.h      2007-08-30 19:02:25 UTC (rev 85065)
@@ -0,0 +1,38 @@
+/*
+ * debug.h: 
+ *
+ * Copyright 2007 Novell, Inc. (http://www.novell.com)
+ *
+ * See the LICENSE file included with the distribution for details.
+ * 
+ */
+
+#ifndef __MONOLIGHT_DEBUG_H__
+#define __MONOLIGHT_DEBUG_H__
+
+// Define STACK_DEBUG here to enable debugging with stack frames.
+// Object tracking depends on this being defined in order to work.
+
+#define STACK_DEBUG 0
+
+#if STACK_DEBUG
+
+#include <glib.h>
+#include <unistd.h>
+#include <execinfo.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAX_STACK_FRAMES 15
+
+char* get_stack_trace_prefix (const char* prefix);
+void print_stack_trace_prefix (const char* prefix); 
+
+char* get_stack_trace ();
+void print_stack_trace ();
+
+#endif
+
+#endif
+

Modified: trunk/moon/src/dependencyobject.cpp
===================================================================
--- trunk/moon/src/dependencyobject.cpp 2007-08-30 18:24:28 UTC (rev 85064)
+++ trunk/moon/src/dependencyobject.cpp 2007-08-30 19:02:25 UTC (rev 85065)
@@ -8,7 +8,6 @@
  */
 
 #include <config.h>
-
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -19,14 +18,45 @@
 #include "collection.h"
 #include "dependencyobject.h"
 
+#if OBJECT_TRACKING
+// Define the ID of the object you want to track
+// Object creation, destruction and all ref/unrefs
+// are logged to the console, with a stacktrace.
+#define OBJECT_TRACK_ID 23
+
+int Base::objects_created = 0;
+int Base::objects_destroyed = 0;
+GList* Base::objects_alive = NULL;
+
+void
+Base::Track (const char* done, const char* typname)
+{
+#if OBJECT_TRACK_ID
+       if (id == OBJECT_TRACK_ID) {
+               printf ("%s tracked object of type '%s': %i, current refcount: 
%i\n", done, typname, id, refcount);
+               PrintStackTrace ();
+       }
+#endif
+}
+
+char* 
+Base::GetStackTrace (const char* prefix)
+{
+       return get_stack_trace_prefix (prefix);
+}
+
+void
+Base::PrintStackTrace ()
+{
+       print_stack_trace ();
+}
+
 void 
 Base::ref ()
 {
        refcount++;
-
-#if DEBUG_REFCNT
-       printf ("refcount++ %p (%s), refcnt = %d\n", this, GetTypeName (), 
refcount);
-#endif
+       
+       Track ("Ref", GetTypeName ());
 }
 
 void
@@ -34,18 +64,28 @@
 {
        refcount--;
        
-#if DEBUG_REFCNT
-               printf ("refcount-- %p (%s), refcnt = %d\n", this, GetTypeName 
(), refcount);
-#endif
+       Track ("Unref", GetTypeName ());
 
        if (refcount == 0) {
-#if DEBUG_REFCNT
-               printf ("destroying object %p (%s)\n", this, GetTypeName ());
-#endif
                delete this;
        }
 }
 
+Base::Base () : refcount(1)
+{
+       id = ++objects_created;
+       objects_alive = g_list_prepend (objects_alive, this);
+       Track ("Created", "");
+}
+
+Base::~Base () 
+{
+       objects_destroyed++;
+       objects_alive = g_list_remove (objects_alive, this);
+       Track ("Destroyed", "");
+}
+#endif
+
 void 
 base_ref (Base *base)
 {
@@ -75,6 +115,7 @@
 {
        Attachee *att = new Attachee ();
        att->dob = container;
+       att->dob->ref ();
        att->prop = property;
        attached_list = g_slist_append (attached_list, att);
 }
@@ -87,6 +128,7 @@
 
                if (att->dob == container && att->prop == property) {
                        attached_list = g_slist_remove_link (attached_list, l);
+                       att->dob->unref ();
                        delete att;
                        break;
                }
@@ -305,9 +347,18 @@
        return Type::DEPENDENCY_OBJECT; 
 }
 
+void free_attachee (gpointer data, gpointer user_data)
+{
+       delete (Attachee*) data;
+}
+
 DependencyObject::~DependencyObject ()
 {
        g_hash_table_destroy (current_values);
+       if (attached_list != NULL) {
+               g_slist_foreach (attached_list, free_attachee, NULL);
+               g_slist_free (attached_list);
+       }
 }
 
 DependencyProperty *

Modified: trunk/moon/src/dependencyobject.h
===================================================================
--- trunk/moon/src/dependencyobject.h   2007-08-30 18:24:28 UTC (rev 85064)
+++ trunk/moon/src/dependencyobject.h   2007-08-30 19:02:25 UTC (rev 85065)
@@ -12,7 +12,12 @@
 
 #include "value.h"
 #include "enums.h"
+#include "debug.h"
 
+#if STACK_DEBUG
+#define OBJECT_TRACKING 1
+#endif
+
 class EventObject;
 
 typedef void (*EventHandler) (EventObject *sender, gpointer calldata, gpointer 
closure);
@@ -29,11 +34,33 @@
 class Base {
  public:       
        guint32 refcount;
-       Base () : refcount(1) { }
-       virtual ~Base () { }
+
+#if OBJECT_TRACKING
+       static int objects_created;
+       static int objects_destroyed;
+       static GList* objects_alive;
+       int id;
+
+       char* GetStackTrace (const char* prefix);
+       char* GetStackTrace () { return GetStackTrace (""); }
+       void PrintStackTrace ();
+       void Track (const char* done, const char* typname);
        
+       Base (); 
+       virtual ~Base ();
        void ref ();
        void unref ();
+#else
+       Base () : refcount(1) {} 
+       virtual ~Base () {}
+       void ref () { refcount++; }
+       void unref ()
+       {
+               refcount--;
+               if (refcount == 0)
+                       delete this;
+       }
+#endif
        
        virtual Type::Kind GetObjectType () = 0;
        

Modified: trunk/moon/src/runtime.cpp
===================================================================
--- trunk/moon/src/runtime.cpp  2007-08-30 18:24:28 UTC (rev 85064)
+++ trunk/moon/src/runtime.cpp  2007-08-30 19:02:25 UTC (rev 85065)
@@ -923,7 +923,7 @@
 }
 
 static bool inited = false;
-
+static bool g_type_inited = false;
 void
 runtime_init (void)
 {
@@ -937,10 +937,20 @@
                printf ("*** is being run against version %s.\n", 
cairo_version_string ());
                printf ("*** Proceed at your own risk\n");
        }
+       
+#if OBJECT_TRACKING
+       printf ("Runtime created. Object tracking summary:\n");
+       printf ("\tObjects created: %i\n", Base::objects_created);
+       printf ("\tObjects destroyed: %i\n", Base::objects_destroyed);
+       printf ("\tDifference: %i\n", Base::objects_created - 
Base::objects_destroyed);
+#endif
 
        inited = true;
 
-       g_type_init ();
+       if (!g_type_inited) {
+               g_type_inited = true;
+               g_type_init ();
+       }
 
        TimeManager::Instance()->Start();
 
@@ -981,16 +991,38 @@
        g_source_remove (source_id);
 }
 
+#if OBJECT_TRACKING
+void 
+print_object_data (gpointer key, gpointer user_data)
+{
+       Base* obj = (Base*) key;
+       if (--*(int*)user_data >= 0)
+               printf ("\t\t%i = %s, refcount: %i\n", obj->id, 
obj->GetTypeName (), obj->refcount);
+}
+#endif
+
 void
 runtime_shutdown ()
 {
        if (!inited)
                return;
-
+       
+       animation_destroy ();
        TimeManager::Instance()->Shutdown ();
-       Type::Shutdown ();
        DependencyObject::Shutdown ();
 
+#if OBJECT_TRACKING
+       printf ("Runtime destroyed. Object tracking summary:\n");
+       printf ("\tObjects created: %i\n", Base::objects_created);
+       printf ("\tObjects destroyed: %i\n", Base::objects_destroyed);
+       printf ("\tDifference: %i\n", Base::objects_created - 
Base::objects_destroyed);
+       int counter = 10;
+       Base::objects_alive = g_list_reverse (Base::objects_alive);
+       g_list_foreach (Base::objects_alive, print_object_data, &counter);
+#endif
+
+       Type::Shutdown ();
        inited = false;
        
+
 }

Modified: trunk/moon/src/type.cpp
===================================================================
--- trunk/moon/src/type.cpp     2007-08-30 18:24:28 UTC (rev 85064)
+++ trunk/moon/src/type.cpp     2007-08-30 19:02:25 UTC (rev 85065)
@@ -27,7 +27,7 @@
        Type implementation
 */
 
-Type** Type::types;
+Type** Type::types = NULL;
 GHashTable* Type::types_by_name = NULL;
 
 Type::Type (const char *name, Type::Kind type, Type::Kind parent)

Modified: trunk/moon/src/type.cpp.in
===================================================================
--- trunk/moon/src/type.cpp.in  2007-08-30 18:24:28 UTC (rev 85064)
+++ trunk/moon/src/type.cpp.in  2007-08-30 19:02:25 UTC (rev 85065)
@@ -22,7 +22,7 @@
        Type implementation
 */
 
-Type** Type::types;
+Type** Type::types = NULL;
 GHashTable* Type::types_by_name = NULL;
 
 Type::Type (const char *name, Type::Kind type, Type::Kind parent)

Modified: trunk/moon/src/xaml.cpp
===================================================================
--- trunk/moon/src/xaml.cpp     2007-08-30 18:24:28 UTC (rev 85064)
+++ trunk/moon/src/xaml.cpp     2007-08-30 19:02:25 UTC (rev 85065)
@@ -147,6 +147,7 @@
                        g_string_free (char_data_buffer, TRUE);
                if (top_element)
                        delete top_element;
+               namescope->unref ();
        }
 };
 

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to