1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 using System;
29 using unoidl.com.sun.star.uno;
30 using unoidl.com.sun.star.lang;
31 
32 namespace uno.util
33 {
34 
35 /** An XAdapter implementation that holds a weak reference
36     (System.WeakReference) to an object.
37     Clients can register listeners (unoidl.com.sun.star.lang.XReference)
38     which are notified when the object (the one which is kept weak) is
39     being finalized.  That is, that object is being destroyed because there
40     are not any hard references to it.
41 */
42 public class WeakAdapter : XAdapter
43 {
44     // references the XWeak implementation
45     private WeakReference m_weakRef;
46     // contains XReference objects registered by addReference
47     private delegate void XReference_dispose();
48     private XReference_dispose m_XReference_dispose;
49 
50     /** ctor.
51 
52         @param obj the object that is to be held weakly
53     */
54     public WeakAdapter( Object obj )
55     {
56         m_weakRef = new WeakReference( obj );
57         m_XReference_dispose = null;
58     }
59 
60     /** Called by the XWeak implementation (WeakBase) when it is being
61         finalized.  It is only being called once.
62         The registererd XReference listeners are notified. On notification
63         they are  to unregister themselves. The notification is thread-safe.
64         However, it is possible to add a listener during the notification
65         process, which will never receive a notification.
66         To prevent this, one would have to synchronize this method with
67         the addReference method. But this can result in deadlocks in a
68         multithreaded environment.
69     */
70     internal /* non-virtual */ void referentDying()
71     {
72         XReference_dispose call;
73         lock (this)
74         {
75             call = m_XReference_dispose;
76             m_XReference_dispose = null;
77         }
78         if (null != call)
79             call();
80     }
81 
82     // XAdapter impl
83 
84     /** Called to obtain a hard reference o the object which is kept weakly
85         by this instance.
86 
87         @return hard reference to the object
88     */
89     public Object queryAdapted()
90     {
91         return m_weakRef.Target;
92     }
93     /** Called by clients to register listener which are notified when the
94         weak object is dying.
95 
96         @param xReference a listener
97     */
98     public void removeReference( XReference xReference )
99     {
100         lock (this)
101         {
102             m_XReference_dispose -=
103                 new XReference_dispose( xReference.dispose );
104         }
105     }
106     /** Called by clients to unregister listeners.
107 
108         @param xReference a listener
109     */
110     public void addReference( XReference xReference )
111     {
112         lock (this)
113         {
114             m_XReference_dispose +=
115                 new XReference_dispose( xReference.dispose );
116         }
117     }
118 }
119 
120 }
121