* generator/OpaqueGen.cs (Generate): Tweak the generated Ref/Unref

a bit; only Ref the pointer if Owned is false (and then set it to
	true), and vice versa for Unref.

	* glib/Opaque.cs (Opaque): set owned before setting Raw, so
	that Raw will be reffed properly.
	(GetOpaque): Fix this up to dtrt in all cases with refcounted
	opaques.
	
	* gtk/TreeView.custom (GetPathAtPos): Use "GetOpaque(...)" rather
	than "new TreePath()"

	* sample/opaquetest/*: regression test for opaque free/ref/unref
	handling

	* sample/Makefile.am (SUBDIRS): add opaquetest

	* configure.in.in (AC_OUTPUT): add opaquetest files

svn path=/trunk/gtk-sharp/; revision=48168
This commit is contained in:
Dan Winship 2005-08-09 14:44:32 +00:00
parent c254638a5a
commit 12cd8d0d17
15 changed files with 794 additions and 14 deletions

View file

@ -1,3 +1,24 @@
2005-08-09 Dan Winship <danw@novell.com>
* generator/OpaqueGen.cs (Generate): Tweak the generated Ref/Unref
a bit; only Ref the pointer if Owned is false (and then set it to
true), and vice versa for Unref.
* glib/Opaque.cs (Opaque): set owned before setting Raw, so
that Raw will be reffed properly.
(GetOpaque): Fix this up to dtrt in all cases with refcounted
opaques.
* gtk/TreeView.custom (GetPathAtPos): Use "GetOpaque(...)" rather
than "new TreePath()"
* sample/opaquetest/*: regression test for opaque free/ref/unref
handling
* sample/Makefile.am (SUBDIRS): add opaquetest
* configure.in.in (AC_OUTPUT): add opaquetest files
2005-08-04 Dan Winship <danw@novell.com>
Change the way generatable validation works. Some generatable

View file

@ -313,6 +313,8 @@ sample/rsvg/Makefile
sample/test/Makefile
sample/valtest/Makefile
sample/valtest/valtest.exe.config
sample/opaquetest/Makefile
sample/opaquetest/opaquetest.exe.config
sample/cairo-sample.exe.config
])

View file

@ -177,7 +177,7 @@
<Docs>
<summary>Whether or not this <see cref="T:GLib.Opaque" /> wrapper owns the raw object.</summary>
<value>
<see langword="true" /> if the wrapper owns the raw object.</value>
<see langword="true" /> if the wrapper owns the raw object and will <see cref="M:GLib.Opaque.Unref"/> / <see cref="M:GLib.Opaque.Free"/> it when the wrapper is disposed.</value>
<remarks>By default, this is set to <see langword="true" /> for opaque objects created with the no-argument constructor, and <see langword="false" /> for opaque objects created with the <see cref="T:System.IntPtr" /> constructor. Methods that return an opaque object can override this by setting the <see cref="M:GLib.Opaque.Owned" /> property accordingly to obey the memory-management conventions of the underlying C code.</remarks>
</Docs>
</Member>

View file

@ -78,7 +78,10 @@ namespace GtkSharp.Generation {
ref_.GenerateImport (sw);
sw.WriteLine ("\t\tprotected override void Ref (IntPtr raw)");
sw.WriteLine ("\t\t{");
sw.WriteLine ("\t\t\t" + ref_.CName + " (raw);");
sw.WriteLine ("\t\t\tif (!Owned) {");
sw.WriteLine ("\t\t\t\t" + ref_.CName + " (raw);");
sw.WriteLine ("\t\t\t\tOwned = true;");
sw.WriteLine ("\t\t\t}");
sw.WriteLine ("\t\t}");
sw.WriteLine ();
@ -95,7 +98,10 @@ namespace GtkSharp.Generation {
unref.GenerateImport (sw);
sw.WriteLine ("\t\tprotected override void Unref (IntPtr raw)");
sw.WriteLine ("\t\t{");
sw.WriteLine ("\t\t\t" + unref.CName + " (raw);");
sw.WriteLine ("\t\t\tif (Owned) {");
sw.WriteLine ("\t\t\t\t" + unref.CName + " (raw);");
sw.WriteLine ("\t\t\t\tOwned = false;");
sw.WriteLine ("\t\t\t}");
sw.WriteLine ("\t\t}");
sw.WriteLine ();

View file

@ -65,7 +65,13 @@ namespace GLib {
}
opaque = (Opaque)Activator.CreateInstance (type, new object[] { o });
opaque.owned = owned;
if (owned) {
if (opaque.owned) {
// The constructor took a Ref it shouldn't have, so undo it
opaque.Unref (o);
} else
opaque.owned = true;
}
return opaque;
}
@ -76,8 +82,8 @@ namespace GLib {
public Opaque (IntPtr raw)
{
Raw = raw;
owned = false;
Raw = raw;
}
protected IntPtr Raw {

View file

@ -81,8 +81,7 @@
bool raw_ret = gtk_tree_view_get_path_at_pos (Handle, x, y, out pathHandle, out columnHandle, out cell_x, out cell_y);
if (raw_ret) {
column = (Gtk.TreeViewColumn) GLib.Object.GetObject (columnHandle, false);
path = new TreePath (pathHandle);
path.Owned = true;
path = (Gtk.TreePath) GLib.Opaque.GetOpaque (pathHandle, typeof (Gtk.TreePath), true);
} else {
path = null;
column = null;
@ -97,10 +96,9 @@
IntPtr pathHandle;
IntPtr columnHandle;
bool raw_ret = gtk_tree_view_get_path_at_pos_intptr (Handle, x, y, out pathHandle, out columnHandle, IntPtr.Zero, IntPtr.Zero);
if (raw_ret) {
path = new TreePath (pathHandle);
path.Owned = true;
} else
if (raw_ret)
path = (Gtk.TreePath) GLib.Opaque.GetOpaque (pathHandle, typeof (Gtk.TreePath), true);
else
path = null;
return raw_ret;
@ -112,8 +110,7 @@
IntPtr columnHandle;
bool raw_ret = gtk_tree_view_get_path_at_pos_intptr (Handle, x, y, out pathHandle, out columnHandle, IntPtr.Zero, IntPtr.Zero);
if (raw_ret) {
path = new TreePath (pathHandle);
path.Owned = true;
path = (Gtk.TreePath) GLib.Opaque.GetOpaque (pathHandle, typeof (Gtk.TreePath), true);
column = (Gtk.TreeViewColumn) GLib.Object.GetObject (columnHandle, false);
} else {
path = null;

View file

@ -1,4 +1,4 @@
SUBDIRS = gconf rsvg test GtkDemo pixmaps gnomevfs valtest
SUBDIRS = gconf rsvg test GtkDemo pixmaps gnomevfs valtest opaquetest
if ENABLE_GNOME
GNOME_TARGETS=gnome-hello-world.exe canvas-example.exe fifteen.exe print.exe

View file

@ -0,0 +1,30 @@
noinst_SCRIPTS = opaquetest.exe
lib_LTLIBRARIES = libopaque.la
assemblies=../../glib/glib-sharp.dll ../../pango/pango-sharp.dll ../../atk/atk-sharp.dll ../../gdk/gdk-sharp.dll ../../gtk/gtk-sharp.dll
references=$(addprefix /r:, $(assemblies))
opaquetest.exe: OpaqueTest.cs generated/*.cs $(assemblies)
$(CSC) /out:opaquetest.exe $(references) $(srcdir)/OpaqueTest.cs generated/*.cs
libopaque_la_SOURCES = \
opaques.c \
opaques.h
libopaque_la_LDFLAGS = -module -avoid-version -no-undefined
libopaque_la_LIBADD = $(GTK_LIBS)
INCLUDES = $(GTK_CFLAGS)
generated/*.cs: opaque-api.xml
$(RUNTIME) ../../generator/gapi_codegen.exe --generate opaque-api.xml --include ../../gtk/gtk-api.xml ../../gdk/gdk-api.xml --outdir=generated --assembly-name=opaque-sharp
api:
PATH=../../parser:$PATH $(RUNTIME) ../../parser/gapi-parser.exe opaque-sources.xml
$(RUNTIME) ../../parser/gapi-fixup.exe --metadata=Opaque.metadata --api=opaque-api.xml
install:
CLEANFILES = \
generated/*.cs

View file

@ -0,0 +1,5 @@
<?xml version="1.0"?>
<metadata>
<attr path="/api/namespace/struct[@name='Opaque']" name="opaque">1</attr>
<attr path="/api/namespace/struct[@name='Refcounted']" name="opaque">1</attr>
</metadata>

View file

@ -0,0 +1,282 @@
// Opaquetest.cs: GLib.Opaque regression test
//
// Copyright (c) 2005 Novell, Inc.
using Gtksharp;
using System;
public class OpaqueTest {
static int errors = 0;
static void GC ()
{
System.GC.Collect ();
System.GC.WaitForPendingFinalizers ();
System.GC.Collect ();
System.GC.WaitForPendingFinalizers ();
}
public static int Main ()
{
Gtk.Application.Init ();
TestOpaque ();
Console.WriteLine ();
TestRefcounted ();
Console.WriteLine ();
Console.WriteLine ("{0} errors", errors);
return errors;
}
static Opaque ret_op;
static Opaque ReturnOpaque ()
{
return ret_op;
}
static void TestOpaque ()
{
Opaque op, op1;
IntPtr handle;
Console.WriteLine ("Testing Opaque new/free");
op = new Opaque ();
if (!op.Owned)
Error ("Newly-created Opaque is not Owned");
handle = op.Handle;
op.Dispose ();
op = new Opaque (handle);
if (op.Owned)
Error ("IntPtr-created Opaque is Owned");
if (Opaquetest.Error)
Error ("Memory error after initial new/free.");
Opaquetest.ExpectError = true;
if (op.Serial != Opaque.LastSerial)
Error ("Serial mismatch. Expected {0}, Got {1}", Opaque.LastSerial, op.Serial);
if (!Opaquetest.Error)
Error ("Opaque not properly freed.");
op.Dispose ();
if (Opaquetest.Error)
Error ("Opaque created from IntPtr was freed by gtk#");
Console.WriteLine ("Testing Opaque copy/free");
op = new Opaque ();
op1 = op.Copy ();
handle = op1.Handle;
op.Dispose ();
op1.Dispose ();
if (Opaquetest.Error)
Error ("Memory error after initial copy/free.");
op = new Opaque (handle);
Opaquetest.ExpectError = true;
if (op.Serial != Opaque.LastSerial)
Error ("Serial mismatch. Expected {0}, Got {1}", Opaque.LastSerial, op.Serial);
if (!Opaquetest.Error)
Error ("Opaque not properly freed.");
op.Dispose ();
if (Opaquetest.Error)
Error ("Opaque created from IntPtr was freed by gtk#");
Console.WriteLine ("Testing non-owned return.");
op = new Opaque ();
op1 = new Opaque ();
op.Friend = op1;
if (Opaquetest.Error)
Error ("Memory error after setting op.Friend.");
op1 = op.Friend;
if (op1.Serial != Opaque.LastSerial || Opaquetest.Error)
Error ("Error reading op.Friend. Expected {0}, Got {1}", Opaque.LastSerial, op1.Serial);
if (!op1.Owned)
Error ("op1 not Owned after being read off op.Friend");
op.Dispose ();
op1.Dispose ();
if (Opaquetest.Error)
Error ("Memory error after freeing op and op1.");
Console.WriteLine ("Testing returning a Gtk#-owned opaque from C# to C");
ret_op = new Opaque ();
op = Opaque.Check (ReturnOpaque, GC);
if (op.Serial != Opaque.LastSerial || Opaquetest.Error)
Error ("Error during Opaque.Check. Expected {0}, Got {1}", Opaque.LastSerial, op.Serial);
op.Dispose ();
if (Opaquetest.Error)
Error ("Memory error after clearing op.");
Console.WriteLine ("Testing returning a Gtk#-owned opaque to a C method that will free it");
ret_op = new Opaque ();
op = Opaque.CheckFree (ReturnOpaque, GC);
if (Opaquetest.Error)
Error ("Error during Opaque.CheckFree.");
Opaquetest.ExpectError = true;
if (op.Serial != Opaque.LastSerial)
Error ("Error during Opaque.CheckFree. Expected {0}, Got {1}", Opaque.LastSerial, op.Serial);
if (!Opaquetest.Error)
Error ("Didn't get expected error accessing op.Serial!");
Opaquetest.ExpectError = true;
op.Dispose ();
if (!Opaquetest.Error)
Error ("Didn't get expected double free on op after CheckFree!");
Console.WriteLine ("Testing leaking a C-owned opaque");
ret_op = new Opaque ();
ret_op.Owned = false;
op = Opaque.Check (ReturnOpaque, GC);
if (op.Serial != Opaque.LastSerial || Opaquetest.Error)
Error ("Error during Opaque.Check. Expected {0}, Got {1}", Opaque.LastSerial, op.Serial);
handle = op.Handle;
op.Dispose ();
if (Opaquetest.Error)
Error ("Memory error after disposing op.");
op = new Opaque (handle);
if (op.Serial != Opaque.LastSerial || Opaquetest.Error)
Error ("Failed to leak op. Expected {0}, Got {1}", Opaque.LastSerial, op.Serial);
Console.WriteLine ("Testing handing over a C-owned opaque to a C method that will free it");
ret_op = new Opaque ();
ret_op.Owned = false;
op = Opaque.CheckFree (ReturnOpaque, GC);
if (Opaquetest.Error)
Error ("Error during Opaque.CheckFree.");
Opaquetest.ExpectError = true;
if (op.Serial != Opaque.LastSerial)
Error ("Error during Opaque.CheckFree. Expected {0}, Got {1}", Opaque.LastSerial, op.Serial);
if (!Opaquetest.Error)
Error ("Didn't get expected error accessing op.Serial!");
op.Dispose ();
if (Opaquetest.Error)
Error ("Double free on op!");
}
static Refcounted ret_ref;
static Refcounted ReturnRefcounted ()
{
return ret_ref;
}
static void TestRefcounted ()
{
Refcounted ref1, ref2;
IntPtr handle;
Console.WriteLine ("Testing Refcounted new/free");
ref1 = new Refcounted ();
if (!ref1.Owned)
Error ("Newly-created Refcounted is not Owned");
handle = ref1.Handle;
ref1.Dispose ();
Opaquetest.ExpectError = true;
ref1 = new Refcounted (handle);
if (!Opaquetest.Error)
Error ("Didn't get expected ref error resurrecting ref1.");
if (!ref1.Owned)
Error ("IntPtr-created Refcounted is not Owned");
Opaquetest.ExpectError = true;
if (ref1.Serial != Refcounted.LastSerial)
Error ("Serial mismatch. Expected {0}, Got {1}", Refcounted.LastSerial, ref1.Serial);
// We caused it to take a ref on the "freed" underlying object, so
// undo that now so it doesn't cause an error later when we're not
// expecting it.
Opaquetest.ExpectError = true;
ref1.Dispose ();
Opaquetest.Error = false;
Console.WriteLine ("Testing Refcounted leak/non-free");
ref1 = new Refcounted ();
ref1.Owned = false;
handle = ref1.Handle;
ref1.Dispose ();
ref1 = new Refcounted (handle);
if (Opaquetest.Error)
Error ("Non-owned ref was freed by gtk#");
if (ref1.Serial != Refcounted.LastSerial)
Error ("Serial mismatch. Expected {0}, Got {1}", Refcounted.LastSerial, ref1.Serial);
if (Opaquetest.Error)
Error ("Non-owned ref was freed by gtk#");
Console.WriteLine ("Testing non-owned return.");
ref1 = new Refcounted ();
ref2 = new Refcounted ();
ref1.Friend = ref2;
if (Opaquetest.Error)
Error ("Memory error after setting ref1.Friend.");
if (ref2.Refcount != 2)
Error ("Refcount wrong for ref2 after setting ref1.Friend. Expected 2, Got {0}", ref2.Refcount);
ref2.Dispose ();
ref2 = ref1.Friend;
if (ref2.Serial != Refcounted.LastSerial || Opaquetest.Error)
Error ("Error reading ref1.Friend. Expected {0}, Got {1}", Refcounted.LastSerial, ref2.Serial);
if (ref2.Refcount != 2 || Opaquetest.Error)
Error ("Refcount wrong for ref2 after reading ref1.Friend. Expected 2, Got {0}", ref2.Refcount);
if (!ref2.Owned)
Error ("ref2 not Owned after being read off ref1.Friend");
ref1.Dispose ();
ref2.Dispose ();
if (Opaquetest.Error)
Error ("Memory error after freeing ref1 and ref2.");
Console.WriteLine ("Testing returning a Gtk#-owned refcounted from C# to C");
ret_ref = new Refcounted ();
ref1 = Refcounted.Check (ReturnRefcounted, GC);
if (ref1.Serial != Refcounted.LastSerial || Opaquetest.Error)
Error ("Error during Refcounted.Check. Expected {0}, Got {1}", Refcounted.LastSerial, ref1.Serial);
ref1.Dispose ();
if (Opaquetest.Error)
Error ("Memory error after clearing ref1.");
Console.WriteLine ("Testing returning a Gtk#-owned refcounted to a C method that will free it");
ret_ref = new Refcounted ();
ref1 = Refcounted.CheckUnref (ReturnRefcounted, GC);
if (Opaquetest.Error)
Error ("Error during Refcounted.CheckUnref.");
Opaquetest.ExpectError = true;
if (ref1.Serial != Refcounted.LastSerial)
Error ("Error during Refcounted.CheckUnref. Expected {0}, Got {1}", Refcounted.LastSerial, ref1.Serial);
if (!Opaquetest.Error)
Error ("Didn't get expected error accessing ref1.Serial!");
Opaquetest.ExpectError = true;
ref1.Dispose ();
if (!Opaquetest.Error)
Error ("Didn't get expected double free on ref1 after CheckUnref!");
Console.WriteLine ("Testing leaking a C-owned refcounted");
ret_ref = new Refcounted ();
ret_ref.Owned = false;
ref1 = Refcounted.Check (ReturnRefcounted, GC);
if (ref1.Serial != Refcounted.LastSerial || Opaquetest.Error)
Error ("Error during Refcounted.Check. Expected {0}, Got {1}", Refcounted.LastSerial, ref1.Serial);
handle = ref1.Handle;
ref1.Dispose ();
if (Opaquetest.Error)
Error ("Memory error after disposing ref1.");
ref1 = new Refcounted (handle);
if (ref1.Serial != Refcounted.LastSerial || Opaquetest.Error)
Error ("Failed to leak ref1. Expected {0}, Got {1}", Refcounted.LastSerial, ref1.Serial);
Console.WriteLine ("Testing handing over a C-owned refcounted to a C method that will free it");
ret_ref = new Refcounted ();
ret_ref.Owned = false;
ref1 = Refcounted.CheckUnref (ReturnRefcounted, GC);
if (Opaquetest.Error)
Error ("Error during Refcounted.CheckUnref.");
Opaquetest.ExpectError = true;
if (ref1.Serial != Refcounted.LastSerial)
Error ("Error during Refcounted.CheckUnref. Expected {0}, Got {1}", Refcounted.LastSerial, ref1.Serial);
if (!Opaquetest.Error)
Error ("Didn't get expected error accessing ref1.Serial!");
ref1.Dispose ();
if (Opaquetest.Error)
Error ("Double free on ref1!");
}
static void Error (string message, params object[] args)
{
Console.Error.WriteLine (" MANAGED ERROR: " + message, args);
errors++;
}
}

View file

@ -0,0 +1,123 @@
<?xml version="1.0"?>
<api>
<!--
This file was automatically generated.
Please DO NOT MODIFY THIS FILE, modify .metadata files instead.
-->
<namespace name="Gtksharp" library="libopaque.dll">
<callback name="GCFunc" cname="GtksharpGCFunc">
<return-type type="void" />
</callback>
<callback name="OpaqueReturnFunc" cname="GtksharpOpaqueReturnFunc">
<return-type type="GtksharpOpaque*" />
</callback>
<callback name="RefcountedReturnFunc" cname="GtksharpRefcountedReturnFunc">
<return-type type="GtksharpRefcounted*" />
</callback>
<struct name="Opaque" cname="GtksharpOpaque" opaque="1">
<field name="Serial" cname="serial" type="int" />
<field name="Valid" cname="valid" type="gboolean" />
<field name="Friend" cname="friend" type="GtksharpOpaque*" />
<method name="Check" cname="gtksharp_opaque_check" shared="true">
<return-type type="GtksharpOpaque*" />
<parameters>
<parameter type="GtksharpOpaqueReturnFunc" name="func" />
<parameter type="GtksharpGCFunc" name="gc" />
</parameters>
</method>
<method name="CheckFree" cname="gtksharp_opaque_check_free" shared="true">
<return-type type="GtksharpOpaque*" />
<parameters>
<parameter type="GtksharpOpaqueReturnFunc" name="func" />
<parameter type="GtksharpGCFunc" name="gc" />
</parameters>
</method>
<method name="Copy" cname="gtksharp_opaque_copy">
<return-type type="GtksharpOpaque*" owned="true" />
</method>
<method name="Free" cname="gtksharp_opaque_free">
<return-type type="void" />
</method>
<method name="GetFriend" cname="gtksharp_opaque_get_friend">
<return-type type="GtksharpOpaque*" />
</method>
<method name="GetLastSerial" cname="gtksharp_opaque_get_last_serial" shared="true">
<return-type type="int" />
</method>
<method name="GetSerial" cname="gtksharp_opaque_get_serial">
<return-type type="int" />
</method>
<constructor cname="gtksharp_opaque_new" />
<method name="SetFriend" cname="gtksharp_opaque_set_friend">
<return-type type="void" />
<parameters>
<parameter type="GtksharpOpaque*" name="friend" />
</parameters>
</method>
</struct>
<struct name="Refcounted" cname="GtksharpRefcounted" opaque="1">
<field name="Serial" cname="serial" type="int" />
<field name="Refcount" cname="refcount" type="int" />
<field name="Valid" cname="valid" type="gboolean" />
<field name="Friend" cname="friend" type="GtksharpRefcounted*" />
<method name="Check" cname="gtksharp_refcounted_check" shared="true">
<return-type type="GtksharpRefcounted*" />
<parameters>
<parameter type="GtksharpRefcountedReturnFunc" name="func" />
<parameter type="GtksharpGCFunc" name="gc" />
</parameters>
</method>
<method name="CheckUnref" cname="gtksharp_refcounted_check_unref" shared="true">
<return-type type="GtksharpRefcounted*" />
<parameters>
<parameter type="GtksharpRefcountedReturnFunc" name="func" />
<parameter type="GtksharpGCFunc" name="gc" />
</parameters>
</method>
<method name="GetFriend" cname="gtksharp_refcounted_get_friend">
<return-type type="GtksharpRefcounted*" />
</method>
<method name="GetLastSerial" cname="gtksharp_refcounted_get_last_serial" shared="true">
<return-type type="int" />
</method>
<method name="GetRefcount" cname="gtksharp_refcounted_get_refcount">
<return-type type="int" />
</method>
<method name="GetSerial" cname="gtksharp_refcounted_get_serial">
<return-type type="int" />
</method>
<constructor cname="gtksharp_refcounted_new" />
<method name="Ref" cname="gtksharp_refcounted_ref">
<return-type type="void" />
</method>
<method name="SetFriend" cname="gtksharp_refcounted_set_friend">
<return-type type="void" />
<parameters>
<parameter type="GtksharpRefcounted*" name="friend" />
</parameters>
</method>
<method name="Unref" cname="gtksharp_refcounted_unref">
<return-type type="void" />
</method>
</struct>
<class name="Opaquetest" cname="GtksharpOpaquetest_">
<method name="GetError" cname="gtksharp_opaquetest_get_error" shared="true">
<return-type type="gboolean" />
</method>
<method name="SetError" cname="gtksharp_opaquetest_set_error" shared="true">
<return-type type="void" />
<parameters>
<parameter type="gboolean" name="err" />
</parameters>
</method>
<method name="SetExpectError" cname="gtksharp_opaquetest_set_expect_error" shared="true">
<return-type type="void" />
<parameters>
<parameter type="gboolean" name="err" />
</parameters>
</method>
</class>
</namespace>
</api>

View file

@ -0,0 +1,9 @@
<gapi-parser-input>
<api filename="opaque-api.xml">
<library name="libopaque.dll">
<namespace name="Gtksharp">
<dir>.</dir>
</namespace>
</library>
</api>
</gapi-parser-input>

226
sample/opaquetest/opaques.c Normal file
View file

@ -0,0 +1,226 @@
/* opaques.c: Opaque memory management test objects
*
* Copyright (c) 2005 Novell, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the Lesser GNU General
* Public License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "opaques.h"
#include <stdio.h>
static int opserial, refserial;
static gboolean error = FALSE, expect_error = FALSE;
static gboolean check_error (gboolean valid, const char *msg, ...);
GtksharpOpaque *
gtksharp_opaque_new (void)
{
GtksharpOpaque *op = g_new0 (GtksharpOpaque, 1);
op->valid = TRUE;
op->serial = opserial++;
return op;
}
int
gtksharp_opaque_get_serial (GtksharpOpaque *op)
{
check_error (op->valid, "get_serial on freed GtksharpOpaque serial %d\n", op->serial);
return op->serial;
}
void gtksharp_opaque_set_friend (GtksharpOpaque *op, GtksharpOpaque *friend)
{
check_error (op->valid, "set_friend on freed GtksharpOpaque serial %d\n", op->serial);
op->friend = friend;
}
GtksharpOpaque *
gtksharp_opaque_get_friend (GtksharpOpaque *op)
{
check_error (op->valid, "get_friend on freed GtksharpOpaque serial %d\n", op->serial);
return op->friend;
}
GtksharpOpaque *
gtksharp_opaque_copy (GtksharpOpaque *op)
{
check_error (op->valid, "copying freed GtksharpOpaque serial %d\n", op->serial);
return gtksharp_opaque_new ();
}
void
gtksharp_opaque_free (GtksharpOpaque *op)
{
check_error (op->valid, "Double free of GtksharpOpaque serial %d\n", op->serial);
op->valid = FALSE;
/* We don't actually free it */
}
GtksharpOpaque *
gtksharp_opaque_check (GtksharpOpaqueReturnFunc func, GtksharpGCFunc gc)
{
GtksharpOpaque *op = func ();
gc ();
return op;
}
GtksharpOpaque *
gtksharp_opaque_check_free (GtksharpOpaqueReturnFunc func, GtksharpGCFunc gc)
{
GtksharpOpaque *op = func ();
gc ();
gtksharp_opaque_free (op);
gc ();
return op;
}
int
gtksharp_opaque_get_last_serial (void)
{
return opserial - 1;
}
GtksharpRefcounted *
gtksharp_refcounted_new (void)
{
GtksharpRefcounted *ref = g_new0 (GtksharpRefcounted, 1);
ref->valid = TRUE;
ref->refcount = 1;
ref->serial = refserial++;
return ref;
}
int
gtksharp_refcounted_get_serial (GtksharpRefcounted *ref)
{
check_error (ref->valid, "get_serial on freed GtksharpRefcounted serial %d\n", ref->serial);
return ref->serial;
}
void
gtksharp_refcounted_ref (GtksharpRefcounted *ref)
{
if (check_error (ref->valid, "ref on freed GtksharpRefcounted serial %d\n", ref->serial))
return;
ref->refcount++;
}
void
gtksharp_refcounted_unref (GtksharpRefcounted *ref)
{
if (check_error (ref->valid, "unref on freed GtksharpRefcounted serial %d\n", ref->serial))
return;
if (--ref->refcount == 0) {
ref->valid = FALSE;
/* We don't actually free it */
}
}
int
gtksharp_refcounted_get_refcount (GtksharpRefcounted *ref)
{
check_error (ref->valid, "get_refcount on freed GtksharpRefcounted serial %d\n", ref->serial);
return ref->refcount;
}
void
gtksharp_refcounted_set_friend (GtksharpRefcounted *ref, GtksharpRefcounted *friend)
{
check_error (ref->valid, "set_friend on freed GtksharpRefcounted serial %d\n", ref->serial);
if (ref->friend)
gtksharp_refcounted_unref (ref->friend);
ref->friend = friend;
if (ref->friend)
gtksharp_refcounted_ref (ref->friend);
}
GtksharpRefcounted *
gtksharp_refcounted_get_friend (GtksharpRefcounted *ref)
{
check_error (ref->valid, "get_friend on freed GtksharpRefcounted serial %d\n", ref->serial);
return ref->friend;
}
GtksharpRefcounted *
gtksharp_refcounted_check (GtksharpRefcountedReturnFunc func, GtksharpGCFunc gc)
{
GtksharpRefcounted *ref = func ();
gc ();
return ref;
}
GtksharpRefcounted *
gtksharp_refcounted_check_unref (GtksharpRefcountedReturnFunc func, GtksharpGCFunc gc)
{
GtksharpRefcounted *ref = func ();
gc ();
gtksharp_refcounted_unref (ref);
gc ();
return ref;
}
int
gtksharp_refcounted_get_last_serial (void)
{
return refserial - 1;
}
static gboolean
check_error (gboolean valid, const char *msg, ...)
{
va_list ap;
if (valid)
return FALSE;
error = TRUE;
if (expect_error) {
expect_error = FALSE;
return FALSE;
}
expect_error = FALSE;
fprintf (stderr, " UNMANAGED ERROR: ");
va_start (ap, msg);
vfprintf (stderr, msg, ap);
va_end (ap);
return TRUE;
}
gboolean
gtksharp_opaquetest_get_error (void)
{
gboolean old_error = error;
error = expect_error = FALSE;
return old_error;
}
void
gtksharp_opaquetest_set_error (gboolean err)
{
error = err;
}
void
gtksharp_opaquetest_set_expect_error (gboolean err)
{
expect_error = err;
}

View file

@ -0,0 +1,70 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2000-2003, Ximian, Inc.
*/
#ifndef GTKSHARP_OPAQUES_H
#define GTKSHARP_OPAQUES_H 1
#include <glib-object.h>
typedef void (*GtksharpGCFunc) (void);
typedef struct GtksharpOpaque GtksharpOpaque;
struct GtksharpOpaque {
int serial;
gboolean valid;
GtksharpOpaque *friend;
};
typedef GtksharpOpaque *(*GtksharpOpaqueReturnFunc) (void);
GtksharpOpaque *gtksharp_opaque_new (void);
int gtksharp_opaque_get_serial (GtksharpOpaque *op);
void gtksharp_opaque_set_friend (GtksharpOpaque *op,
GtksharpOpaque *friend);
GtksharpOpaque *gtksharp_opaque_get_friend (GtksharpOpaque *op);
GtksharpOpaque *gtksharp_opaque_copy (GtksharpOpaque *op);
void gtksharp_opaque_free (GtksharpOpaque *op);
GtksharpOpaque *gtksharp_opaque_check (GtksharpOpaqueReturnFunc func,
GtksharpGCFunc gc);
GtksharpOpaque *gtksharp_opaque_check_free (GtksharpOpaqueReturnFunc func,
GtksharpGCFunc gc);
int gtksharp_opaque_get_last_serial (void);
typedef struct GtksharpRefcounted GtksharpRefcounted;
struct GtksharpRefcounted {
int serial, refcount;
gboolean valid;
GtksharpRefcounted *friend;
};
typedef GtksharpRefcounted *(*GtksharpRefcountedReturnFunc) (void);
GtksharpRefcounted *gtksharp_refcounted_new (void);
int gtksharp_refcounted_get_serial (GtksharpRefcounted *ref);
void gtksharp_refcounted_ref (GtksharpRefcounted *ref);
void gtksharp_refcounted_unref (GtksharpRefcounted *ref);
int gtksharp_refcounted_get_refcount (GtksharpRefcounted *ref);
void gtksharp_refcounted_set_friend (GtksharpRefcounted *ref,
GtksharpRefcounted *friend);
GtksharpRefcounted *gtksharp_refcounted_get_friend (GtksharpRefcounted *ref);
GtksharpRefcounted *gtksharp_refcounted_check (GtksharpRefcountedReturnFunc func,
GtksharpGCFunc gc);
GtksharpRefcounted *gtksharp_refcounted_check_unref (GtksharpRefcountedReturnFunc func,
GtksharpGCFunc gc);
int gtksharp_refcounted_get_last_serial (void);
gboolean gtksharp_opaquetest_get_error (void);
void gtksharp_opaquetest_set_error (gboolean err);
void gtksharp_opaquetest_set_expect_error (gboolean err);
#endif /* GTKSHARP_OPAQUES_H */

View file

@ -0,0 +1,3 @@
<configuration>
<dllmap dll="libopaque.dll" target=".libs/libopaque@LIB_PREFIX@@LIB_SUFFIX@"/>
</configuration>