Direct-BT v3.3.0-1-gc2d430c
Direct-BT - Direct Bluetooth Programming.
DBTNativeDownlink.java
Go to the documentation of this file.
1/**
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2020 Gothel Software e.K.
4 * Copyright (c) 2020 ZAFENA AB
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26package jau.direct_bt;
27
28import java.util.concurrent.atomic.AtomicBoolean;
29
30/**
31 * Java counterpart to C++ jau::JavaUplink
32 *
33 * Store the native `std::shared_ptr<T> *` long representation
34 * and handles the lifecycles of
35 * - Java object reference in the native object
36 * - `jau::JavaUplink`'s `std::shared_ptr<JavaAnon>` via `JavaUplink::setJavaObject()`
37 * - Native object reference in the Java object
38 * - `std::shared_ptr<T> *` long representation in `long nativeInstance`
39 *
40 * Using a `shared_ptr<T>` ensures surviving of the native object when temporary copied
41 * within JNI methods w/o locking.
42 */
43public abstract class DBTNativeDownlink
44{
45 /** native `std::shared_ptr<T> *` long representation. */
46 private long nativeInstance;
47 private final AtomicBoolean isNativeValid = new AtomicBoolean(false);
48 private final Object nativeLock = new Object();
49
50 /**
51 *
52 * @param nativeInstance
53 */
54 protected DBTNativeDownlink(final long nativeInstance)
55 {
56 this.nativeInstance = nativeInstance;
57 isNativeValid.set(true);
58 initNativeJavaObject(nativeInstance);
59 }
61 {
62 this.nativeInstance = 0;
63 isNativeValid.set(false);
64 }
65 protected final void initDownlink(final long nativeInstance) {
66 synchronized (nativeLock) {
67 if( isNativeValid.compareAndSet(false, true) ) {
68 this.nativeInstance = nativeInstance;
69 initNativeJavaObject(nativeInstance);
70 } else {
71 System.err.println("DBTNativeDownlink.init2: Already valid, dropping nativeInstance 0x"+Long.toHexString(nativeInstance));
72 }
73 }
74 }
75
76 /**
77 * Returns true if native instance is valid, otherwise false.
78 */
79 protected final boolean isNativeValid() { return isNativeValid.get(); }
80
81 @Override
82 protected void finalize()
83 {
84 delete();
85 }
86
87 /**
88 * Deletes the {@code nativeInstance} in the following order
89 * <ol>
90 * <li>Removes this java reference from the {@code nativeInstance}, i.e. `std::shared_ptr<JavaAnon>` via `JavaUplink::setJavaObject()`</li>
91 * <li>Deletes the {@code nativeInstance} via {@link #deleteImpl(long)}</li>
92 * <li>Zeros the {@code nativeInstance} reference</li>
93 * </ol>
94 */
95 public final void delete() {
96 synchronized (nativeLock) {
97 if( !isNativeValid.compareAndSet(true, false) ) {
98 if( DBTManager.DEBUG ) {
99 System.err.println("JAVA: delete: !valid -> bail: "+getClass().getSimpleName());
100 }
101 return;
102 }
103 if( DBTManager.DEBUG ) {
104 System.err.println("JAVA: delete.0: "+getClass().getSimpleName()+": valid, handle 0x"+Long.toHexString(nativeInstance));
105 }
106 final long _nativeInstance = nativeInstance;
107 nativeInstance = 0;
108 deleteNativeJavaObject(_nativeInstance); // will issue notifyDeleted() itself!
109 deleteImpl(_nativeInstance);
110 if( DBTManager.DEBUG ) {
111 System.err.println("JAVA: delete.X: "+getClass().getSimpleName()+": handle 0x"+Long.toHexString(nativeInstance));
112 }
113 }
114 }
115
116 /**
117 * Called from native JavaUplink dtor -> JavaGlobalObj dtor,
118 * i.e. native instance destructed in native land.
119 */
120 private final void notifyDeleted() {
121 synchronized (nativeLock) {
122 final boolean _isValid = isNativeValid.get();
123 final long _nativeInstance = nativeInstance;
124 isNativeValid.set(false);
125 nativeInstance = 0;
126 if( DBTManager.DEBUG ) {
127 System.err.println("JAVA: delete.notifyDeleted: "+getClass().getSimpleName()+", was: valid "+_isValid+", handle 0x"+Long.toHexString(_nativeInstance)+": "+toString());
128 }
129 }
130 }
131
132 /**
133 * Deletes the native instance.
134 * <p>
135 * Called via {@link #delete()} and at this point
136 * <ul>
137 * <li>this java reference has been removed from the native instance, i.e. {@code JavaUplink}'s {@code javaObjectRef = nullptr}</li>
138 * <li>the {@link #nativeInstance} reference has been zeroed, but passed as argument for this final native deletion task.</li>
139 * </ul>
140 * </p>
141 * @param nativeInstance copy of {@link #nativeInstance} reference, which has been already zeroed.
142 */
143 protected abstract void deleteImpl(long nativeInstance);
144
145 private native void initNativeJavaObject(final long nativeInstance);
146 private native void deleteNativeJavaObject(final long nativeInstance);
147}
static final boolean DEBUG
Definition: DBTManager.java:43