def make_handler_g_body(cls): csname = schema.cpp2csname(cls.get_name()) iname = schema.get_iname(cls) funcs = get_funcs(cls) result = [] # this dictionary used to keep object alive even when we doesn't reference object directly, but it can be referenced only from native side result.append( 'private static Dictionary<IntPtr, %(csname)s> _roots = new Dictionary<IntPtr, %(csname)s>();' % {'csname': csname}) result.append('') result.append('private int _refct;') result.append('private %s* _self;' % iname) # result.append('private bool _disposed;') result.append('') result.append('protected object SyncRoot { get { return this; } }') result.append('') if schema.is_reversible(cls): result.append('internal static %s FromNativeOrNull(%s* ptr)' % (csname, iname)) result.append('{') result.append(indent + '%s value = null;' % csname) result.append(indent + 'bool found;') result.append(indent + 'lock (_roots)') result.append(indent + '{') result.append(indent + indent + 'found = _roots.TryGetValue((IntPtr)ptr, out value);') result.append(indent + '}') result.append(indent + 'return found ? value : null;') result.append('}') result.append('') result.append('internal static %s FromNative(%s* ptr)' % (csname, iname)) result.append('{') result.append(indent + 'var value = FromNativeOrNull(ptr);') result.append( indent + 'if (value == null) throw ExceptionBuilder.ObjectNotFound();') result.append(indent + 'return value;') result.append('}') result.append('') for func in funcs: result.append( 'private %(iname)s.%(delegate_type)s %(delegate_slot)s;' % func) result.append('') # ctor result.append('protected %s()' % csname) result.append('{') result.append(indent + '_self = %s.Alloc();' % iname) result.append('') for func in funcs: result.append( indent + '%(delegate_slot)s = new %(iname)s.%(delegate_type)s(%(csn_name)s);' % func) result.append( indent + '_self->%(field_name)s = Marshal.GetFunctionPointerForDelegate(%(delegate_slot)s);' % func) result.append('}') result.append('') # finalizer & dispose result.append('~%s()' % csname) result.append('{') result.append(indent + 'Dispose(false);') result.append('}') result.append('') if schema.is_autodispose(cls): result.append('private void Dispose()') result.append('{') result.append(indent + 'Dispose(true);') result.append(indent + 'GC.SuppressFinalize(this);') result.append('}') result.append('') result.append('protected virtual void Dispose(bool disposing)') result.append('{') # result.append(indent + '_disposed = true;') result.append(indent + 'if (_self != null)') result.append(indent + '{') result.append(indent + indent + '%s.Free(_self);' % iname) result.append(indent + indent + '_self = null;') result.append(indent + '}') result.append('}') result.append('') # todo: this methods must throw exception if object already disposed # todo: verify self pointer in debug result.append('private void add_ref(%s* self)' % iname) result.append('{') result.append(indent + 'lock (SyncRoot)') result.append(indent + '{') result.append(indent + indent + 'var result = ++_refct;') result.append(indent + indent + 'if (result == 1)') result.append(indent + indent + '{') result.append(indent + indent + indent + 'lock (_roots) { _roots.Add((IntPtr)_self, this); }') result.append(indent + indent + '}') result.append(indent + '}') result.append('}') result.append('') result.append('private int release(%s* self)' % iname) result.append('{') result.append(indent + 'lock (SyncRoot)') result.append(indent + '{') result.append(indent + indent + 'var result = --_refct;') result.append(indent + indent + 'if (result == 0)') result.append(indent + indent + '{') result.append(indent + indent + indent + 'lock (_roots) { _roots.Remove((IntPtr)_self); }') if schema.is_autodispose(cls): result.append(indent + indent + indent + 'Dispose();') result.append(indent + indent + indent + 'return 1;') result.append(indent + indent + '}') result.append(indent + indent + 'return 0;') result.append(indent + '}') result.append('}') result.append('') result.append('private int has_one_ref(%s* self)' % iname) result.append('{') result.append(indent + 'lock (SyncRoot) { return _refct == 1 ? 1 : 0; }') result.append('}') result.append('') result.append('private int has_at_least_one_ref(%s* self)' % iname) result.append('{') result.append(indent + 'lock (SyncRoot) { return _refct != 0 ? 1 : 0; }') result.append('}') result.append('') result.append('internal %s* ToNative()' % iname) result.append('{') result.append(indent + 'add_ref(_self);') result.append(indent + 'return _self;') result.append('}') result.append('') result.append('[Conditional("DEBUG")]') result.append('private void CheckSelf(%s* self)' % iname) result.append('{') result.append( indent + 'if (_self != self) throw ExceptionBuilder.InvalidSelfReference();') result.append('}') result.append('') return result
def make_handler_g_body(cls): csname = schema.cpp2csname(cls.get_name()) iname = schema.get_iname(cls) funcs = get_funcs(cls) result = [] # this dictionary used to keep object alive even when we doesn't reference object directly, but it can be referenced only from native side result.append('private static Dictionary<IntPtr, %(csname)s> _roots = new Dictionary<IntPtr, %(csname)s>();' % { 'csname' : csname }) result.append('') result.append('private int _refct;') result.append('private %s* _self;' % iname) # result.append('private bool _disposed;') result.append('') result.append('protected object SyncRoot { get { return this; } }') result.append('') if schema.is_reversible(cls): result.append('internal static %s FromNativeOrNull(%s* ptr)' % (csname, iname)) result.append('{') result.append(indent + '%s value = null;' % csname) result.append(indent + 'bool found;') result.append(indent + 'lock (_roots)') result.append(indent + '{') result.append(indent + indent + 'found = _roots.TryGetValue((IntPtr)ptr, out value);') result.append(indent + '}') result.append(indent + 'return found ? value : null;') result.append('}') result.append('') result.append('internal static %s FromNative(%s* ptr)' % (csname, iname)) result.append('{') result.append(indent + 'var value = FromNativeOrNull(ptr);') result.append(indent + 'if (value == null) throw ExceptionBuilder.ObjectNotFound();') result.append(indent + 'return value;') result.append('}') result.append('') for func in funcs: result.append('private %(iname)s.%(delegate_type)s %(delegate_slot)s;' % func) result.append('') # ctor result.append('protected %s()' % csname) result.append('{') result.append(indent + '_self = %s.Alloc();' % iname) result.append(''); for func in funcs: result.append(indent + '%(delegate_slot)s = new %(iname)s.%(delegate_type)s(%(csn_name)s);' % func) result.append(indent + '_self->%(field_name)s = Marshal.GetFunctionPointerForDelegate(%(delegate_slot)s);' % func) result.append('}') result.append('') # finalizer & dispose result.append('~%s()' % csname) result.append('{') result.append(indent + 'Dispose(false);') result.append('}') result.append('') result.append('protected virtual void Dispose(bool disposing)') result.append('{') # result.append(indent + '_disposed = true;') result.append(indent + 'if (_self != null)') result.append(indent + '{') result.append(indent + indent + '%s.Free(_self);' % iname) result.append(indent + indent + '_self = null;') result.append(indent + '}') result.append('}') result.append('') # todo: this methods must throw exception if object already disposed # todo: verify self pointer in debug result.append('private int add_ref(%s* self)' % iname) result.append('{') result.append(indent + 'lock (SyncRoot)') result.append(indent + '{') result.append(indent + indent + 'var result = ++_refct;') result.append(indent + indent + 'if (result == 1)') result.append(indent + indent + '{') result.append(indent + indent + indent + 'lock (_roots) { _roots.Add((IntPtr)_self, this); }') result.append(indent + indent + '}') result.append(indent + indent + 'return result;') result.append(indent + '}') result.append('}') result.append('') result.append('private int release(%s* self)' % iname) result.append('{') result.append(indent + 'lock (SyncRoot)') result.append(indent + '{') result.append(indent + indent + 'var result = --_refct;') result.append(indent + indent + 'if (result == 0)') result.append(indent + indent + '{') result.append(indent + indent + indent + 'lock (_roots) { _roots.Remove((IntPtr)_self); }') result.append(indent + indent + '}') result.append(indent + indent + 'return result;') result.append(indent + '}') result.append('}') result.append('') result.append('private int get_refct(%s* self)' % iname) result.append('{') result.append(indent + 'return _refct;') result.append('}') result.append('') result.append('internal %s* ToNative()' % iname) result.append('{') result.append(indent + 'add_ref(_self);') result.append(indent + 'return _self;') result.append('}') result.append('') result.append('[Conditional("DEBUG")]') result.append('private void CheckSelf(%s* self)' % iname) result.append('{') result.append(indent + 'if (_self != self) throw ExceptionBuilder.InvalidSelfReference();') result.append('}') result.append('') return result