diff options
author | Sven Gothel <[email protected]> | 2020-06-29 05:59:08 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2020-06-29 05:59:08 +0200 |
commit | 0b7e94850a0bb5e4d389709bc9c449cd4f7dc094 (patch) | |
tree | 852b5353ac669275145bbb5097692b8ce579df9a /java/direct_bt | |
parent | 809487569a0e521bd9a5850cfbee00c2ee524932 (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.java | 2 | ||||
-rw-r--r-- | java/direct_bt/tinyb/DBTDevice.java | 2 | ||||
-rw-r--r-- | java/direct_bt/tinyb/DBTGattCharacteristic.java | 2 | ||||
-rw-r--r-- | java/direct_bt/tinyb/DBTGattDescriptor.java | 2 | ||||
-rw-r--r-- | java/direct_bt/tinyb/DBTGattService.java | 2 | ||||
-rw-r--r-- | java/direct_bt/tinyb/DBTManager.java | 5 | ||||
-rw-r--r-- | java/direct_bt/tinyb/DBTNativeDownlink.java | 68 |
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); |