1 /**
2 * Copyright 2008 Atlassian Pty Ltd
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.atlassian.util.concurrent;
18
19 import net.jcip.annotations.ThreadSafe;
20
21 import java.lang.ref.WeakReference;
22 import java.util.Iterator;
23 import java.util.NoSuchElementException;
24 import java.util.Queue;
25 import java.util.concurrent.LinkedBlockingQueue;
26
27 /**
28 * Simple {@link Iterable} that holds {@link WeakReference weak references} to content elements. For
29 * convenience there are {@link #add(Object)} and {@link #isEmpty()} methods.
30 * <p>
31 * {@link Iterator Iterators} returned by this object maintain a hard reference to the next object.
32 * They are otherwise unstable as references may be garbage collected at any time
33 */
34 @ThreadSafe public class WeakIterable<E> implements Iterable<E> {
35 private final Queue<WeakReference<E>> queue = new LinkedBlockingQueue<WeakReference<E>>();
36
37 E add(final E e) {
38 queue.add(new WeakReference<E>(e));
39 return e;
40 }
41
42 boolean isEmpty() {
43 return !iterator().hasNext();
44 }
45
46 public Iterator<E> iterator() {
47 final Iterator<WeakReference<E>> iterator = queue.iterator();
48 return new Iterator<E>() {
49 E next = getNext();
50
51 public boolean hasNext() {
52 return next != null;
53 }
54
55 public E next() {
56 if (next == null) {
57 throw new NoSuchElementException();
58 }
59 try {
60 return next;
61 }
62 finally {
63 next = getNext();
64 }
65 }
66
67 public void remove() {
68 throw new UnsupportedOperationException();
69 }
70
71 E getNext() {
72 E result = null;
73 while (result == null) {
74 if (!iterator.hasNext()) {
75 return null;
76 }
77 final WeakReference<E> ref = iterator.next();
78 final E e = ref.get();
79 if (e == null) {
80 iterator.remove();
81 continue;
82 }
83 result = e;
84 }
85 return result;
86 }
87 };
88 }
89 }