View Javadoc
1   /**
2    * Copyright (C) 2010-14 pvmanager developers. See COPYRIGHT.TXT
3    * All rights reserved. Use is subject to license terms. See LICENSE.TXT
4    */
5   package org.epics.pvmanager;
6   
7   import java.util.concurrent.Executor;
8   import java.util.concurrent.Executors;
9   import java.util.concurrent.ScheduledExecutorService;
10  import org.epics.pvmanager.expression.DesiredRateExpression;
11  import org.epics.pvmanager.expression.DesiredRateReadWriteExpression;
12  import org.epics.pvmanager.expression.SourceRateExpression;
13  import org.epics.pvmanager.expression.SourceRateReadWriteExpression;
14  import org.epics.pvmanager.expression.WriteExpression;
15  
16  /**
17   * Entry point for the library, manages the defaults and allows to create
18   * {@link PVReader}, {@link PVWriter} and {@link PV } from an read or write expression.
19   * <p>
20   * <b>NotificationExecutor</b> - This is used for all notifications.
21   * By default this uses {@link org.epics.pvmanager.util.Executors#localThread()} so that
22   * the notification are done on whatever current thread needs to notify.
23   * This means that new read notifications are run on threads managed by
24   * the ReadScannerExecutorService, write notifications are run on threads
25   * managed by the DataSource and exceptions notification are run on the thread
26   * where the exception is done. This can be changed to make all notifications
27   * routed to single threaded sub-systems, such as UI environments like SWING,
28   * SWT or similar. This can be changed on a PV by PV basis.
29   * <p>
30   * <b>AsynchWriteExecutor</b> - This is used for asynchronous writes, to return
31   * right away, and for running timeouts on each write.
32   * By default this uses the internal PVManager work pool. The work
33   * submitted here is the calculation of the corresponding {@link WriteExpression}
34   * and submission to the {@link DataSource}. The DataSource itself typically
35   * has asynchronous work, which is executed in the DataSource specific threads.
36   * Changing this to {@link org.epics.pvmanager.util.Executors#localThread()} will make that preparation
37   * task on the thread that calls {@link PVWriter#write(java.lang.Object) } but
38   * it will not transform the call in a synchronous call.
39   * <p>
40   * <b>ReadScannerExecutorService</b> - This is used to run the periodic
41   * scan for new values. By default this uses the internal PVManager work pool. The work
42   * submitted here is the calculation of the corresponding {@link DesiredRateExpression}
43   * and submission to the NotificationExecutor.
44   *
45   * @author carcassi
46   */
47  public class PVManager {
48  
49      private static volatile Executor defaultNotificationExecutor = org.epics.pvmanager.util.Executors.localThread();
50      private static volatile DataSource defaultDataSource = null;
51      private static final ScheduledExecutorService workerPool = Executors.newScheduledThreadPool(Math.max(1, Runtime.getRuntime().availableProcessors() - 1),
52              org.epics.pvmanager.util.Executors.namedPool("PVMgr Worker "));
53      private static ScheduledExecutorService readScannerExecutorService = workerPool;
54      private static ScheduledExecutorService asyncWriteExecutor = workerPool;
55  
56      /**
57       * Changes the default executor on which all notifications are going to be posted.
58       *
59       * @param notificationExecutor the new notification executor
60       */
61      public static void setDefaultNotificationExecutor(Executor notificationExecutor) {
62          defaultNotificationExecutor = notificationExecutor;
63      }
64  
65      /**
66       * Returns the current default executor that will execute all notifications.
67       * 
68       * @return the default executor
69       */
70      public static Executor getDefaultNotificationExecutor() {
71          return defaultNotificationExecutor;
72      }
73  
74      /**
75       * Changes the default source for data.
76       *
77       * @param dataSource the data source
78       */
79      public static void setDefaultDataSource(DataSource dataSource) {
80          PVManager.defaultDataSource = dataSource;
81      }
82  
83      /**
84       * Returns the current default data source.
85       * 
86       * @return a data source or null if it was not set
87       */
88      public static DataSource getDefaultDataSource() {
89          return defaultDataSource;
90      }
91  
92      /**
93       * Reads the given expression, and returns an object to configure the parameters
94       * for the read. At each notification it will return the latest value,
95       * even if more had been received from the last notification.
96       *
97       * @param <T> type of the read payload
98       * @param pvExpression the expression to read
99       * @return the read configuration
100      */
101     public static <T> PVReaderConfiguration<T> read(SourceRateExpression<T> pvExpression) {
102         return new PVReaderConfiguration<T>(ExpressionLanguage.latestValueOf(pvExpression));
103     }
104 
105     /**
106      * Reads the given expression, and returns an object to configure the parameters
107      * for the read.
108      *
109      * @param <T> type of the read payload
110      * @param pvExpression the expression to read
111      * @return the read configuration
112      */
113     public static <T> PVReaderConfiguration<T> read(DesiredRateExpression<T> pvExpression) {
114         return new PVReaderConfiguration<T>(pvExpression);
115     }
116     
117     /**
118      * Writes the given expression, and returns an object to configure the parameters
119      * for the write.
120      *
121      * @param <T> type of the write payload
122      * @param writeExpression the expression to write
123      * @return the write configuration
124      */
125     public static <T> PVWriterConfiguration<T> write(WriteExpression<T> writeExpression) {
126         return new PVWriterConfiguration<T>(writeExpression);
127     }
128     
129     /**
130      * Both reads and writes the given expression, and returns an object to configure the parameters
131      * for the both read and write. It's similar to use both {@link #read(org.epics.pvmanager.expression.SourceRateExpression) }
132      * and {@link #write(org.epics.pvmanager.expression.WriteExpression) } at the same time.
133      *
134      * @param <R> type of the read payload
135      * @param <W> type of the write payload
136      * @param readWriteExpression the expression to read and write
137      * @return the read and write configuration
138      */
139     public static <R, W> PVConfiguration<R, W> readAndWrite(SourceRateReadWriteExpression<R, W> readWriteExpression) {
140         return readAndWrite(ExpressionLanguage.latestValueOf(readWriteExpression));
141     }
142     
143     /**
144      * Both reads and writes the given expression, and returns an object to configure the parameters
145      * for the both read and write. It's similar to use both {@link #read(org.epics.pvmanager.expression.SourceRateExpression) }
146      * and {@link #write(org.epics.pvmanager.expression.WriteExpression) } at the same time.
147      *
148      * @param <R> type of the read payload
149      * @param <W> type of the write payload
150      * @param readWriteExpression the expression to read and write
151      * @return the read and write configuration
152      */
153     public static <R, W> PVConfiguration<R, W> readAndWrite(DesiredRateReadWriteExpression<R, W> readWriteExpression) {
154         return new PVConfiguration<R, W>(readWriteExpression);
155     }
156 
157     /**
158      * Returns the current executor on which the asynchronous calls are executed.
159      * 
160      * @return the current executor
161      */
162     public static ScheduledExecutorService getAsyncWriteExecutor() {
163         return asyncWriteExecutor;
164     }
165 
166     /**
167      * Changes the executor used for the asynchronous write calls.
168      * 
169      * @param asyncWriteExecutor the new executor
170      */
171     public static void setAsyncWriteExecutor(ScheduledExecutorService asyncWriteExecutor) {
172         PVManager.asyncWriteExecutor = asyncWriteExecutor;
173     }
174 
175     /**
176      * Returns the executor service used to schedule and run the 
177      * periodic reading scan for new values.
178      * 
179      * @return the service for the read operations
180      */
181     public static ScheduledExecutorService getReadScannerExecutorService() {
182         return readScannerExecutorService;
183     }
184 
185     /**
186      * Changes the executor service to use for executing the periodic read
187      * scan.
188      * 
189      * @param readScannerExecutorService  the new service for the read operations
190      */
191     public static void setReadScannerExecutorService(ScheduledExecutorService readScannerExecutorService) {
192         PVManager.readScannerExecutorService = readScannerExecutorService;
193     }
194     
195 }