]> git.draconx.ca Git - upkg.git/commitdiff
uobject: Implement an interface for loading/unloading.
authorNick Bowler <nbowler@draconx.ca>
Mon, 13 Jul 2009 22:32:19 +0000 (18:32 -0400)
committerNick Bowler <nbowler@draconx.ca>
Mon, 13 Jul 2009 22:32:19 +0000 (18:32 -0400)
This allows, for example, an instance of Engine.Music to load its music
data only when required.  It may be useful to keep around an instance
without allocating gobs of memory to store data that won't be used.

src/Makefile.am
src/engine/music.c
src/loadable.c [new file with mode: 0644]
src/loadable.h [new file with mode: 0644]
src/upkg.c

index 67e4d7b0e36ef41c238383ab2f38aaea56a184da..128393a957ae0f8154d1796bf41ca4d5bd0fb600 100644 (file)
@@ -2,14 +2,14 @@ lib_LTLIBRARIES = libupkg.la
 
 libupkg_la_SOURCES = libupkg.c pack.c
 include_HEADERS = upkg.h
-noinst_HEADERS = pack.h exportable.h uobject.h module.h avl.h
+noinst_HEADERS = pack.h loadable.h exportable.h uobject.h module.h avl.h
 
 if BUILD_UPKG
 
 include engine/Makefile.inc
 
 bin_PROGRAMS  = upkg
-upkg_SOURCES  = upkg.c avl.c module.c exportable.c uobject.c
+upkg_SOURCES  = upkg.c avl.c module.c loadable.c exportable.c uobject.c
 upkg_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib \
        $(GLIB_CFLAGS) $(LTDLINCL)
 upkg_LDFLAGS  = -L$(top_builddir)/lib -export-dynamic
index 87a549b7e6d538766a2832ff7248afca41bfe50a..f770662995e8f63e2ea359117b005850783b7fc6 100644 (file)
@@ -3,6 +3,7 @@
 #include <glib-object.h>
 
 #include "exportable.h"
+#include "loadable.h"
 #include "uobject.h"
 #include "music.h"
 #include "upkg.h"
 
 struct music_priv {
        struct upkg_file *f;
+       unsigned loaded;
 };
 
 static void exportable_init(UObjectExportable *);
+static void loadable_init(UObjectLoadable *);
 
 G_DEFINE_DYNAMIC_TYPE_EXTENDED(EngineMusic, engine_music, U_OBJECT_TYPE, 0,
        G_IMPLEMENT_INTERFACE(U_OBJECT_TYPE_EXPORTABLE, exportable_init)
+       G_IMPLEMENT_INTERFACE(U_OBJECT_TYPE_LOADABLE, loadable_init)
 );
 
+static int load(GObject *o)
+{
+       struct music_priv *priv = MUSIC_GET_PRIV(o);
+
+       if (!priv->loaded) {
+               g_return_val_if_fail(priv->f != NULL, -1);
+
+               if (upkg_export_seek(priv->f, 0, SEEK_SET) != 0) {
+                       return -1;
+               }
+       }
+
+       priv->loaded++;
+       return 0;
+}
+
+static void unload(GObject *o)
+{
+       struct music_priv *priv = MUSIC_GET_PRIV(o);
+       g_return_if_fail(priv->loaded > 0);
+
+       --priv->loaded;
+}
+
 static int export(GObject *o, FILE *f)
 {
        struct music_priv *priv = MUSIC_GET_PRIV(o);
@@ -54,6 +82,12 @@ static void exportable_init(UObjectExportable *e)
        e->export_name = export_name;
 }
 
+static void loadable_init(UObjectLoadable *l)
+{
+       l->load   = load;
+       l->unload = unload;
+}
+
 static int deserialize(UObject *o, struct upkg_file *f)
 {
        struct music_priv *priv = MUSIC_GET_PRIV(o);
@@ -99,15 +133,28 @@ void music_register(GTypeModule *m)
 
 static void engine_music_init(EngineMusic *m)
 {
+       struct music_priv *priv = MUSIC_GET_PRIV(m);
+       *priv = (struct music_priv){0};
+}
+
+static void engine_music_finalize(GObject *o)
+{
+       struct music_priv *priv = MUSIC_GET_PRIV(o);
+
+       if (priv->loaded >= 1) {
+               priv->loaded = 1;
+               unload(o);
+       }
 }
 
 static void engine_music_class_init(EngineMusicClass *class)
 {
        UObjectClass *uo = U_OBJECT_CLASS(class);
-
+       GObjectClass *go = G_OBJECT_CLASS(class);
        g_type_class_add_private(class, sizeof (struct music_priv));
 
        uo->deserialize = deserialize;
+       go->finalize    = engine_music_finalize;
 }
 
 static void engine_music_class_finalize(EngineMusicClass *class)
diff --git a/src/loadable.c b/src/loadable.c
new file mode 100644 (file)
index 0000000..26b81fd
--- /dev/null
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include <glib-object.h>
+#include "loadable.h"
+
+GType u_object_loadable_get_type(void)
+{
+       static GType type = 0;
+       if (type == 0) {
+               static const GTypeInfo info = {
+                       sizeof (UObjectLoadable),
+                       NULL,
+                       NULL,
+               };
+
+               type = g_type_register_static(G_TYPE_INTERFACE,
+                       "UObjectLoadable", &info, 0);
+       }
+       return type;
+}
+
+int u_object_load(GObject *obj)
+{
+       g_return_val_if_fail(U_OBJECT_IS_LOADABLE(obj), -1);
+       return U_OBJECT_LOADABLE_GET_INTERFACE(obj)->load(obj);
+}
+
+void u_object_unload(GObject *obj)
+{
+       g_return_if_fail(U_OBJECT_IS_LOADABLE(obj));
+       U_OBJECT_LOADABLE_GET_INTERFACE(obj)->unload(obj);
+}
diff --git a/src/loadable.h b/src/loadable.h
new file mode 100644 (file)
index 0000000..88d25e3
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef LOADABLE_H_
+#define LOADABLE_H_
+
+#include <stdio.h>
+#include <glib-object.h>
+
+#define U_OBJECT_TYPE_LOADABLE (u_object_loadable_get_type())
+#define U_OBJECT_LOADABLE(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, \
+       U_OBJECT_TYPE_LOADABLE, UObjectLoadable)
+#define U_OBJECT_IS_LOADABLE(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, \
+       U_OBJECT_TYPE_LOADABLE)
+#define U_OBJECT_LOADABLE_GET_INTERFACE(inst) G_TYPE_INSTANCE_GET_INTERFACE \
+       (inst, U_OBJECT_TYPE_LOADABLE, UObjectLoadable)
+
+typedef struct UObjectLoadable UObjectLoadable;
+
+struct UObjectLoadable {
+       GTypeInterface parent;
+
+       int (*load)(GObject *obj);
+       void (*unload)(GObject *obj);
+};
+
+GType u_object_loadable_get_type(void);
+
+int u_object_load(GObject *obj);
+void u_object_unload(GObject *obj);
+
+#endif
index 82a673d100ccc6c522bd597713608ab40d3cd7fb..87794cb6b1c3b6413e2d68383742a1b3c00e0b85 100644 (file)
@@ -28,6 +28,7 @@
 #include "module.h"
 #include "uobject.h"
 #include "exportable.h"
+#include "loadable.h"
 
 enum {
        MODE_INFO,
@@ -161,6 +162,11 @@ static int export(struct upkg *pkg, GObject *obj, unsigned idx)
        if (u_object_deserialize(obj, f) != 0) {
                goto out;
        }
+
+       if (U_OBJECT_IS_LOADABLE(obj) && u_object_load(obj) != 0) {
+               goto out;
+       }
+
        u_object_export_name(obj, name, sizeof name);
 
        printf("exporting %s to %s\n", upkg_export_name(pkg, idx), name);
@@ -178,6 +184,10 @@ static int export(struct upkg *pkg, GObject *obj, unsigned idx)
                goto out;
        }
 
+       if (U_OBJECT_IS_LOADABLE(obj)) {
+               u_object_unload(obj);
+       }
+
 out:
        upkg_export_close(f);
        return rc;