From 8257c2961fa7ec57caddb33cdcdc4ccba232914f Mon Sep 17 00:00:00 2001 From: Roland Singer Date: Mon, 28 Jan 2019 08:58:46 +0100 Subject: [PATCH] GC fixes --- app.go | 15 +---------- bytes.go | 16 ++---------- char.go | 32 ------------------------ gml.go | 4 +-- image.go | 11 ++++++-- internal/binding/headers/gml_variant.h | 2 -- internal/binding/sources/gml_variant.cpp | 30 ---------------------- variant.go | 4 --- 8 files changed, 14 insertions(+), 100 deletions(-) delete mode 100644 char.go diff --git a/app.go b/app.go index f2a8727..9b342bc 100644 --- a/app.go +++ b/app.go @@ -106,23 +106,10 @@ func newAppWithArgs(args []string) (a *app, err error) { return } - // Always free the C value. - runtime.SetFinalizer(a, freeApp) return } -func freeApp(a *app) { - if a.freed { - return - } - a.freed = true - C.gml_app_free(a.app) - freeCharArray(a.argv, a.argc) -} - -func (a *app) Free() { - freeApp(a) -} +// TODO: remove gml_app_free func (a *app) getDp() (dp float64, err error) { apiErr := errorPool.Get() diff --git a/bytes.go b/bytes.go index d320f88..b6ee6ea 100644 --- a/bytes.go +++ b/bytes.go @@ -31,13 +31,11 @@ package gml import "C" import ( "fmt" - "runtime" "unsafe" ) type bytes struct { - freed bool - ptr C.gml_bytes + ptr C.gml_bytes } func newBytes() (b *bytes) { @@ -49,21 +47,11 @@ func newBytes() (b *bytes) { if b.ptr == nil { panic(fmt.Errorf("failed to create gml bytes: C pointer is nil")) } - - runtime.SetFinalizer(b, freeBytes) // Always free the C value. return } -func freeBytes(b *bytes) { - if b.freed { - return - } - b.freed = true - C.gml_bytes_free(b.ptr) -} - func (b *bytes) Free() { - freeBytes(b) + C.gml_bytes_free(b.ptr) } func (b *bytes) Bytes() []byte { diff --git a/char.go b/char.go deleted file mode 100644 index e09d45d..0000000 --- a/char.go +++ /dev/null @@ -1,32 +0,0 @@ -/* - * GML - Go QML - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Roland Singer - * Copyright (c) 2019 Sebastian Borchers - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package gml - -// TODO: this is currently only supported for Variant. Add support to the code generation (signals, slots... args). -// A Char is an alias for a rune which is converted to a QChar when used within a Variant. -type Char rune diff --git a/gml.go b/gml.go index 9a094cd..e540fc8 100644 --- a/gml.go +++ b/gml.go @@ -63,7 +63,7 @@ func RunMain(f func()) { gapp.RunMain(f) } -// Exec load sthe root QML file located at url, +// Exec load the root QML file located at url, // executes the application and returns the exit code. // This method is blocking. // Hint: Must be called within main thread. @@ -71,7 +71,7 @@ func Exec(url string) (retCode int, err error) { return gapp.Exec(url) } -// ExecExit load sthe root QML file located at url, +// ExecExit load the root QML file located at url, // executes the app, prints errors and exits // the application with the specific exit code. func ExecExit(url string) { diff --git a/image.go b/image.go index 434ffed..8e14a69 100644 --- a/image.go +++ b/image.go @@ -38,8 +38,6 @@ import ( "unsafe" ) -// TODO: add LoadFromBuffer & LoadFromGoImage - type Image struct { freed bool img C.gml_image @@ -123,6 +121,10 @@ func (img *Image) LoadFromGoImage(gimg image.Image) error { return apiErr.Err("failed to load from data") } + // Prevent the GC from freeing. Go issue 13347 + runtime.KeepAlive(img) + runtime.KeepAlive(gimg) + return nil } @@ -156,5 +158,10 @@ func (img *Image) LoadFromData(data []byte) error { if ret != 0 { return apiErr.Err("failed to load from data") } + + // Prevent the GC from freeing. Go issue 13347 + runtime.KeepAlive(img) + runtime.KeepAlive(data) + return nil } diff --git a/internal/binding/headers/gml_variant.h b/internal/binding/headers/gml_variant.h index 3c7073a..14c9bd7 100644 --- a/internal/binding/headers/gml_variant.h +++ b/internal/binding/headers/gml_variant.h @@ -59,7 +59,6 @@ gml_variant gml_variant_new_from_uint32(u_int32_t i); gml_variant gml_variant_new_from_int64 (int64_t i); gml_variant gml_variant_new_from_uint64(u_int64_t i); -gml_variant gml_variant_new_from_rune (int32_t r); gml_variant gml_variant_new_from_string(char* s); gml_variant gml_variant_new_from_bytes (char* b, int size); @@ -82,7 +81,6 @@ u_int32_t gml_variant_to_uint32(gml_variant v); int64_t gml_variant_to_int64 (gml_variant v); u_int64_t gml_variant_to_uint64(gml_variant v); -int32_t gml_variant_to_rune (gml_variant v); void gml_variant_to_string(gml_variant v, gml_bytes b); void gml_variant_to_bytes (gml_variant v, gml_bytes b); diff --git a/internal/binding/sources/gml_variant.cpp b/internal/binding/sources/gml_variant.cpp index c229259..3406821 100644 --- a/internal/binding/sources/gml_variant.cpp +++ b/internal/binding/sources/gml_variant.cpp @@ -241,21 +241,6 @@ gml_variant gml_variant_new_from_uint64(u_int64_t i) { } } -gml_variant gml_variant_new_from_rune(int32_t r) { - try { - QVariant* v = new QVariant(QChar(r)); - return (gml_variant)v; - } - catch (std::exception& e) { - gml_error_log_exception("variant: " + string(e.what())); - return NULL; - } - catch (...) { - gml_error_log_exception("variant"); - return NULL; - } -} - gml_variant gml_variant_new_from_string(char* s) { try { QVariant* v = new QVariant(QString(s)); @@ -470,21 +455,6 @@ u_int64_t gml_variant_to_uint64(gml_variant v) { } } -int32_t gml_variant_to_rune(gml_variant v) { - try { - QVariant* qv = (QVariant*)v; - return (int32_t)(qv->toInt()); - } - catch (std::exception& e) { - gml_error_log_exception("variant: " + string(e.what())); - return 0; - } - catch (...) { - gml_error_log_exception("variant"); - return 0; - } -} - void gml_variant_to_string(gml_variant v, gml_bytes b) { try { QVariant* qv = (QVariant*)v; diff --git a/variant.go b/variant.go index 862f925..d890e89 100644 --- a/variant.go +++ b/variant.go @@ -93,8 +93,6 @@ func ToVariant(i interface{}) *Variant { case uint64: ptr = C.gml_variant_new_from_uint64(C.u_int64_t(d)) - case Char: // TODO: remove? - ptr = C.gml_variant_new_from_rune(C.int32_t(d)) case string: cstr := C.CString(d) defer C.free(unsafe.Pointer(cstr)) @@ -183,8 +181,6 @@ func (v *Variant) Decode(i interface{}) (err error) { case *uint64: *d = uint64(C.gml_variant_to_uint64(v.ptr)) - case *Char: // TODO: remove? - *d = Char(C.gml_variant_to_rune(v.ptr)) case *string: b := newBytes() defer b.Free()