112f608f3d2089439a108788a1908941eea4277b9Puneet Lall/* 212f608f3d2089439a108788a1908941eea4277b9Puneet Lall * Copyright (C) 2014 The Android Open Source Project 312f608f3d2089439a108788a1908941eea4277b9Puneet Lall * 412f608f3d2089439a108788a1908941eea4277b9Puneet Lall * Licensed under the Apache License, Version 2.0 (the "License"); 512f608f3d2089439a108788a1908941eea4277b9Puneet Lall * you may not use this file except in compliance with the License. 612f608f3d2089439a108788a1908941eea4277b9Puneet Lall * You may obtain a copy of the License at 712f608f3d2089439a108788a1908941eea4277b9Puneet Lall * 812f608f3d2089439a108788a1908941eea4277b9Puneet Lall * http://www.apache.org/licenses/LICENSE-2.0 912f608f3d2089439a108788a1908941eea4277b9Puneet Lall * 1012f608f3d2089439a108788a1908941eea4277b9Puneet Lall * Unless required by applicable law or agreed to in writing, software 1112f608f3d2089439a108788a1908941eea4277b9Puneet Lall * distributed under the License is distributed on an "AS IS" BASIS, 1212f608f3d2089439a108788a1908941eea4277b9Puneet Lall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1312f608f3d2089439a108788a1908941eea4277b9Puneet Lall * See the License for the specific language governing permissions and 1412f608f3d2089439a108788a1908941eea4277b9Puneet Lall * limitations under the License. 1512f608f3d2089439a108788a1908941eea4277b9Puneet Lall */ 1612f608f3d2089439a108788a1908941eea4277b9Puneet Lall 1712f608f3d2089439a108788a1908941eea4277b9Puneet Lallpackage com.android.camera.async; 1812f608f3d2089439a108788a1908941eea4277b9Puneet Lall 1912f608f3d2089439a108788a1908941eea4277b9Puneet Lallimport java.util.ArrayList; 2012f608f3d2089439a108788a1908941eea4277b9Puneet Lallimport java.util.HashSet; 2112f608f3d2089439a108788a1908941eea4277b9Puneet Lallimport java.util.List; 2212f608f3d2089439a108788a1908941eea4277b9Puneet Lallimport java.util.Set; 2312f608f3d2089439a108788a1908941eea4277b9Puneet Lall 2412f608f3d2089439a108788a1908941eea4277b9Puneet Lall/** 2512f608f3d2089439a108788a1908941eea4277b9Puneet Lall * Enables handling the shut-down of components in a structured way. 2612f608f3d2089439a108788a1908941eea4277b9Puneet Lall * <p> 2712f608f3d2089439a108788a1908941eea4277b9Puneet Lall * Lifetimes are nestable sets of {@link SafeCloseable}s useful for guaranteeing 2812f608f3d2089439a108788a1908941eea4277b9Puneet Lall * that resources, such as threads, files, hardware devices, etc., are properly 2912f608f3d2089439a108788a1908941eea4277b9Puneet Lall * closed when necessary. 3012f608f3d2089439a108788a1908941eea4277b9Puneet Lall * <p> 3112f608f3d2089439a108788a1908941eea4277b9Puneet Lall * Child lifetimes are closed when their parent is closed, or when they are 3212f608f3d2089439a108788a1908941eea4277b9Puneet Lall * closed directly, whichever comes first. Objects added to a particular 3312f608f3d2089439a108788a1908941eea4277b9Puneet Lall * lifetime will only ever be closed once by that lifetime. 3412f608f3d2089439a108788a1908941eea4277b9Puneet Lall * </p> 3512f608f3d2089439a108788a1908941eea4277b9Puneet Lall */ 3612f608f3d2089439a108788a1908941eea4277b9Puneet Lallpublic class Lifetime implements SafeCloseable { 3712f608f3d2089439a108788a1908941eea4277b9Puneet Lall /** 3812f608f3d2089439a108788a1908941eea4277b9Puneet Lall * The parent, or null if there is no parent lifetime. 3912f608f3d2089439a108788a1908941eea4277b9Puneet Lall */ 4012f608f3d2089439a108788a1908941eea4277b9Puneet Lall private final Lifetime mParent; 4112f608f3d2089439a108788a1908941eea4277b9Puneet Lall private final Object mLock; 4212f608f3d2089439a108788a1908941eea4277b9Puneet Lall private final Set<SafeCloseable> mCloseables; 4312f608f3d2089439a108788a1908941eea4277b9Puneet Lall private boolean mClosed; 4412f608f3d2089439a108788a1908941eea4277b9Puneet Lall 4512f608f3d2089439a108788a1908941eea4277b9Puneet Lall public Lifetime() { 4612f608f3d2089439a108788a1908941eea4277b9Puneet Lall mLock = new Object(); 4712f608f3d2089439a108788a1908941eea4277b9Puneet Lall mCloseables = new HashSet<SafeCloseable>(); 4812f608f3d2089439a108788a1908941eea4277b9Puneet Lall mParent = null; 4912f608f3d2089439a108788a1908941eea4277b9Puneet Lall mClosed = false; 5012f608f3d2089439a108788a1908941eea4277b9Puneet Lall } 5112f608f3d2089439a108788a1908941eea4277b9Puneet Lall 5212f608f3d2089439a108788a1908941eea4277b9Puneet Lall public Lifetime(Lifetime parent) { 5312f608f3d2089439a108788a1908941eea4277b9Puneet Lall mLock = new Object(); 5412f608f3d2089439a108788a1908941eea4277b9Puneet Lall mCloseables = new HashSet<SafeCloseable>(); 5512f608f3d2089439a108788a1908941eea4277b9Puneet Lall mParent = parent; 5612f608f3d2089439a108788a1908941eea4277b9Puneet Lall mClosed = false; 5712f608f3d2089439a108788a1908941eea4277b9Puneet Lall parent.mCloseables.add(this); 5812f608f3d2089439a108788a1908941eea4277b9Puneet Lall } 5912f608f3d2089439a108788a1908941eea4277b9Puneet Lall 6012f608f3d2089439a108788a1908941eea4277b9Puneet Lall /** 6112f608f3d2089439a108788a1908941eea4277b9Puneet Lall * Adds the given object to this lifetime and returns it. 6212f608f3d2089439a108788a1908941eea4277b9Puneet Lall */ 6312f608f3d2089439a108788a1908941eea4277b9Puneet Lall public <T extends SafeCloseable> T add(T closeable) { 6412f608f3d2089439a108788a1908941eea4277b9Puneet Lall boolean needToClose = false; 6512f608f3d2089439a108788a1908941eea4277b9Puneet Lall synchronized (mLock) { 6612f608f3d2089439a108788a1908941eea4277b9Puneet Lall if (mClosed) { 6712f608f3d2089439a108788a1908941eea4277b9Puneet Lall needToClose = true; 6812f608f3d2089439a108788a1908941eea4277b9Puneet Lall } else { 6912f608f3d2089439a108788a1908941eea4277b9Puneet Lall mCloseables.add(closeable); 7012f608f3d2089439a108788a1908941eea4277b9Puneet Lall } 7112f608f3d2089439a108788a1908941eea4277b9Puneet Lall } 7212f608f3d2089439a108788a1908941eea4277b9Puneet Lall if (needToClose) { 7312f608f3d2089439a108788a1908941eea4277b9Puneet Lall closeable.close(); 7412f608f3d2089439a108788a1908941eea4277b9Puneet Lall } 7512f608f3d2089439a108788a1908941eea4277b9Puneet Lall return closeable; 7612f608f3d2089439a108788a1908941eea4277b9Puneet Lall } 7712f608f3d2089439a108788a1908941eea4277b9Puneet Lall 7812f608f3d2089439a108788a1908941eea4277b9Puneet Lall @Override 7912f608f3d2089439a108788a1908941eea4277b9Puneet Lall public void close() { 8012f608f3d2089439a108788a1908941eea4277b9Puneet Lall List<SafeCloseable> toClose = new ArrayList<SafeCloseable>(); 8112f608f3d2089439a108788a1908941eea4277b9Puneet Lall synchronized (mLock) { 8212f608f3d2089439a108788a1908941eea4277b9Puneet Lall if (mClosed) { 8312f608f3d2089439a108788a1908941eea4277b9Puneet Lall return; 8412f608f3d2089439a108788a1908941eea4277b9Puneet Lall } 8512f608f3d2089439a108788a1908941eea4277b9Puneet Lall mClosed = true; 8612f608f3d2089439a108788a1908941eea4277b9Puneet Lall // Remove from parent to avoid leaking memory if a long-lasting 8712f608f3d2089439a108788a1908941eea4277b9Puneet Lall // lifetime has lots of shorter-lived lifetimes created and 8812f608f3d2089439a108788a1908941eea4277b9Puneet Lall // destroyed repeatedly. 8912f608f3d2089439a108788a1908941eea4277b9Puneet Lall if (mParent != null) { 9012f608f3d2089439a108788a1908941eea4277b9Puneet Lall mParent.mCloseables.remove(this); 9112f608f3d2089439a108788a1908941eea4277b9Puneet Lall } 9212f608f3d2089439a108788a1908941eea4277b9Puneet Lall toClose.addAll(mCloseables); 9312f608f3d2089439a108788a1908941eea4277b9Puneet Lall mCloseables.clear(); 9412f608f3d2089439a108788a1908941eea4277b9Puneet Lall } 9512f608f3d2089439a108788a1908941eea4277b9Puneet Lall // Invoke close() outside the critical section 9612f608f3d2089439a108788a1908941eea4277b9Puneet Lall for (SafeCloseable closeable : toClose) { 9712f608f3d2089439a108788a1908941eea4277b9Puneet Lall closeable.close(); 9812f608f3d2089439a108788a1908941eea4277b9Puneet Lall } 9912f608f3d2089439a108788a1908941eea4277b9Puneet Lall } 10012f608f3d2089439a108788a1908941eea4277b9Puneet Lall} 101