blob: 43c0ec5738f0da6c13f2662b04e2b9730f966065 [file] [log] [blame]
Marcel Offermansa962bc92009-11-21 17:59:33 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
Pierre De Ropf74a1162009-12-04 22:40:38 +000019package org.apache.felix.dm.impl;
Marcel Offermansa962bc92009-11-21 17:59:33 +000020
21import java.util.LinkedList;
22import java.util.NoSuchElementException;
23
24/**
25 * Allows you to enqueue tasks from multiple threads and then execute
26 * them on one thread sequentially. It assumes more than one thread will
27 * try to execute the tasks and it will make an effort to pick the first
28 * task that comes along whilst making sure subsequent tasks return
29 * without waiting.
30 *
31 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
32 */
33public final class SerialExecutor {
34 private final LinkedList m_workQueue = new LinkedList();
35 private Runnable m_active;
36
37 /**
38 * Enqueue a new task for later execution. This method is
39 * thread-safe, so multiple threads can contribute tasks.
40 *
41 * @param runnable the runnable containing the actual task
42 */
43 public synchronized void enqueue(final Runnable runnable) {
44 m_workQueue.addLast(new Runnable() {
45 public void run() {
46 try {
47 runnable.run();
48 }
49 finally {
50 scheduleNext();
51 }
52 }
53 });
54 }
55
56 /**
57 * Execute any pending tasks. This method is thread safe,
58 * so multiple threads can try to execute the pending
59 * tasks, but only the first will be used to actually do
60 * so. Other threads will return immediately.
61 */
62 public void execute() {
63 Runnable active;
64 synchronized (this) {
65 active = m_active;
66 }
67 if (active == null) {
68 scheduleNext();
69 }
70 }
71
72 private void scheduleNext() {
73 Runnable active;
74 synchronized (this) {
75 try {
76 m_active = (Runnable) m_workQueue.removeFirst();
77 }
78 catch (NoSuchElementException e) {
79 m_active = null;
80 }
81 active = m_active;
82 }
83 if (active != null) {
84 active.run();
85 }
86 }
87}