SingleRunningTask.java revision c50b6f685ba26a38b8110f6ca0115b12f84d643c
1/*
2 * Copyright (C) 2011 The Android Open Source Project
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
17package com.android.email;
18
19import android.util.Log;
20
21import java.util.concurrent.atomic.AtomicBoolean;
22
23/**
24 * Base class for a task that runs at most one instance at any given moment.
25 *
26 * Call {@link #run} to start the task.  If the task is already running on another thread, it'll do
27 * nothing.
28 */
29public abstract class SingleRunningTask<Param> {
30    private final AtomicBoolean mIsRunning = new AtomicBoolean(false);
31    private final String mLogTaskName;
32
33    public SingleRunningTask(String logTaskName) {
34        mLogTaskName = logTaskName;
35    }
36
37    /**
38     * Calls {@link #runInternal} if it's not running already.
39     */
40    public final void run(Param param) {
41        if (mIsRunning.compareAndSet(false, true)) {
42            Log.i(Email.LOG_TAG,  mLogTaskName + ": start");
43            try {
44                runInternal(param);
45            } finally {
46                Log.i(Email.LOG_TAG, mLogTaskName + ": done");
47                mIsRunning.set(false);
48            }
49        } else {
50            // Already running -- do nothing.
51            Log.i(Email.LOG_TAG, mLogTaskName + ": already running");
52        }
53    }
54
55    /**
56     * The actual task must be implemented by subclasses.
57     */
58    protected abstract void runInternal(Param param);
59
60    /* package */ boolean isRunningForTest() {
61        return mIsRunning.get();
62    }
63}
64