summaryrefslogtreecommitdiffstats
path: root/java/direct_bt
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2020-06-29 05:59:08 +0200
committerSven Gothel <[email protected]>2020-06-29 05:59:08 +0200
commit0b7e94850a0bb5e4d389709bc9c449cd4f7dc094 (patch)
tree852b5353ac669275145bbb5097692b8ce579df9a /java/direct_bt
parent809487569a0e521bd9a5850cfbee00c2ee524932 (diff)
Resolve regression calling DBTNativeDownlink.delete() having notifyDeleted() being called back from deleteNativeJavaObject(..)
Regression introduced with commit 83e0c7f75b4206701c1b9c62ebd4282f50f92a31 DBTNativeDownlink.delete() calls DBTNativeDownlink.deleteNativeJavaObject(..), which by itself now calls back using DBTNativeDownlink.notifyDeleted() and purges isValid and nativeInstance. Therefor, DBTNativeDownlink.delete() needs to cache the nativeInstance reference and pass it down to DBTNativeDownlink.deleteImpl(long) as argument. Further refine synchronization, using a local Object and isValid being an AtomicBoolean to allow isValid() return the current state.
Diffstat (limited to 'java/direct_bt')
-rw-r--r--java/direct_bt/tinyb/DBTAdapter.java2
-rw-r--r--java/direct_bt/tinyb/DBTDevice.java2
-rw-r--r--java/direct_bt/tinyb/DBTGattCharacteristic.java2
-rw-r--r--java/direct_bt/tinyb/DBTGattDescriptor.java2
-rw-r--r--java/direct_bt/tinyb/DBTGattService.java2
-rw-r--r--java/direct_bt/tinyb/DBTManager.java5
-rw-r--r--java/direct_bt/tinyb/DBTNativeDownlink.java68
7 files changed, 54 insertions, 29 deletions
diff --git a/java/direct_bt/tinyb/DBTAdapter.java b/java/direct_bt/tinyb/DBTAdapter.java
index 17b975f9..b10eb02c 100644
--- a/java/direct_bt/tinyb/DBTAdapter.java
+++ b/java/direct_bt/tinyb/DBTAdapter.java
@@ -303,7 +303,7 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter
/* internal */
@Override
- protected native void deleteImpl();
+ protected native void deleteImpl(long nativeInstance);
/* discovery */
diff --git a/java/direct_bt/tinyb/DBTDevice.java b/java/direct_bt/tinyb/DBTDevice.java
index 6a0ca25c..8f0b0c4e 100644
--- a/java/direct_bt/tinyb/DBTDevice.java
+++ b/java/direct_bt/tinyb/DBTDevice.java
@@ -597,7 +597,7 @@ public class DBTDevice extends DBTObject implements BluetoothDevice
* </p>
*/
@Override
- protected native void deleteImpl();
+ protected native void deleteImpl(long nativeInstance);
@Override
public native boolean addCharacteristicListener(final GATTCharacteristicListener listener, final BluetoothGattCharacteristic characteristicMatch);
diff --git a/java/direct_bt/tinyb/DBTGattCharacteristic.java b/java/direct_bt/tinyb/DBTGattCharacteristic.java
index ccca1ae4..bd7f0dea 100644
--- a/java/direct_bt/tinyb/DBTGattCharacteristic.java
+++ b/java/direct_bt/tinyb/DBTGattCharacteristic.java
@@ -322,6 +322,6 @@ public class DBTGattCharacteristic extends DBTObject implements BluetoothGattCha
private native boolean enableValueNotificationsImpl(boolean v);
@Override
- protected native void deleteImpl();
+ protected native void deleteImpl(long nativeInstance);
}
diff --git a/java/direct_bt/tinyb/DBTGattDescriptor.java b/java/direct_bt/tinyb/DBTGattDescriptor.java
index 86b27530..2733f8ba 100644
--- a/java/direct_bt/tinyb/DBTGattDescriptor.java
+++ b/java/direct_bt/tinyb/DBTGattDescriptor.java
@@ -167,5 +167,5 @@ public class DBTGattDescriptor extends DBTObject implements BluetoothGattDescrip
private native boolean writeValueImpl(byte[] argValue) throws BluetoothException;
@Override
- protected native void deleteImpl();
+ protected native void deleteImpl(long nativeInstance);
}
diff --git a/java/direct_bt/tinyb/DBTGattService.java b/java/direct_bt/tinyb/DBTGattService.java
index 3bdb45a8..98081e25 100644
--- a/java/direct_bt/tinyb/DBTGattService.java
+++ b/java/direct_bt/tinyb/DBTGattService.java
@@ -131,5 +131,5 @@ public class DBTGattService extends DBTObject implements BluetoothGattService
private native List<BluetoothGattCharacteristic> getCharacteristicsImpl();
@Override
- protected native void deleteImpl();
+ protected native void deleteImpl(long nativeInstance);
}
diff --git a/java/direct_bt/tinyb/DBTManager.java b/java/direct_bt/tinyb/DBTManager.java
index c74f0706..263b7365 100644
--- a/java/direct_bt/tinyb/DBTManager.java
+++ b/java/direct_bt/tinyb/DBTManager.java
@@ -43,6 +43,7 @@ import org.tinyb.BluetoothType;
public class DBTManager implements BluetoothManager
{
protected static final boolean DEBUG = BluetoothFactory.DEBUG;
+ protected static final boolean VERBOSE = BluetoothFactory.VERBOSE;
private static volatile boolean isJVMShuttingDown = false;
private static final List<Runnable> userShutdownHooks = new ArrayList<Runnable>();
@@ -269,7 +270,7 @@ public class DBTManager implements BluetoothManager
private native List<BluetoothAdapter> getAdapterListImpl();
private native void initImpl(final boolean unifyUUID128Bit) throws BluetoothException;
- private native void deleteImpl();
+ private native void deleteImpl(long nativeInstance);
private DBTManager()
{
initImpl(unifyUUID128Bit);
@@ -304,7 +305,7 @@ public class DBTManager implements BluetoothManager
a.close();
}
adapters.clear();
- deleteImpl();
+ deleteImpl(nativeInstance);
}
}
diff --git a/java/direct_bt/tinyb/DBTNativeDownlink.java b/java/direct_bt/tinyb/DBTNativeDownlink.java
index d3535ce0..c45bdb23 100644
--- a/java/direct_bt/tinyb/DBTNativeDownlink.java
+++ b/java/direct_bt/tinyb/DBTNativeDownlink.java
@@ -25,12 +25,15 @@
package direct_bt.tinyb;
+import java.util.concurrent.atomic.AtomicBoolean;
+
import org.tinyb.BluetoothFactory;
public abstract class DBTNativeDownlink
{
- protected long nativeInstance;
- private boolean isValid;
+ private long nativeInstance;
+ private final AtomicBoolean isValid = new AtomicBoolean(false);
+ private final Object nativeLock = new Object();
static {
BluetoothFactory.checkInitialized();
@@ -39,11 +42,11 @@ public abstract class DBTNativeDownlink
protected DBTNativeDownlink(final long nativeInstance)
{
this.nativeInstance = nativeInstance;
- isValid = true;
+ isValid.set(true);
initNativeJavaObject(nativeInstance);
}
- protected final boolean isValid() { return isValid; }
+ protected final boolean isValid() { return isValid.get(); }
@Override
protected void finalize()
@@ -52,41 +55,62 @@ public abstract class DBTNativeDownlink
}
/**
- * Deletes the native instance in the following order
+ * Deletes the {@code nativeInstance} in the following order
* <ol>
- * <li>Removes this java reference from the native instance</li>
- * <li>Deletes the native instance via {@link #deleteImpl()}</li>
- * <li>Sets the nativeInstance := 0</li>
+ * <li>Removes this java reference from the {@code nativeInstance}</li>
+ * <li>Deletes the {@code nativeInstance} via {@link #deleteImpl(long)}</li>
+ * <li>Zeros the {@code nativeInstance} reference</li>
* </ol>
*/
- public synchronized void delete() {
- if (!isValid) {
- return;
+ public final void delete() {
+ synchronized (nativeLock) {
+ if( !isValid.compareAndSet(true, false) ) {
+ if( DBTManager.DEBUG ) {
+ System.err.println("JAVA: delete: !valid -> bail: "+getClass().getSimpleName());
+ }
+ return;
+ }
+ if( DBTManager.DEBUG ) {
+ System.err.println("JAVA: delete.0: "+getClass().getSimpleName()+": valid, handle 0x"+Long.toHexString(nativeInstance));
+ }
+ final long _nativeInstance = nativeInstance;
+ nativeInstance = 0;
+ deleteNativeJavaObject(_nativeInstance); // will issue notifyDeleted() itself!
+ deleteImpl(_nativeInstance);
+ if( DBTManager.DEBUG ) {
+ System.err.println("JAVA: delete.X: "+getClass().getSimpleName()+": handle 0x"+Long.toHexString(nativeInstance));
+ }
}
- isValid = false;
- deleteNativeJavaObject(nativeInstance);
- deleteImpl();
- nativeInstance = 0;
}
/**
* Called from native JavaUplink dtor -> JavaGlobalObj dtor,
* i.e. native instance destructed in native land.
*/
- private synchronized void notifyDeleted() {
- isValid = false;
- nativeInstance = 0;
- // System.err.println("***** notifyDeleted: "+getClass().getSimpleName()+": valid "+isValid+" -> false, handle 0x"+Long.toHexString(nativeInstance)+" -> null: "+toString());
+ private final void notifyDeleted() {
+ synchronized (nativeLock) {
+ final boolean _isValid = isValid.get();
+ final long _nativeInstance = nativeInstance;
+ isValid.set(false);
+ nativeInstance = 0;
+ if( DBTManager.DEBUG ) {
+ System.err.println("JAVA: delete.notifyDeleted: "+getClass().getSimpleName()+", was: valid "+_isValid+", handle 0x"+Long.toHexString(_nativeInstance)+": "+toString());
+ }
+ }
}
/**
* Deletes the native instance.
* <p>
- * Called via {@link #delete()} and at this point this java reference
- * has been removed from the native instance.
+ * Called via {@link #delete()} and at this point
+ * <ul>
+ * <li>this java reference has been removed from the native instance, i.e. {@code JavaUplink}'s {@code javaObjectRef = nullptr}</li>
+ * <li>the {@link #nativeInstance} reference has been zeroed, but passed as argument for this final native deletion task.</li>
+ * </ul>
* </p>
+ * @param nativeInstance copy of {@link #nativeInstance} reference, which has been already zeroed.
*/
- protected abstract void deleteImpl();
+ protected abstract void deleteImpl(long nativeInstance);
private native void initNativeJavaObject(final long nativeInstance);
private native void deleteNativeJavaObject(final long nativeInstance);