jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/Dispatch.java
changeset 36502 6183b00a9ce1
parent 36501 93915076a341
parent 36490 8454215d47f2
child 36503 4a95f4b1bd8b
equal deleted inserted replaced
36501:93915076a341 36502:6183b00a9ce1
     1 /*
       
     2  * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package com.apple.concurrent;
       
    27 
       
    28 import java.util.concurrent.*;
       
    29 
       
    30 /**
       
    31  * Factory for {@link Executor}s and {@link ExecutorService}s backed by
       
    32  * libdispatch.
       
    33  *
       
    34  * Access is controlled through the Dispatch.getInstance() method, because
       
    35  * performed tasks occur on threads owned by libdispatch. These threads are
       
    36  * not owned by any particular AppContext or have any specific context
       
    37  * classloader installed.
       
    38  *
       
    39  * @since Java for Mac OS X 10.6 Update 2
       
    40  */
       
    41 public final class Dispatch {
       
    42         /**
       
    43          * The priorities of the three default asynchronous queues.
       
    44          */
       
    45         public enum Priority {
       
    46                 LOW(-2), NORMAL(0), HIGH(2); // values from <dispatch/queue.h>
       
    47 
       
    48                 final int nativePriority;
       
    49                 Priority(final int nativePriority) { this.nativePriority = nativePriority; }
       
    50         };
       
    51 
       
    52         final static Dispatch instance = new Dispatch();
       
    53 
       
    54         /**
       
    55          * Factory method returns an instnace of Dispatch if supported by the
       
    56          * underlying operating system, and if the caller's security manager
       
    57          * permits "canInvokeInSystemThreadGroup".
       
    58          *
       
    59          * @return a factory instance of Dispatch, or null if not available
       
    60          */
       
    61         public static Dispatch getInstance() {
       
    62                 checkSecurity();
       
    63                 if (!LibDispatchNative.nativeIsDispatchSupported()) return null;
       
    64 
       
    65                 return instance;
       
    66         }
       
    67 
       
    68         private static void checkSecurity() {
       
    69         final SecurityManager security = System.getSecurityManager();
       
    70         if (security != null) security.checkPermission(new RuntimePermission("canInvokeInSystemThreadGroup"));
       
    71     }
       
    72 
       
    73         private Dispatch() { }
       
    74 
       
    75         /**
       
    76          * Creates an {@link Executor} that performs tasks asynchronously. The {@link Executor}
       
    77          * cannot be shutdown, and enqueued {@link Runnable}s cannot be canceled. Passing null
       
    78          * returns the {@link Priority.NORMAL} {@link Executor}.
       
    79          *
       
    80          * @param priority - the priority of the returned {@link Executor}
       
    81          * @return an asynchronous {@link Executor}
       
    82          */
       
    83         public Executor getAsyncExecutor(Priority priority) {
       
    84                 if (priority == null) priority = Priority.NORMAL;
       
    85                 final long nativeQueue = LibDispatchNative.nativeCreateConcurrentQueue(priority.nativePriority);
       
    86                 if (nativeQueue == 0L) return null;
       
    87                 return new LibDispatchConcurrentQueue(nativeQueue);
       
    88         }
       
    89 
       
    90         int queueIndex = 0;
       
    91         /**
       
    92          * Creates an {@link ExecutorService} that performs tasks synchronously in FIFO order.
       
    93          * Useful to protect a resource against concurrent modification, in lieu of a lock.
       
    94          * Passing null returns an {@link ExecutorService} with a uniquely labeled queue.
       
    95          *
       
    96          * @param label - a label to name the queue, shown in several debugging tools
       
    97          * @return a synchronous {@link ExecutorService}
       
    98          */
       
    99         public ExecutorService createSerialExecutor(String label) {
       
   100                 if (label == null) label = "";
       
   101                 if (label.length() > 256) label = label.substring(0, 256);
       
   102                 String queueName = "com.apple.java.concurrent.";
       
   103                 if ("".equals(label)) {
       
   104                         synchronized (this) {
       
   105                                 queueName += queueIndex++;
       
   106                         }
       
   107                 } else {
       
   108                         queueName += label;
       
   109                 }
       
   110 
       
   111                 final long nativeQueue = LibDispatchNative.nativeCreateSerialQueue(queueName);
       
   112                 if (nativeQueue == 0) return null;
       
   113                 return new LibDispatchSerialQueue(nativeQueue);
       
   114         }
       
   115 
       
   116         Executor nonBlockingMainQueue = null;
       
   117         /**
       
   118          * Returns an {@link Executor} that performs the provided Runnables on the main queue of the process.
       
   119          * Runnables submitted to this {@link Executor} will not run until the AWT is started or another native toolkit is running a CFRunLoop or NSRunLoop on the main thread.
       
   120          *
       
   121          * Submitting a Runnable to this {@link Executor} does not wait for the Runnable to complete.
       
   122          * @return an asynchronous {@link Executor} that is backed by the main queue
       
   123          */
       
   124         public synchronized Executor getNonBlockingMainQueueExecutor() {
       
   125                 if (nonBlockingMainQueue != null) return nonBlockingMainQueue;
       
   126                 return nonBlockingMainQueue = new LibDispatchMainQueue.ASync();
       
   127         }
       
   128 
       
   129         Executor blockingMainQueue = null;
       
   130         /**
       
   131          * Returns an {@link Executor} that performs the provided Runnables on the main queue of the process.
       
   132          * Runnables submitted to this {@link Executor} will not run until the AWT is started or another native toolkit is running a CFRunLoop or NSRunLoop on the main thread.
       
   133          *
       
   134          * Submitting a Runnable to this {@link Executor} will block until the Runnable has completed.
       
   135          * @return an {@link Executor} that is backed by the main queue
       
   136          */
       
   137         public synchronized Executor getBlockingMainQueueExecutor() {
       
   138                 if (blockingMainQueue != null) return blockingMainQueue;
       
   139                 return blockingMainQueue = new LibDispatchMainQueue.Sync();
       
   140         }
       
   141 }