View Javadoc

1   /*
2    * Grapht, an open source dependency injector.
3    * Copyright 2014-2015 various contributors (see CONTRIBUTORS.txt)
4    * Copyright 2010-2014 Regents of the University of Minnesota
5    *
6    * This program is free software; you can redistribute it and/or modify
7    * it under the terms of the GNU Lesser General Public License as
8    * published by the Free Software Foundation; either version 2.1 of the
9    * License, or (at your option) any later version.
10   *
11   * This program is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13   * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14   * details.
15   *
16   * You should have received a copy of the GNU General Public License along with
17   * this program; if not, write to the Free Software Foundation, Inc., 51
18   * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19   */
20  package org.grouplens.grapht.util;
21  
22  import javax.annotation.Nonnull;
23  import javax.annotation.concurrent.ThreadSafe;
24  import javax.inject.Provider;
25  
26  /**
27   * MemoizingProvider is a Provider that enforces memoization or caching on
28   * another Provider that it wraps.
29   *
30   * @param <T>
31   * @author <a href="http://grouplens.org">GroupLens Research</a>
32   */
33  @ThreadSafe
34  public class MemoizingProvider<T> implements TypedProvider<T> {
35      private final Provider<T> wrapped;
36  
37      // We track a boolean because this supports providing null instances, in
38      // which case we can't just check against null to see if we've already
39      // queried the base provider
40      private volatile T cached;
41      private volatile boolean invoked;
42  
43      public MemoizingProvider(@Nonnull Provider<T> provider) {
44          Preconditions.notNull("provider", provider);
45          wrapped = provider;
46          cached = null;
47          invoked = false;
48      }
49  
50      @Override
51      public Class<?> getProvidedType() {
52          return Types.getProvidedType(wrapped);
53      }
54  
55      @Override
56      public T get() {
57          if (!invoked) {
58              synchronized (this) {
59                  if (!invoked) {
60                      cached = wrapped.get();
61                      invoked = true;
62                  }
63              }
64          }
65          return cached;
66      }
67  }