1bb5cb5fa3d9e4ac18f4b4c9adaf237b804a09c56Paul Rohde/*
2bb5cb5fa3d9e4ac18f4b4c9adaf237b804a09c56Paul Rohde * Copyright (C) 2015 The Android Open Source Project
3bb5cb5fa3d9e4ac18f4b4c9adaf237b804a09c56Paul Rohde *
4bb5cb5fa3d9e4ac18f4b4c9adaf237b804a09c56Paul Rohde * Licensed under the Apache License, Version 2.0 (the "License");
5bb5cb5fa3d9e4ac18f4b4c9adaf237b804a09c56Paul Rohde * you may not use this file except in compliance with the License.
6bb5cb5fa3d9e4ac18f4b4c9adaf237b804a09c56Paul Rohde * You may obtain a copy of the License at
7bb5cb5fa3d9e4ac18f4b4c9adaf237b804a09c56Paul Rohde *
8bb5cb5fa3d9e4ac18f4b4c9adaf237b804a09c56Paul Rohde *      http://www.apache.org/licenses/LICENSE-2.0
9bb5cb5fa3d9e4ac18f4b4c9adaf237b804a09c56Paul Rohde *
10bb5cb5fa3d9e4ac18f4b4c9adaf237b804a09c56Paul Rohde * Unless required by applicable law or agreed to in writing, software
11bb5cb5fa3d9e4ac18f4b4c9adaf237b804a09c56Paul Rohde * distributed under the License is distributed on an "AS IS" BASIS,
12bb5cb5fa3d9e4ac18f4b4c9adaf237b804a09c56Paul Rohde * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bb5cb5fa3d9e4ac18f4b4c9adaf237b804a09c56Paul Rohde * See the License for the specific language governing permissions and
14bb5cb5fa3d9e4ac18f4b4c9adaf237b804a09c56Paul Rohde * limitations under the License.
15bb5cb5fa3d9e4ac18f4b4c9adaf237b804a09c56Paul Rohde */
16bb5cb5fa3d9e4ac18f4b4c9adaf237b804a09c56Paul Rohde
17b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohdepackage com.android.camera.device;
18b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde
19b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohdeimport com.android.camera.async.Lifetime;
20b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohdeimport com.android.camera.async.SafeCloseable;
21b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohdeimport com.google.common.util.concurrent.ListenableFuture;
22b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohdeimport com.google.common.util.concurrent.SettableFuture;
23b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde
24b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohdeimport java.util.concurrent.atomic.AtomicBoolean;
25b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde
26b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohdeimport javax.annotation.concurrent.ThreadSafe;
27b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde
28b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde/**
29b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde * ThreadSafe class to deal with the combined future and lifetime
30b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde * for a single device request.
31b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde */
32b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde@ThreadSafe
33b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohdepublic class SingleDeviceRequest<TDevice> implements SafeCloseable {
34b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde    private final SettableFuture<TDevice> mFuture;
35b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde    private final Lifetime mLifetime;
36b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde    private final AtomicBoolean mIsClosed;
37b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde
38b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde    public SingleDeviceRequest(Lifetime lifetime) {
39b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde        mLifetime = lifetime;
40b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde        mFuture = SettableFuture.create();
41b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde        mIsClosed = new AtomicBoolean(false);
42b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde    }
43b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde
44b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde    /**
45b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde     * Return the future instance for this request.
46b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde     */
47b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde    public ListenableFuture<TDevice> getFuture() {
48b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde        return mFuture;
49b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde    }
50b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde
51b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde    /**
52b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde     * Return the lifetime instance for this request.
53b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde     */
54b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde    public Lifetime getLifetime() {
55b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde        return mLifetime;
56b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde    }
57b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde
58b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde    /**
59b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde     * If the future has not been set, set the value.
60b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde     */
61b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde    public boolean set(TDevice device) {
62b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde        if (!mIsClosed.get()) {
63b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde            return mFuture.set(device);
64b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde        } else {
65b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde            return false;
66b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde        }
67b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde    }
68b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde
69b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde    public boolean isClosed() {
70b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde        return mIsClosed.get();
71b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde    }
72b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde
73b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde    public void closeWithException(Throwable throwable) {
74b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde        if (!mIsClosed.getAndSet(true)) {
75b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde            mFuture.setException(throwable);
76b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde            mLifetime.close();
77b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde        }
78b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde    }
79b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde
80b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde    @Override
81b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde    public void close() {
82b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde        if (!mIsClosed.getAndSet(true)) {
83b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde            mFuture.cancel(true /* mayInterruptIfRunning */);
84b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde            mLifetime.close();
85b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde        }
86b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde    }
87b6a4d96a310a1dee22ddea89b09130bcda206bb3Paul Rohde}
88