1 /*******************************************************************************
2 * Copyright (c) 2012 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.maps.pojo;
14 import java.awt.Image;
15 import java.util.LinkedList;
16 import java.util.List;
17 import java.util.concurrent.Executors;
18 import java.util.concurrent.ScheduledExecutorService;
19 import java.util.concurrent.TimeUnit;
20 import java.util.concurrent.atomic.AtomicInteger;
22 import org.simantics.maps.ProvisionException;
23 import org.simantics.maps.query.Query;
24 import org.simantics.maps.tile.IFilter;
25 import org.simantics.maps.tile.ITileProvider;
26 import org.simantics.maps.tile.TileKey;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
31 * @author Tuukka Lehtonen
34 public class TileJob implements Runnable {
36 private static final Logger LOGGER = LoggerFactory.getLogger(TileJob.class);
37 private static final AtomicInteger counter = new AtomicInteger();
39 private LinkedList<Query<TileKey, Image>> queue = new LinkedList<>();
40 private ScheduledExecutorService executor = Executors.newScheduledThreadPool(1, runnable -> {
41 Thread thread = new Thread(runnable, getClass().getSimpleName() + "-" + counter.getAndIncrement());
42 thread.setDaemon(true);
45 private ITileProvider provider;
50 public void setTileProvider(ITileProvider provider) {
51 this.provider = provider;
54 protected Image doQuery(TileKey key) throws ProvisionException {
55 return provider.get(key);
59 Query<TileKey, Image> job = pullNextJob();
63 Image result = doQuery(job.source);
64 job.listener.queryComplete(job, result);
65 } catch (Exception e) {
66 LOGGER.error("Querying failed for job {}", job, e);
67 job.listener.queryFailed(job, e);
72 } while (job != null);
75 protected synchronized int jobsLeft() {
79 protected synchronized Query<TileKey, Image> pullNextJob() {
82 return queue.removeFirst();
85 public synchronized void clear() {
86 @SuppressWarnings("unchecked")
87 Query<TileKey, Image> jobs[] = queue.toArray(new Query[queue.size()]);
88 for (Query<TileKey, Image> j : jobs)
92 public synchronized void addJob(Query<TileKey, Image> job) {
94 if (queue.size() == 1) {
95 executor.execute(this);
99 public synchronized void addAsFirstJob(Query<TileKey, Image> job) {
101 if (queue.size() == 1) {
102 executor.execute(this);
106 public synchronized boolean removeJob(Query<TileKey, Image> job) {
107 if (queue.remove(job)) {
108 job.listener.queryCanceled(job);
114 public synchronized void filterQueries(IFilter<TileKey> filter) {
118 LinkedList<Query<TileKey, Image>> result = new LinkedList<Query<TileKey, Image>>();
119 for (Query<TileKey, Image> query : queue) {
120 if (filter.select(query.source))
123 query.listener.queryCanceled(query);
128 public void dispose() {
131 if (!executor.awaitTermination(100, TimeUnit.MILLISECONDS)) {
132 // this should shutdown for good
133 List<Runnable> unfinished = executor.shutdownNow();
134 LOGGER.warn("TileJob did not terminate in time - left jobs {}", unfinished);
136 } catch (InterruptedException e) {