0

I'm writing a C# wrapper around a native dll that uses opaque pointers to identify resources. A typical example would be something like

typedef struct session session;
typedef struct track track;

void* sessionCreate(int arg, session** sess);
void  sessionRelease(session** sess);
track* sessionGetTrack(session* sess, int index);
void trackAddRef(track* trk);
void trackRelease(track* trk);
int  trackGetLength(track* trk);

In my wrapper, I've created C# classes corresponding to the different opaque types, with member functions corresponding to the various functions using the different opaque types.

This is fine. There are also callbacks from the dll, for example

void(* track_changed )(track *trk, bool changedExternally);

In order to map from the static delegate that handles the callback to the object that corresponds to the handle supplied, I'm using a static dictionary of WeakReferences (IntPtr/SafeHandle as key, object reference as aata) in each of my classes.

So what is the right way to approach removing entries from the static dictionary? I'm writing library code and cannot rely on my clients to Dispose my objects. Should the I put the code in the finalizer?

Or is there a better way to manage the correspondence between the static callbacks and my object instances?

Tom Davies
  • 2,386
  • 3
  • 27
  • 44

1 Answers1

1

Your clients really should (indeed I would prefer to say must) dispose of your objects since they are IDisposable, just like they do with other BCL classes.

In any case a bog-standard implementation of the dispose/finalize pattern should cover all bases. There is more related discussion here.

Community
  • 1
  • 1
Jon
  • 428,835
  • 81
  • 738
  • 806
  • Asking clients to have to Dispose my objects simply because of my internal implementation details seems like bad form to me. I'd rather not implement IDisposable at all, and just leave the Finalizers to remove entries from the static dictionary. Would this be bad? – Tom Davies Jan 22 '13 at 15:26
  • I was under the impression that each object corresponds to (or is?) a `SafeHandle`, which is rightly `IDisposable`. Therefore shouldn't the user have the responsibility of releasing the unmanaged resource as usual? When they do, you can depopulate the dictionary for free. – Jon Jan 22 '13 at 15:29
  • Part of the motivation for the facade/wrapper is to make use of garbage collection so that users need not worry about manual resource handling. Deterministic releasing of the unmanaged resources is not important to clients of this wrapper. – Tom Davies Jan 22 '13 at 15:35
  • @TomDavies - If you want users to be able to use the garbage collector then you should implement IDisposable. Don't try to recreate something custom, use IDisposable, and allow your users to implement your libary the correct way. – Security Hound Jan 22 '13 at 20:04
  • Ramhound - that confuses me - implementing IDisposible suggests to users that they should take responsibility for the lifecycle of the objects, rather than the GC. At least, it looks that way to me. – Tom Davies Jan 22 '13 at 20:28
  • @TomDavies: It's not only about *deterministic* release. Applications that use lots of unmanaged resources might easily starve the OS itself. IMHO the cleanliness of a dictionary is not what you should be worrying about -- you can put 50K items inside with nothing bad happening other than memory being used. But 50K unreleased OS handles? – Jon Jan 22 '13 at 20:29
  • They are not OS handles in this case, but handles to refernce counted structures allocated/destroyed inside a native dll. I don't really see any difference between leaving the cleanup of these resources to the GC, and the normal operation of the GC on managed objects. – Tom Davies Jan 22 '13 at 20:35