diff options
Diffstat (limited to 'cli_ure/source/ure/uno/util')
-rw-r--r-- | cli_ure/source/ure/uno/util/DisposeGuard.cs | 50 | ||||
-rw-r--r-- | cli_ure/source/ure/uno/util/WeakAdapter.cs | 111 | ||||
-rw-r--r-- | cli_ure/source/ure/uno/util/WeakBase.cs | 135 | ||||
-rw-r--r-- | cli_ure/source/ure/uno/util/WeakComponentBase.cs | 185 |
4 files changed, 481 insertions, 0 deletions
diff --git a/cli_ure/source/ure/uno/util/DisposeGuard.cs b/cli_ure/source/ure/uno/util/DisposeGuard.cs new file mode 100644 index 0000000000..ce2e90ddf3 --- /dev/null +++ b/cli_ure/source/ure/uno/util/DisposeGuard.cs @@ -0,0 +1,50 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +using System; +using unoidl.com.sun.star.lang; + +namespace uno.util +{ + +/** Helper class to conveniently auto dispose UNO objects from within + managed code. +*/ +public struct DisposeGuard : IDisposable +{ + private XComponent m_xComponent; + + /** ctor. + + @param obj target object + */ + public DisposeGuard( XComponent obj ) + { + m_xComponent = obj; + } + + /** System.IDisposable impl + */ + public void Dispose() + { + if (null != m_xComponent) + m_xComponent.dispose(); + } +} + +} diff --git a/cli_ure/source/ure/uno/util/WeakAdapter.cs b/cli_ure/source/ure/uno/util/WeakAdapter.cs new file mode 100644 index 0000000000..508a4b0f15 --- /dev/null +++ b/cli_ure/source/ure/uno/util/WeakAdapter.cs @@ -0,0 +1,111 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +using System; +using unoidl.com.sun.star.uno; +using unoidl.com.sun.star.lang; + +namespace uno.util +{ + +/** An XAdapter implementation that holds a weak reference + (System.WeakReference) to an object. + Clients can register listeners (unoidl.com.sun.star.lang.XReference) + which are notified when the object (the one which is kept weak) is + being finalized. That is, that object is being destroyed because there + are not any hard references to it. +*/ +public class WeakAdapter : XAdapter +{ + // references the XWeak implementation + private WeakReference m_weakRef; + // contains XReference objects registered by addReference + private delegate void XReference_dispose(); + private XReference_dispose m_XReference_dispose; + + /** ctor. + + @param obj the object that is to be held weakly + */ + public WeakAdapter( Object obj ) + { + m_weakRef = new WeakReference( obj ); + m_XReference_dispose = null; + } + + /** Called by the XWeak implementation (WeakBase) when it is being + finalized. It is only being called once. + The registererd XReference listeners are notified. On notification + they are to unregister themselves. The notification is thread-safe. + However, it is possible to add a listener during the notification + process, which will never receive a notification. + To prevent this, one would have to synchronize this method with + the addReference method. But this can result in deadlocks in a + multithreaded environment. + */ + internal /* non-virtual */ void referentDying() + { + XReference_dispose call; + lock (this) + { + call = m_XReference_dispose; + m_XReference_dispose = null; + } + if (null != call) + call(); + } + + // XAdapter impl + + /** Called to obtain a hard reference o the object which is kept weakly + by this instance. + + @return hard reference to the object + */ + public Object queryAdapted() + { + return m_weakRef.Target; + } + /** Called by clients to register listener which are notified when the + weak object is dying. + + @param xReference a listener + */ + public void removeReference( XReference xReference ) + { + lock (this) + { + m_XReference_dispose -= + new XReference_dispose( xReference.dispose ); + } + } + /** Called by clients to unregister listeners. + + @param xReference a listener + */ + public void addReference( XReference xReference ) + { + lock (this) + { + m_XReference_dispose += + new XReference_dispose( xReference.dispose ); + } + } +} + +} diff --git a/cli_ure/source/ure/uno/util/WeakBase.cs b/cli_ure/source/ure/uno/util/WeakBase.cs new file mode 100644 index 0000000000..561d2e577f --- /dev/null +++ b/cli_ure/source/ure/uno/util/WeakBase.cs @@ -0,0 +1,135 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +using System; +using System.Collections; +using unoidl.com.sun.star.uno; +using unoidl.com.sun.star.lang; + +namespace uno.util +{ + +/** This class can be used as a base class for UNO objects. + It implements the capability to be kept weakly + (unoidl.com.sun.star.uno.XWeak) and it implements + unoidl.com.sun.star.lang.XTypeProvider which is necessary for + using the object from StarBasic. +*/ +public class WeakBase : XWeak, XTypeProvider +{ + // Contains all WeakAdapter which have been created in this class + // They have to be notified when this object dies + private WeakAdapter m_adapter = null; + + protected static Hashtable s_types = new Hashtable(); + protected static Hashtable s_impl_ids = new Hashtable(); + + // XWeak impl + /** The returned XAdapter implementation can be used to keap a + weak reference to this object. + + @return a weak adapter + */ + public XAdapter queryAdapter() + { + if (null == m_adapter) + { + lock (this) + { + if (null == m_adapter) + m_adapter = new WeakAdapter( this ); + } + } + return m_adapter; + } + + /** Overrides of Object.Finalize method. + When there are no references to this object anymore, then the + garbage collector calls this method, thereby causing the adapter + object to be notified. The adapter, in turn, notifies all + listeners (unoidl.com.sun.star.uno.XReference). + */ + ~WeakBase() + { + if (null != m_adapter) + m_adapter.referentDying(); + } + + // XTypeProvider impl + + /** Returns an array of Type objects which represent all implemented + UNO interfaces of this object. + + @return Type objects of all implemented interfaces. + */ + public Type [] getTypes() + { + Type [] types; + Type type = GetType(); + lock (s_types) + { + types = (Type []) s_types[ type ]; + if (null == types) + { + Type [] interfaces = type.GetInterfaces(); + ArrayList list = new ArrayList( interfaces.Length ); + for ( Int32 pos = 0; pos < interfaces.Length; ++pos ) + { + Type iface = interfaces[ pos ]; + // xxx todo: as long as the bridge cannot introduce + // native CTS types into UNO on the fly + if (iface.FullName.StartsWith( "unoidl." )) + { + list.Add( iface ); + } + } + Int32 len = list.Count; + Type [] ar = new Type [ len ]; + for ( Int32 pos = 0; pos < len; ++pos ) + ar[ pos ] = (Type) list[ pos ]; + s_types[ type ] = ar; + types = ar; + } + } + return types; + } + + public byte [] getImplementationId() + { + return new byte[0]; + } + + // System.Object + public override String ToString() + { + System.Text.StringBuilder buf = + new System.Text.StringBuilder( base.ToString(), 256 ); + buf.Append( "\nUNO Object Implementation:\n\tInterfaces: " ); + Type [] types = getTypes(); + for ( Int32 pos = 0; pos < types.Length; ++pos ) + { + buf.Append( types[ pos ].FullName ); + if (pos < (types.Length -1)) + buf.Append( ", " ); + } + return buf.ToString(); + } +} + +} + diff --git a/cli_ure/source/ure/uno/util/WeakComponentBase.cs b/cli_ure/source/ure/uno/util/WeakComponentBase.cs new file mode 100644 index 0000000000..48715afc6a --- /dev/null +++ b/cli_ure/source/ure/uno/util/WeakComponentBase.cs @@ -0,0 +1,185 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +using System; +using unoidl.com.sun.star.lang; + +namespace uno.util +{ + +/** This class can be used as a base class for UNO objects. + It implements the capability to be kept weakly + (unoidl.com.sun.star.uno.XWeak) and it implements + unoidl.com.sun.star.lang.XTypeProvider which is necessary for + using the object from StarBasic. + In addition, it implements the interface + unoidl.com.sun.star.lang.XComponent to be disposed explicitly. +*/ +public class WeakComponentBase : WeakBase, XComponent +{ + private delegate void t_disposing( EventObject evt ); + private t_disposing m_disposing = null; + private bool m_inDispose = false; + private bool m_disposed = false; + + /** Indicates whether object is already disposed. + + @return + true, if object has been disposed + */ + protected bool isDisposed() + { + lock (this) + { + return m_disposed; + } + } + + /** Checks whether this object is disposed and throws a DisposedException + if it is already disposed. + */ + protected void checkUnDisposed() + { + if (! isDisposed()) + { + throw new unoidl.com.sun.star.lang.DisposedException( + "object already disposed!", this ); + } + } + + ~WeakComponentBase() + { + bool doDispose; + lock (this) + { + doDispose = (!m_inDispose && !m_disposed); + } + if (doDispose) + { + dispose(); + } + } + + /** Override to perform extra clean-up work. Provided for subclasses. + It is called during dispose() + */ + protected void preDisposing() + { + } + + /** Override to become notified right before the disposing action is + performed. + */ + protected void postDisposing() + { + } + + // XComponent impl + /** This method is called by the owner of this object to explicitly + dispose it. This implementation of dispose() first notifies this object + via preDisposing(), then all registered event listeners and + finally this object again calling postDisposing(). + */ + public void dispose() + { + // Determine in a thread-safe way if this is the first call to this + // method. Only then we proceed with the notification of event + // listeners. It is an error to call this method more than once. + bool doDispose = false; + t_disposing call = null; + lock (this) + { + if (! m_inDispose && !m_disposed) + { + call = m_disposing; + m_disposing = null; + m_inDispose = true; + doDispose = true; + } + } + // The notification occurs in an unsynchronized block in order to avoid + // deadlocks if one of the listeners calls back in a different thread on + // a synchronized method which uses the same object. + if (doDispose) + { + try + { + // call sub class + preDisposing(); + // send disposing notifications to listeners + if (null != call) + { + EventObject evt = new EventObject( this ); + call( evt ); + } + // call sub class + postDisposing(); + } + finally + { + // finally makes sure that the flags are set ensuring + // that this function is only called once. + m_disposed = true; + m_inDispose = false; + } + } + else + { + // in a multithreaded environment, it can't be avoided, + // that dispose is called twice. + // However this condition is traced, because it MAY indicate an + // error. +#if DEBUG + Console.WriteLine( + "WeakComponentBase.dispose() - dispose called twice" ); +#endif +// Debug.Fail( "WeakComponentBase.dispose() - dispose called twice" ); + } + } + /** Registers an event listener being notified when this object is disposed. + + @param xListener event listener + */ + public void addEventListener( XEventListener xListener ) + { + bool add; + lock (this) + { + add = (! m_inDispose && !m_disposed); + if (add) + m_disposing += new t_disposing( xListener.disposing ); + } + if (! add) + xListener.disposing( new EventObject( this ) ); + } + /** Revokes an event listener from being notified when this object + is disposed. + + @param xListener event listener + */ + public void removeEventListener( XEventListener xListener ) + { + lock (this) + { + if (! m_inDispose && !m_disposed) + m_disposing -= new t_disposing( xListener.disposing ); + } + } +} + +} |