jdk/src/jdk.snmp/share/classes/com/sun/jmx/snmp/tasks/ThreadService.java
changeset 25859 3317bb8137f4
parent 23010 6dadb192ad81
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.snmp/share/classes/com/sun/jmx/snmp/tasks/ThreadService.java	Sun Aug 17 15:54:13 2014 +0100
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.jmx.snmp.tasks;
+
+import java.util.ArrayList;
+import com.sun.jmx.snmp.tasks.Task;
+import com.sun.jmx.snmp.tasks.TaskServer;
+
+/**
+ * This class implements a {@link com.sun.jmx.snmp.tasks.TaskServer} over
+ * a thread pool.
+ * <p><b>This API is a Sun Microsystems internal API  and is subject
+ * to change without notice.</b></p>
+ **/
+public class ThreadService implements TaskServer {
+
+    public ThreadService(int threadNumber) {
+        if (threadNumber <= 0) {
+            throw new IllegalArgumentException("The thread number should bigger than zero.");
+        }
+
+        minThreads = threadNumber;
+        threadList = new ExecutorThread[threadNumber];
+
+        priority = Thread.currentThread().getPriority();
+        cloader = Thread.currentThread().getContextClassLoader();
+
+    }
+
+// public methods
+// --------------
+
+    /**
+     * Submit a task to be executed.
+     * Once a task is submitted, it is guaranteed that either
+     * {@link com.sun.jmx.snmp.tasks.Task#run() task.run()} or
+     * {@link com.sun.jmx.snmp.tasks.Task#cancel() task.cancel()} will be called.
+     * This implementation of TaskServer uses a thread pool to execute
+     * the submitted tasks.
+     * @param task The task to be executed.
+     * @exception IllegalArgumentException if the submitted task is null.
+     **/
+    public void submitTask(Task task) throws IllegalArgumentException {
+        submitTask((Runnable)task);
+    }
+
+    /**
+     * Submit a task to be executed.
+     * This implementation of TaskServer uses a thread pool to execute
+     * the submitted tasks.
+     * @param task The task to be executed.
+     * @exception IllegalArgumentException if the submitted task is null.
+     **/
+    public void submitTask(Runnable task) throws IllegalArgumentException {
+        stateCheck();
+
+        if (task == null) {
+            throw new IllegalArgumentException("No task specified.");
+        }
+
+        synchronized(jobList) {
+            jobList.add(jobList.size(), task);
+
+            jobList.notify();
+        }
+
+        createThread();
+    }
+
+    public Runnable removeTask(Runnable task) {
+        stateCheck();
+
+        Runnable removed = null;
+        synchronized(jobList) {
+            int lg = jobList.indexOf(task);
+            if (lg >= 0) {
+                removed = jobList.remove(lg);
+            }
+        }
+        if (removed != null && removed instanceof Task)
+            ((Task) removed).cancel();
+        return removed;
+    }
+
+    public void removeAll() {
+        stateCheck();
+
+        final Object[] jobs;
+        synchronized(jobList) {
+            jobs = jobList.toArray();
+            jobList.clear();
+        }
+        final int len = jobs.length;
+        for (int i=0; i<len ; i++) {
+            final Object o = jobs[i];
+            if (o!= null && o instanceof Task) ((Task)o).cancel();
+        }
+    }
+
+    // to terminate
+    public void terminate() {
+
+        if (terminated == true) {
+            return;
+        }
+
+        terminated = true;
+
+        synchronized(jobList) {
+            jobList.notifyAll();
+        }
+
+        removeAll();
+
+        for (int i=0; i<currThreds; i++) {
+            try {
+                threadList[i].interrupt();
+            } catch (Exception e) {
+                // TODO
+            }
+        }
+
+        threadList = null;
+    }
+
+// private classes
+// ---------------
+
+    // A thread used to execute jobs
+    //
+    private class ExecutorThread extends Thread {
+        public ExecutorThread() {
+            super(threadGroup, "ThreadService-"+counter++);
+            setDaemon(true);
+
+            // init
+            this.setPriority(priority);
+            this.setContextClassLoader(cloader);
+
+            idle++;
+        }
+
+        public void run() {
+
+            while(!terminated) {
+                Runnable job = null;
+
+                synchronized(jobList) {
+                    if (jobList.size() > 0) {
+                        job = jobList.remove(0);
+                        if (jobList.size() > 0) {
+                            jobList.notify();
+                        }
+
+                    } else {
+                        try {
+                            jobList.wait();
+                        } catch (InterruptedException ie) {
+                            // terminated ?
+                        } finally {
+                        }
+                        continue;
+                    }
+                }
+                if (job != null) {
+                    try {
+                        idle--;
+                        job.run();
+                    } catch (Exception e) {
+                        // TODO
+                        e.printStackTrace();
+                    } finally {
+                        idle++;
+                    }
+                }
+
+                // re-init
+                this.setPriority(priority);
+                Thread.interrupted();
+                this.setContextClassLoader(cloader);
+            }
+        }
+    }
+
+// private methods
+    private void stateCheck() throws IllegalStateException {
+        if (terminated) {
+            throw new IllegalStateException("The thread service has been terminated.");
+        }
+    }
+
+    private void createThread() {
+        if (idle < 1) {
+            synchronized(threadList) {
+                if (jobList.size() > 0 && currThreds < minThreads) {
+                    ExecutorThread et = new ExecutorThread();
+                    et.start();
+                    threadList[currThreds++] = et;
+                }
+            }
+        }
+    }
+
+
+// protected or private variables
+// ------------------------------
+    private ArrayList<Runnable> jobList = new ArrayList<Runnable>(0);
+
+    private ExecutorThread[] threadList;
+    private int minThreads = 1;
+    private int currThreds = 0;
+    private int idle = 0;
+
+    private boolean terminated = false;
+    private int priority;
+    private ThreadGroup threadGroup = new ThreadGroup("ThreadService");
+    private ClassLoader cloader;
+
+    private static long counter = 0;
+
+    private int addedJobs = 1;
+    private int doneJobs = 1;
+}