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