changeset 788:03a74ce1bcc5

AsynchronousFileChannel completion handler may never be invoked when created with custom thread pool that supports only one thread (win only)
author alanb
date Sat, 25 Oct 2008 16:31:09 +0100
parents 1616d976e9da
children f4537b85a97a
files src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java test/java/nio/channels/AsynchronousFileChannel/Basic.java test/java/nio/channels/AsynchronousFileChannel/CustomThreadPool.java
diffstat 3 files changed, 45 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java	Sat Oct 25 13:35:19 2008 +0100
+++ b/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java	Sat Oct 25 16:31:09 2008 +0100
@@ -127,7 +127,7 @@
             throw new ProviderMismatchException();
         WindowsPath file = (WindowsPath)path;
         ThreadPool pool = (executor == null) ? null :
-            ThreadPool.create(ThreadPoolType.CACHED, executor, 1);
+            ThreadPool.create(ThreadPoolType.CACHED, executor, 0);
         WindowsSecurityDescriptor sd =
             WindowsSecurityDescriptor.fromAttribute(attrs);
         try {
--- a/test/java/nio/channels/AsynchronousFileChannel/Basic.java	Sat Oct 25 13:35:19 2008 +0100
+++ b/test/java/nio/channels/AsynchronousFileChannel/Basic.java	Sat Oct 25 16:31:09 2008 +0100
@@ -289,40 +289,50 @@
                  return t;
              }
         };
-        ExecutorService executor = Executors.newFixedThreadPool(2, threadFactory);
 
-        Set<StandardOpenOption> opts = EnumSet.of(WRITE);
-        AsynchronousFileChannel ch = AsynchronousFileChannel.open(file, opts, executor);
+        // exercise tests with varied number of threads
+        for (int nThreads=1; nThreads<=5; nThreads++) {
+            synchronized (threads) {
+                threads.clear();
+            }
+            ExecutorService executor = Executors.newFixedThreadPool(nThreads, threadFactory);
+            Set<StandardOpenOption> opts = EnumSet.of(WRITE);
+            AsynchronousFileChannel ch = AsynchronousFileChannel.open(file, opts, executor);
+            try {
+                for (int i=0; i<10; i++) {
+                    // do I/O operation to see which thread invokes the completion handler
+                    final AtomicReference<Thread> invoker = new AtomicReference<Thread>();
+                    final CountDownLatch latch = new CountDownLatch(1);
 
-        // do I/O operation to see which thread invokes the completion handler
-        final AtomicReference<Thread> invoker = new AtomicReference<Thread>();
-        final CountDownLatch latch = new CountDownLatch(1);
+                    ch.write(genBuffer(), 0L, null, new CompletionHandler<Integer,Void>() {
+                        public void completed(Integer result, Void att) {
+                            invoker.set(Thread.currentThread());
+                            latch.countDown();
+                        }
+                        public void failed(Throwable exc, Void att) {
+                        }
+                        public void cancelled(Void att) {
+                        }
+                    });
+                    await(latch);
 
-        ch.write(genBuffer(), 0L, null, new CompletionHandler<Integer,Void>() {
-            public void completed(Integer result, Void att) {
-                invoker.set(Thread.currentThread());
-                latch.countDown();
+                    // check invoker
+                    boolean found = false;
+                    synchronized (threads) {
+                        for (Thread t: threads) {
+                            if (t == invoker.get()) {
+                                found = true;
+                                break;
+                            }
+                        }
+                    }
+                    if (!found)
+                        throw new RuntimeException("Invoker thread not found");
+                }
+            } finally {
+                ch.close();
             }
-            public void failed(Throwable exc, Void att) {
-            }
-            public void cancelled(Void att) {
-            }
-        });
-        await(latch);
-
-        // check invoker
-        if (invoker.get() != Thread.currentThread()) {
-            boolean found = false;
-            for (Thread t: threads) {
-                if (t == invoker.get()) {
-                    found = true;
-                    break;
-                }
-            }
-            if (!found)
-                throw new RuntimeException("Invoker thread not found");
         }
-        ch.close();
     }
 
     // exercise asynchronous close
@@ -414,7 +424,8 @@
                 throw new RuntimeException("isCancelled not consistent");
             try {
                 res.get();
-                throw new RuntimeException("CancellationException expected");
+                if (!cancelled)
+                    throw new RuntimeException("CancellationException expected");
             } catch (CancellationException x) {
                 // expected
             } catch (ExecutionException x) {
--- a/test/java/nio/channels/AsynchronousFileChannel/CustomThreadPool.java	Sat Oct 25 13:35:19 2008 +0100
+++ b/test/java/nio/channels/AsynchronousFileChannel/CustomThreadPool.java	Sat Oct 25 16:31:09 2008 +0100
@@ -60,11 +60,8 @@
         }
         ch.close();
 
-        // if completion handler not invoked by initiator thread then check
-        // invoker by thread created by custom ThreadFactory
-        if (t != Thread.currentThread()) {
-            if (!MyThreadFactory.created(t))
-                throw new RuntimeException("Handler invoked by unknown thread");
-        }
+        // check handler was run by known thread
+        if (!MyThreadFactory.created(t))
+            throw new RuntimeException("Handler invoked by unknown thread");
     }
 }