changeset 60:9709643f623d

Cache function pointers so they don't get garbage collected. Added callback so they can be uncached when being removed.
author Brian Smith <brian@dbsoft.org>
date Fri, 08 Mar 2013 18:46:49 -0600
parents 9ef94c1639c3
children 1c4bbae2ab88
files src/dw/dw.go src/dw/dwglue.c
diffstat 2 files changed, 43 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/src/dw/dw.go	Fri Mar 08 16:44:58 2013 -0600
+++ b/src/dw/dw.go	Fri Mar 08 18:46:49 2013 -0600
@@ -307,6 +307,9 @@
 var VK_LCONTROL = int(C.VK_LCONTROL)
 var VK_RCONTROL = int(C.VK_RCONTROL)
 
+// Cache the function pointers so they don't get garbage collected
+var backs []unsafe.Pointer;
+
 func RESOURCE(id uintptr) unsafe.Pointer {
     return unsafe.Pointer(id);
 }
@@ -799,6 +802,7 @@
 }
 
 func Timer_connect(interval int, sigfunc SIGNAL_FUNC, data POINTER) HTIMER {
+   backs = append(backs, unsafe.Pointer(sigfunc));
    return HTIMER{C.go_timer_connect(C.int(interval), unsafe.Pointer(sigfunc), unsafe.Pointer(data), 0)};
 }
 
@@ -812,6 +816,7 @@
    csigname := C.CString(signame);
    defer C.free(unsafe.Pointer(csigname));
    
+   backs = append(backs, unsafe.Pointer(sigfunc));
    C.go_signal_connect(unsafe.Pointer(window.hwnd), csigname, unsafe.Pointer(sigfunc), unsafe.Pointer(data), 0);
 }
 
@@ -1769,6 +1774,7 @@
 
 /* Classic version... */
 func Print_new2(jobname string, flags uint, pages uint, drawfunc SIGNAL_FUNC, drawdata POINTER) HPRINT {
+   backs = append(backs, unsafe.Pointer(drawfunc));
    cjobname := C.CString(jobname);
    defer C.free(unsafe.Pointer(cjobname));
 
@@ -1792,17 +1798,13 @@
    runtime.LockOSThread();
 }
 
-/* Do we need to cache the function pointers so they don't get garbage collected?
-var backs []unsafe.Pointer;
-*/
-
 var go_flags_no_data C.int = 1;
 
 func (window HWND) ConnectDelete(sigfunc func(window HWND) int) {
    csigname := C.CString(C.DW_SIGNAL_DELETE);
    defer C.free(unsafe.Pointer(csigname));
    
-   //backs = append(backs, unsafe.Pointer(&sigfunc));
+   backs = append(backs, unsafe.Pointer(&sigfunc));
    C.go_signal_connect(unsafe.Pointer(window.hwnd), csigname, unsafe.Pointer(&sigfunc), nil, go_flags_no_data);
 }
 
@@ -1810,7 +1812,7 @@
    csigname := C.CString(C.DW_SIGNAL_CLICKED);
    defer C.free(unsafe.Pointer(csigname));
    
-   //backs = append(backs, unsafe.Pointer(&sigfunc));
+   backs = append(backs, unsafe.Pointer(&sigfunc));
    C.go_signal_connect(unsafe.Pointer(window.hwnd), csigname, unsafe.Pointer(&sigfunc), nil, go_flags_no_data);
 }
 
@@ -1818,7 +1820,7 @@
    csigname := C.CString(C.DW_SIGNAL_SET_FOCUS);
    defer C.free(unsafe.Pointer(csigname));
    
-   //backs = append(backs, unsafe.Pointer(&sigfunc));
+   backs = append(backs, unsafe.Pointer(&sigfunc));
    C.go_signal_connect(unsafe.Pointer(window.hwnd), csigname, unsafe.Pointer(&sigfunc), nil, go_flags_no_data);
 }
 
@@ -1826,7 +1828,7 @@
    csigname := C.CString(C.DW_SIGNAL_KEY_PRESS);
    defer C.free(unsafe.Pointer(csigname));
    
-   //backs = append(backs, unsafe.Pointer(&sigfunc));
+   backs = append(backs, unsafe.Pointer(&sigfunc));
    C.go_signal_connect(unsafe.Pointer(window.hwnd), csigname, unsafe.Pointer(&sigfunc), nil, go_flags_no_data);
 }
 
@@ -1834,7 +1836,7 @@
    csigname := C.CString(C.DW_SIGNAL_MOTION_NOTIFY);
    defer C.free(unsafe.Pointer(csigname));
    
-   //backs = append(backs, unsafe.Pointer(&sigfunc));
+   backs = append(backs, unsafe.Pointer(&sigfunc));
    C.go_signal_connect(unsafe.Pointer(window.hwnd), csigname, unsafe.Pointer(&sigfunc), nil, go_flags_no_data);
 }
 
@@ -1842,7 +1844,7 @@
    csigname := C.CString(C.DW_SIGNAL_BUTTON_PRESS);
    defer C.free(unsafe.Pointer(csigname));
    
-   //backs = append(backs, unsafe.Pointer(&sigfunc));
+   backs = append(backs, unsafe.Pointer(&sigfunc));
    C.go_signal_connect(unsafe.Pointer(window.hwnd), csigname, unsafe.Pointer(&sigfunc), nil, go_flags_no_data);
 }
 
@@ -1850,7 +1852,7 @@
    csigname := C.CString(C.DW_SIGNAL_BUTTON_RELEASE);
    defer C.free(unsafe.Pointer(csigname));
    
-   //backs = append(backs, unsafe.Pointer(&sigfunc));
+   backs = append(backs, unsafe.Pointer(&sigfunc));
    C.go_signal_connect(unsafe.Pointer(window.hwnd), csigname, unsafe.Pointer(&sigfunc), nil, go_flags_no_data);
 }
 
@@ -1858,7 +1860,7 @@
    csigname := C.CString(C.DW_SIGNAL_EXPOSE);
    defer C.free(unsafe.Pointer(csigname));
    
-   //backs = append(backs, unsafe.Pointer(&sigfunc));
+   backs = append(backs, unsafe.Pointer(&sigfunc));
    C.go_signal_connect(unsafe.Pointer(window.hwnd), csigname, unsafe.Pointer(&sigfunc), nil, go_flags_no_data);
 }
 
@@ -1866,7 +1868,7 @@
    csigname := C.CString(C.DW_SIGNAL_ITEM_ENTER);
    defer C.free(unsafe.Pointer(csigname));
    
-   //backs = append(backs, unsafe.Pointer(&sigfunc));
+   backs = append(backs, unsafe.Pointer(&sigfunc));
    C.go_signal_connect(unsafe.Pointer(window.hwnd), csigname, unsafe.Pointer(&sigfunc), nil, go_flags_no_data);
 }
 
@@ -1874,7 +1876,7 @@
    csigname := C.CString(C.DW_SIGNAL_ITEM_CONTEXT);
    defer C.free(unsafe.Pointer(csigname));
    
-   //backs = append(backs, unsafe.Pointer(&sigfunc));
+   backs = append(backs, unsafe.Pointer(&sigfunc));
    C.go_signal_connect(unsafe.Pointer(window.hwnd), csigname, unsafe.Pointer(&sigfunc), nil, go_flags_no_data);
 }
 
@@ -1882,7 +1884,7 @@
    csigname := C.CString(C.DW_SIGNAL_ITEM_SELECT);
    defer C.free(unsafe.Pointer(csigname));
    
-   //backs = append(backs, unsafe.Pointer(&sigfunc));
+   backs = append(backs, unsafe.Pointer(&sigfunc));
    C.go_signal_connect(unsafe.Pointer(window.hwnd), csigname, unsafe.Pointer(&sigfunc), nil, go_flags_no_data);
 }
 
@@ -1890,7 +1892,7 @@
    csigname := C.CString(C.DW_SIGNAL_LIST_SELECT);
    defer C.free(unsafe.Pointer(csigname));
    
-   //backs = append(backs, unsafe.Pointer(&sigfunc));
+   backs = append(backs, unsafe.Pointer(&sigfunc));
    C.go_signal_connect(unsafe.Pointer(window.hwnd), csigname, unsafe.Pointer(&sigfunc), nil, go_flags_no_data);
 }
 
@@ -1898,7 +1900,7 @@
    csigname := C.CString(C.DW_SIGNAL_VALUE_CHANGED);
    defer C.free(unsafe.Pointer(csigname));
    
-   //backs = append(backs, unsafe.Pointer(&sigfunc));
+   backs = append(backs, unsafe.Pointer(&sigfunc));
    C.go_signal_connect(unsafe.Pointer(window.hwnd), csigname, unsafe.Pointer(&sigfunc), nil, go_flags_no_data);
 }
 
@@ -1906,7 +1908,7 @@
    csigname := C.CString(C.DW_SIGNAL_COLUMN_CLICK);
    defer C.free(unsafe.Pointer(csigname));
    
-   //backs = append(backs, unsafe.Pointer(&sigfunc));
+   backs = append(backs, unsafe.Pointer(&sigfunc));
    C.go_signal_connect(unsafe.Pointer(window.hwnd), csigname, unsafe.Pointer(&sigfunc), nil, go_flags_no_data);
 }
 
@@ -1914,7 +1916,7 @@
    csigname := C.CString(C.DW_SIGNAL_SWITCH_PAGE);
    defer C.free(unsafe.Pointer(csigname));
    
-   //backs = append(backs, unsafe.Pointer(&sigfunc));
+   backs = append(backs, unsafe.Pointer(&sigfunc));
    C.go_signal_connect(unsafe.Pointer(window.hwnd), csigname, unsafe.Pointer(&sigfunc), nil, go_flags_no_data);
 }
 
@@ -1922,13 +1924,13 @@
    csigname := C.CString(C.DW_SIGNAL_TREE_EXPAND);
    defer C.free(unsafe.Pointer(csigname));
    
-   //backs = append(backs, unsafe.Pointer(&sigfunc));
+   backs = append(backs, unsafe.Pointer(&sigfunc));
    C.go_signal_connect(unsafe.Pointer(window.hwnd), csigname, unsafe.Pointer(&sigfunc), nil, go_flags_no_data);
 }
 
 func (id HTIMER) Connect(sigfunc func() int, interval int) {
    if id.tid == 0 {
-      //backs = append(backs, unsafe.Pointer(&sigfunc));
+      backs = append(backs, unsafe.Pointer(&sigfunc));
       id.tid = C.go_timer_connect(C.int(interval), unsafe.Pointer(&sigfunc), nil, go_flags_no_data);
    }
 }
@@ -1941,7 +1943,7 @@
 
 func (print HPRINT) Connect(drawfunc func(HPRINT, HPIXMAP, int) int, flags uint, pages int) {
    if print.hprint == nil {
-      //backs = append(backs, unsafe.Pointer(&sigfunc));
+      backs = append(backs, unsafe.Pointer(&drawfunc));
       cjobname := C.CString(print.jobname);
       defer C.free(unsafe.Pointer(cjobname));
 
@@ -1957,6 +1959,22 @@
    Print_cancel(print);
 }
 
+//export go_callback_remove
+func go_callback_remove(pfunc unsafe.Pointer) {
+   // Scan through the callback function pointer list...
+   for i, p := range backs {
+      // When we find the pointer of the function
+      // we are removing...
+      if p == pfunc {
+         // Remove it from the callback list...
+         // So it can be garbage collected if not used
+         backs = append(backs[:i], backs[i+1:]...);
+         //delete(backs, i);
+         return;
+      }
+   }   
+}
+
 //export go_int_callback_basic
 func go_int_callback_basic(pfunc unsafe.Pointer, window unsafe.Pointer, data unsafe.Pointer, flags C.int) C.int {
    if (flags & go_flags_no_data) == go_flags_no_data {
--- a/src/dw/dwglue.c	Fri Mar 08 16:44:58 2013 -0600
+++ b/src/dw/dwglue.c	Fri Mar 08 18:46:49 2013 -0600
@@ -1099,6 +1099,7 @@
 extern int go_int_callback_tree(void *pfunc, void* window, void *item, void *data, int flags);
 extern int go_int_callback_timer(void *pfunc, void *data, int flags);
 extern int go_int_callback_print(void *pfunc, void *print, void *pixmap, int page_num, void *data, int flags);
+extern void go_callback_remove(void *pfunc);
 
 static int DWSIGNAL go_callback_basic(HWND window, void *data)
 {
@@ -1262,6 +1263,8 @@
 {
    if(data)
    {
+      void **param = (void **)data;
+      go_callback_remove(param[0]);
       free(data);
    }
 }