1 package ch.hslu.exercises.sw06.ex4;
2
3 import java.util.ArrayDeque;
4 import java.util.concurrent.Semaphore;
5 import java.util.concurrent.TimeUnit;
6
7
8
9
10
11
12
13 public final class BoundedBuffer<T> implements Buffer<T> {
14
15 private final ArrayDeque<T> queue;
16 private final Semaphore putSema;
17 private final Semaphore takeSema;
18
19
20
21
22
23
24 public BoundedBuffer(final int n) {
25 queue = new ArrayDeque<>(n);
26 putSema = new Semaphore(n);
27 takeSema = new Semaphore(0);
28 }
29
30 @Override
31 public void add(final T elem) throws InterruptedException {
32 putSema.acquire();
33 addSynchronized(elem);
34 }
35
36 @Override
37 public T remove() throws InterruptedException {
38 takeSema.acquire();
39 return removeSynchronized();
40 }
41
42 @Override
43 public boolean add(T elem, long millis) throws InterruptedException {
44 if (putSema.tryAcquire(millis, TimeUnit.MILLISECONDS)) {
45 addSynchronized(elem);
46 return true;
47 } else {
48 return false;
49 }
50 }
51
52 @Override
53 public T remove(long millis) throws InterruptedException {
54 if (takeSema.tryAcquire(millis, TimeUnit.MILLISECONDS)) {
55 return removeSynchronized();
56 } else {
57 return null;
58 }
59 }
60
61 public void addSynchronized(T elem) {
62 synchronized (queue) {
63 queue.addFirst(elem);
64 }
65 takeSema.release();
66 }
67
68 private T removeSynchronized() {
69 T elem;
70 synchronized (queue) {
71 elem = queue.removeLast();
72 }
73 putSema.release();
74 return elem;
75 }
76
77 @Override
78 public boolean empty() {
79 return takeSema.availablePermits() == 0;
80 }
81
82 @Override
83 public boolean full() {
84 return putSema.availablePermits() == 0;
85 }
86
87 @Override
88 public int size() {
89 return takeSema.availablePermits();
90 }
91 }