From 809e46ccb199efe132162a69d442effb955c9e28 Mon Sep 17 00:00:00 2001 From: tpietzsch Date: Thu, 25 Apr 2024 12:05:46 +0200 Subject: [PATCH] Revise thread-safety logic --- .../blocks/FallbackPrimitiveBlocks.java | 12 +++++- .../net/imglib2/blocks/PrimitiveBlocks.java | 14 ++++--- .../imglib2/blocks/PrimitiveBlocksUtils.java | 28 +------------ .../imglib2/blocks/ViewPrimitiveBlocks.java | 42 ++++++++++++++++--- 4 files changed, 56 insertions(+), 40 deletions(-) diff --git a/src/main/java/net/imglib2/blocks/FallbackPrimitiveBlocks.java b/src/main/java/net/imglib2/blocks/FallbackPrimitiveBlocks.java index c517400f8..7354dee96 100644 --- a/src/main/java/net/imglib2/blocks/FallbackPrimitiveBlocks.java +++ b/src/main/java/net/imglib2/blocks/FallbackPrimitiveBlocks.java @@ -40,6 +40,7 @@ import net.imglib2.loops.LoopBuilder; import net.imglib2.type.NativeType; import net.imglib2.type.NativeTypeFactory; +import net.imglib2.util.Cast; import net.imglib2.util.Util; import net.imglib2.view.Views; @@ -66,8 +67,8 @@ public FallbackPrimitiveBlocks( final RandomAccessible< T > source, final T type if ( type.getEntitiesPerPixel().getRatio() != 1 ) throw new IllegalArgumentException( "Types with entitiesPerPixel != 1 are not supported" ); - nativeTypeFactory = ( NativeTypeFactory< T, A > ) type.getNativeTypeFactory(); - primitiveTypeProperties = ( PrimitiveTypeProperties< ?, A > ) PrimitiveTypeProperties.get( nativeTypeFactory.getPrimitiveType() ); + nativeTypeFactory = Cast.unchecked( type.getNativeTypeFactory() ); + primitiveTypeProperties = Cast.unchecked( PrimitiveTypeProperties.get( nativeTypeFactory.getPrimitiveType() ) ); } @Override @@ -85,6 +86,13 @@ public void copy( final long[] srcPos, final Object dest, final int[] size ) LoopBuilder.setImages( Views.interval( source, interval ), img ).forEachPixel( ( a, b ) -> b.set( a ) ); } + @Override + public PrimitiveBlocks< T > independentCopy() + { + // NB FallbackPrimitiveBlocks is stateless + return this; + } + @Override public PrimitiveBlocks< T > threadSafe() { diff --git a/src/main/java/net/imglib2/blocks/PrimitiveBlocks.java b/src/main/java/net/imglib2/blocks/PrimitiveBlocks.java index f7568c28b..9c1b96c48 100644 --- a/src/main/java/net/imglib2/blocks/PrimitiveBlocks.java +++ b/src/main/java/net/imglib2/blocks/PrimitiveBlocks.java @@ -33,13 +33,13 @@ */ package net.imglib2.blocks; +import static net.imglib2.blocks.PrimitiveBlocks.OnFallback.FAIL; +import static net.imglib2.blocks.PrimitiveBlocks.OnFallback.WARN; + import net.imglib2.RandomAccessible; import net.imglib2.type.NativeType; import net.imglib2.util.Util; -import static net.imglib2.blocks.PrimitiveBlocks.OnFallback.FAIL; -import static net.imglib2.blocks.PrimitiveBlocks.OnFallback.WARN; - /** * Copy blocks of data out of a {@code NativeType} source into primitive @@ -77,7 +77,7 @@ * If a source {@code RandomAccessible} cannot be understood, {@link * PrimitiveBlocks#of(RandomAccessible) PrimitiveBlocks.of} will return a * fall-back implementation (based on {@code LoopBuilder}). - * + *

* With the optional {@link OnFallback OnFallback} argument to {@link * PrimitiveBlocks#of(RandomAccessible, OnFallback) PrimitiveBlocks.of} it can * be configured, whether @@ -144,6 +144,8 @@ default void copy( int[] srcPos, Object dest, int[] size ) */ PrimitiveBlocks< T > threadSafe(); + PrimitiveBlocks< T > independentCopy(); + enum OnFallback { ACCEPT, @@ -197,11 +199,11 @@ static < T extends NativeType< T > > PrimitiveBlocks< T > of( * @return a {@code PrimitiveBlocks} accessor for {@code ra}. * @param pixel type */ - static < T extends NativeType< T >, R extends NativeType< R > > PrimitiveBlocks< T > of( + static < T extends NativeType< T > > PrimitiveBlocks< T > of( RandomAccessible< T > ra, OnFallback onFallback ) { - final ViewPropertiesOrError< T, R > props = ViewAnalyzer.getViewProperties( ra ); + final ViewPropertiesOrError< T, ? > props = ViewAnalyzer.getViewProperties( ra ); if ( props.isFullySupported() ) { return new ViewPrimitiveBlocks<>( props.getViewProperties() ); diff --git a/src/main/java/net/imglib2/blocks/PrimitiveBlocksUtils.java b/src/main/java/net/imglib2/blocks/PrimitiveBlocksUtils.java index 51fec5cd9..4d5a251ce 100644 --- a/src/main/java/net/imglib2/blocks/PrimitiveBlocksUtils.java +++ b/src/main/java/net/imglib2/blocks/PrimitiveBlocksUtils.java @@ -34,41 +34,15 @@ package net.imglib2.blocks; import java.util.Arrays; -import java.util.function.Supplier; + import net.imglib2.img.array.ArrayImg; import net.imglib2.img.array.ArrayImgFactory; import net.imglib2.img.basictypeaccess.array.ArrayDataAccess; import net.imglib2.transform.integer.MixedTransform; import net.imglib2.type.NativeType; -import net.imglib2.util.CloseableThreadLocal; class PrimitiveBlocksUtils { - static < T extends NativeType< T > > PrimitiveBlocks< T > threadSafe( final Supplier< PrimitiveBlocks< T > > supplier ) - { - final CloseableThreadLocal< PrimitiveBlocks< T > > tl = CloseableThreadLocal.withInitial( supplier ); - return new PrimitiveBlocks< T >() - { - @Override - public T getType() - { - return tl.get().getType(); - } - - @Override - public void copy( final long[] srcPos, final Object dest, final int[] size ) - { - tl.get().copy( srcPos, dest, size ); - } - - @Override - public PrimitiveBlocks< T > threadSafe() - { - return this; - } - }; - } - static < T extends NativeType< T > > Object extractOobValue( final T type, final Extension extension ) { if ( extension.type() == Extension.Type.CONSTANT ) diff --git a/src/main/java/net/imglib2/blocks/ViewPrimitiveBlocks.java b/src/main/java/net/imglib2/blocks/ViewPrimitiveBlocks.java index 4771da8fd..aa552dcf3 100644 --- a/src/main/java/net/imglib2/blocks/ViewPrimitiveBlocks.java +++ b/src/main/java/net/imglib2/blocks/ViewPrimitiveBlocks.java @@ -33,15 +33,17 @@ */ package net.imglib2.blocks; -import net.imglib2.img.basictypeaccess.nio.BufferAccess; +import static net.imglib2.blocks.PrimitiveBlocksUtils.extractOobValue; + +import java.util.function.Supplier; + import net.imglib2.transform.integer.MixedTransform; import net.imglib2.type.NativeType; import net.imglib2.type.PrimitiveType; import net.imglib2.util.Cast; +import net.imglib2.util.CloseableThreadLocal; import net.imglib2.util.Intervals; -import static net.imglib2.blocks.PrimitiveBlocksUtils.extractOobValue; - class ViewPrimitiveBlocks< T extends NativeType< T >, R extends NativeType< R > > implements PrimitiveBlocks< T > { private final ViewProperties< T, R > props; @@ -59,6 +61,8 @@ class ViewPrimitiveBlocks< T extends NativeType< T >, R extends NativeType< R > private final Convert convert; + private Supplier< PrimitiveBlocks< T > > threadSafeSupplier; + public ViewPrimitiveBlocks( final ViewProperties< T, R > props ) { this.props = props; @@ -157,10 +161,38 @@ else if ( doConvert ) @Override public PrimitiveBlocks< T > threadSafe() { - return PrimitiveBlocksUtils.threadSafe( this::newInstance ); + if ( threadSafeSupplier == null ) + threadSafeSupplier = CloseableThreadLocal.withInitial( this::independentCopy )::get; + return new PrimitiveBlocks< T >() + { + @Override + public T getType() + { + return props.getViewType(); + } + + @Override + public void copy( final long[] srcPos, final Object dest, final int[] size ) + { + threadSafeSupplier.get().copy( srcPos, dest, size ); + } + + @Override + public PrimitiveBlocks< T > independentCopy() + { + return ViewPrimitiveBlocks.this.independentCopy().threadSafe(); + } + + @Override + public PrimitiveBlocks< T > threadSafe() + { + return this; + } + }; } - ViewPrimitiveBlocks< T, R > newInstance() + @Override + public PrimitiveBlocks< T > independentCopy() { return new ViewPrimitiveBlocks<>( this ); }