• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GENERATED SOURCE. DO NOT MODIFY. */
2 // © 2016 and later: Unicode, Inc. and others.
3 // License & terms of use: http://www.unicode.org/copyright.html#License
4 /*
5 *******************************************************************************
6 * Copyright (C) 2013-2014, International Business Machines
7 * Corporation and others.  All Rights Reserved.
8 *******************************************************************************
9 * SharedObject.java, ported from sharedobject.h/.cpp
10 *
11 * C++ version created on: 2013dec19
12 * created by: Markus W. Scherer
13 */
14 
15 package ohos.global.icu.impl.coll;
16 
17 import java.util.concurrent.atomic.AtomicInteger;
18 
19 import ohos.global.icu.util.ICUCloneNotSupportedException;
20 
21 /**
22  * Base class for shared, reference-counted, auto-deleted objects.
23  * Java subclasses are mutable and must implement clone().
24  *
25  * <p>In C++, the SharedObject base class is used for both memory and ownership management.
26  * In Java, memory management (deletion after last reference is gone)
27  * is up to the garbage collector,
28  * but the reference counter is still used to see whether the referent is the sole owner.
29  *
30  * <p>Usage:
31  * <pre>
32  * class S extends SharedObject {
33  *     public clone() { ... }
34  * }
35  *
36  * // Either use the nest class Reference (which costs an extra allocation),
37  * // or duplicate its code in the class that uses S
38  * // (which duplicates code and is more error-prone).
39  * class U {
40  *     // For read-only access, use s.readOnly().
41  *     // For writable access, use S ownedS = s.copyOnWrite();
42  *     private SharedObject.Reference&lt;S&gt; s;
43  *     // Returns a writable version of s.
44  *     // If there is exactly one owner, then s itself is returned.
45  *     // If there are multiple owners, then s is replaced with a clone,
46  *     // and that is returned.
47  *     private S getOwnedS() {
48  *         return s.copyOnWrite();
49  *     }
50  *     public U clone() {
51  *         ...
52  *         c.s = s.clone();
53  *         ...
54  *     }
55  * }
56  *
57  * class V {
58  *     // For read-only access, use s directly.
59  *     // For writable access, use S ownedS = getOwnedS();
60  *     private S s;
61  *     // Returns a writable version of s.
62  *     // If there is exactly one owner, then s itself is returned.
63  *     // If there are multiple owners, then s is replaced with a clone,
64  *     // and that is returned.
65  *     private S getOwnedS() {
66  *         if(s.getRefCount() > 1) {
67  *             S ownedS = s.clone();
68  *             s.removeRef();
69  *             s = ownedS;
70  *             ownedS.addRef();
71  *         }
72  *         return s;
73  *     }
74  *     public U clone() {
75  *         ...
76  *         s.addRef();
77  *         ...
78  *     }
79  *     protected void finalize() {
80  *         ...
81  *         if(s != null) {
82  *             s.removeRef();
83  *             s = null;
84  *         }
85  *         ...
86  *     }
87  * }
88  * </pre>
89  *
90  * Either use only Java memory management, or use addRef()/removeRef().
91  * Sharing requires reference-counting.
92  *
93  * TODO: Consider making this more widely available inside ICU,
94  * or else adopting a different model.
95  * @hide exposed on OHOS
96  */
97 public class SharedObject implements Cloneable {
98     /**
99      * Similar to a smart pointer, basically a port of the static methods of C++ SharedObject.
100      * @hide exposed on OHOS
101      */
102     public static final class Reference<T extends SharedObject> implements Cloneable {
103         private T ref;
104 
Reference(T r)105         public Reference(T r) {
106             ref = r;
107             if(r != null) {
108                 r.addRef();
109             }
110         }
111 
112         @SuppressWarnings("unchecked")
113         @Override
clone()114         public Reference<T> clone() {
115             Reference<T> c;
116             try {
117                 c = (Reference<T>)super.clone();
118             } catch (CloneNotSupportedException e) {
119                 // Should never happen.
120                 throw new ICUCloneNotSupportedException(e);
121             }
122             if(ref != null) {
123                 ref.addRef();
124             }
125             return c;
126         }
127 
readOnly()128         public T readOnly() { return ref; }
129 
130         /**
131          * Returns a writable version of the reference.
132          * If there is exactly one owner, then the reference itself is returned.
133          * If there are multiple owners, then the reference is replaced with a clone,
134          * and that is returned.
135          */
copyOnWrite()136         public T copyOnWrite() {
137             T r = ref;
138             if(r.getRefCount() <= 1) { return r; }
139             @SuppressWarnings("unchecked")
140             T r2 = (T)r.clone();
141             r.removeRef();
142             ref = r2;
143             r2.addRef();
144             return r2;
145         }
146 
clear()147         public void clear() {
148             if(ref != null) {
149                 ref.removeRef();
150                 ref = null;
151             }
152         }
153 
154         @Override
finalize()155         protected void finalize() throws Throwable {
156             super.finalize();
157             clear();
158         }
159     }
160 
161     /** Initializes refCount to 0. */
SharedObject()162     public SharedObject() {}
163 
164     /** Initializes refCount to 0. */
165     @Override
clone()166     public SharedObject clone() {
167         SharedObject c;
168         try {
169             c = (SharedObject)super.clone();
170         } catch (CloneNotSupportedException e) {
171             // Should never happen.
172             throw new ICUCloneNotSupportedException(e);
173         }
174         c.refCount = new AtomicInteger();
175         return c;
176     }
177 
178     /**
179      * Increments the number of references to this object. Thread-safe.
180      */
addRef()181     public final void addRef() { refCount.incrementAndGet(); }
182     /**
183      * Decrements the number of references to this object,
184      * and auto-deletes "this" if the number becomes 0. Thread-safe.
185      */
removeRef()186     public final void removeRef() {
187         // Deletion in Java is up to the garbage collector.
188         refCount.decrementAndGet();
189     }
190 
191     /**
192      * Returns the reference counter. Uses a memory barrier.
193      */
getRefCount()194     public final int getRefCount() { return refCount.get(); }
195 
deleteIfZeroRefCount()196     public final void deleteIfZeroRefCount() {
197         // Deletion in Java is up to the garbage collector.
198     }
199 
200     private AtomicInteger refCount = new AtomicInteger();
201 }
202