View Javadoc
1   /*
2    * Licensed to The Apereo Foundation under one or more contributor license
3    * agreements. See the NOTICE file distributed with this work for additional
4    * information regarding copyright ownership.
5    *
6    *
7    * The Apereo Foundation licenses this file to you under the Educational
8    * Community License, Version 2.0 (the "License"); you may not use this file
9    * except in compliance with the License. You may obtain a copy of the License
10   * at:
11   *
12   *   http://opensource.org/licenses/ecl2.txt
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
17   * License for the specific language governing permissions and limitations under
18   * the License.
19   *
20   */
21  
22  package org.opencastproject.util;
23  
24  import static org.opencastproject.util.data.Option.none;
25  import static org.opencastproject.util.data.Option.some;
26  
27  import org.opencastproject.util.data.Function0;
28  import org.opencastproject.util.data.Option;
29  
30  import java.util.concurrent.atomic.AtomicBoolean;
31  
32  /** Only one function application can be threaded through the needle eye at a time. */
33  public final class NeedleEye {
34    private final AtomicBoolean running = new AtomicBoolean(false);
35  
36    /**
37     * Apply function <code>f</code> only if no other thread currently applies a function using this needle eye. Please
38     * note that <code>f</code> must <em>not</em> return null, so please do not use
39     * {@link org.opencastproject.util.data.Effect0}.
40     * 
41     * @return the result of <code>f</code> or none if another function is currently being applied.
42     */
43    public <A> Option<A> apply(Function0<A> f) {
44      if (running.compareAndSet(false, true)) {
45        try {
46          return some(f.apply());
47        } finally {
48          running.set(false);
49        }
50      } else {
51        return none();
52      }
53    }
54  }