2
2
// World.cs: Redland Initialization class
4
// $Id: World.cs,v 1.5 2004/07/09 15:29:06 cmdjb Exp $
4
// $Id: World.cs,v 1.7 2005/01/05 11:41:42 edd Exp $
7
7
// Cesar Lopez Nataren (cesar@ciencias.unam.mx)
8
8
// Edd Dumbill (edd@usefulinc.com)
10
10
// (C) 2004, Cesar Lopez Nataren
11
// (C) 2004-5 Edd Dumbill
19
19
namespace Redland {
21
public class WorldException : Exception {
22
public WorldException (String s): base (s) { }
21
25
class World : IWrapper {
27
private static HandleRef handle;
25
29
internal ArrayList messages;
30
private LogLevel level;
32
private static int refs = 0;
33
private static bool initialized = false;
35
// HOW WORLD'S LIFETIME IS MANAGED -- Edd Dumbill, 2005-01-05
37
// It is necessary to keep an instance of the C world around for
38
// as long as any Redland object needs it. This includes in their
39
// destructors. Unfortunately, when all references to objects and
40
// any 'inner' objects referred to within are liable to finalization,
41
// the .NET finalizer makes no distinction about order. This means
42
// that if the C-world were closed from ~World() then some of the
43
// other object finalizers would crash as the C world would close
44
// before their own C based destructors (which need world) could run.
46
// To get around this, we detach the destruction of the C world from
47
// the .NET World object lifecycle, and use a single static reference
48
// to it, with manual ref-counting. Each client object uses
49
// AddReference at construct-time and RemoveReference in Dispose().
50
// This includes the .NET World object.
52
// When RemoveReference makes the ref count hit zero, the C-world is
53
// destroyed. To ensure this only happens at the end of the run, the
54
// World object itself performs an AddReference on construct and
55
// RemoveReference on destruct.
29
57
public LogMessage [] Messages {
35
63
private delegate int MessageHandler (IntPtr userdata, IntPtr message);
64
private MessageHandler mhandler;
37
66
[DllImport ("librdf")]
38
67
static extern IntPtr librdf_new_world ();
39
68
[DllImport ("librdf")]
40
static extern void librdf_world_set_logger (IntPtr world,
69
static extern void librdf_world_set_logger (HandleRef world,
41
70
IntPtr userdata, Delegate cb);
45
world = librdf_new_world ();
47
librdf_world_set_logger (world, new IntPtr (0),
48
new MessageHandler (dispatchMessage));
49
level = LogLevel.Warn;
75
handle = new HandleRef (this, librdf_new_world ());
77
mhandler = new MessageHandler (dispatchMessage);
78
librdf_world_set_logger (handle, new IntPtr (0), mhandler);
79
level = LogLevel.Warn;
80
// logger set up, now let's open the world
85
throw new WorldException ("Can only make one World");
52
93
public LogLevel LogLevel {
61
[DllImport ("librdf")]
62
static extern void librdf_world_open (IntPtr world);
66
librdf_world_open (world);
69
public IntPtr Handle {
73
[DllImport ("librdf")]
74
static extern void librdf_free_world (IntPtr world);
78
librdf_free_world (world);
95
set { level = value; }
98
[DllImport ("librdf")]
99
static extern void librdf_world_open (HandleRef world);
101
static internal void Open ()
103
librdf_world_open (handle);
106
public HandleRef Handle {
107
get { return handle; }
110
public World AddReference () {
115
public void RemoveReference () {
117
throw new WorldException ("Attempt to remove reference from World when no references held");
125
[DllImport ("librdf")]
126
static extern void librdf_free_world (HandleRef world);
128
protected static void FreeWorld ()
131
throw new WorldException ("Attempt to free world when references still held");
133
if (handle.Handle != IntPtr.Zero) {
134
librdf_free_world (handle);
135
handle = new HandleRef (handle.Wrapper, IntPtr.Zero);
81
139
public void ClearLog ()