altoslib: Fix 8 to 12 bit conversion for Mega pyro voltage data
[fw/altos] / altoslib / AltosMapCache.java
1 /*
2  * Copyright © 2010 Anthony Towns <aj@erisian.com.au>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 package org.altusmetrum.altoslib_12;
20
21 import java.io.*;
22 import java.net.*;
23
24 public class AltosMapCache implements AltosMapCacheListener {
25
26         /* An entry in the MapCache */
27         class MapCacheElement implements AltosMapTileListener {
28
29                 AltosMapTile            tile;           /* Notify when image has been loaded */
30                 AltosImage              image;
31                 long                    used;
32
33                 class loader implements Runnable {
34                         public void run() {
35                                 if (image == null) {
36                                         try {
37                                                 image = map_interface.load_image(tile.store.file);
38                                         } catch (Exception ex) {
39                                         }
40                                 }
41                                 tile.notify_image(image);
42                         }
43                 }
44
45                 private void load() {
46                         loader  l = new loader();
47                         Thread  lt = new Thread(l);
48                         lt.start();
49                 }
50
51                 public void flush() {
52                         if (image != null) {
53                                 image.flush();
54                                 image = null;
55                         }
56                 }
57
58                 public boolean has_map() {
59                         return tile.status == AltosMapTile.loaded;
60                 }
61
62                 public synchronized void notify_tile(AltosMapTile tile, int status) {
63                         if (status == AltosMapTile.fetched) {
64                                 load();
65                         }
66                 }
67
68                 public MapCacheElement(AltosMapTile tile) {
69                         this.tile = tile;
70                         this.image = null;
71                         this.used = 0;
72                         tile.add_listener(this);
73                 }
74         }
75
76         int                     min_cache_size;         /* configured minimum cache size */
77         int                     cache_size;             /* current cache size */
78         int                     requested_cache_size;   /* cache size computed by application */
79
80         private Object          fetch_lock = new Object();
81         private Object          cache_lock = new Object();
82
83         AltosMapInterface       map_interface;
84
85         MapCacheElement[]       elements = new MapCacheElement[cache_size];
86
87         long                    used;
88
89         public void set_cache_size(int new_size) {
90
91                 requested_cache_size = new_size;
92
93                 if (new_size < min_cache_size)
94                         new_size = min_cache_size;
95
96                 if (new_size == cache_size)
97                         return;
98
99                 synchronized(cache_lock) {
100                         MapCacheElement[]       new_elements = new MapCacheElement[new_size];
101
102                         for (int i = 0; i < cache_size; i++) {
103                                 if (i < new_size)
104                                         new_elements[i] = elements[i];
105                                 else if (elements[i] != null)
106                                         elements[i].flush();
107                         }
108                         elements = new_elements;
109                         cache_size = new_size;
110                 }
111         }
112
113         public AltosImage get(AltosMapTile tile) {
114                 int             oldest = -1;
115                 long            age = used;
116
117                 synchronized(cache_lock) {
118                         MapCacheElement element = null;
119                         for (int i = 0; i < cache_size; i++) {
120                                 element = elements[i];
121
122                                 if (element == null) {
123                                         oldest = i;
124                                         break;
125                                 }
126                                 if (tile.store.equals(element.tile.store)) {
127                                         element.used = used++;
128                                         return element.image;
129                                 }
130                                 if (element.used < age) {
131                                         oldest = i;
132                                         age = element.used;
133                                 }
134                         }
135
136                         element = new MapCacheElement(tile);
137                         element.used = used++;
138                         if (elements[oldest] != null)
139                                 elements[oldest].flush();
140
141                         elements[oldest] = element;
142                         return element.image;
143                 }
144         }
145
146         public void map_cache_changed(int map_cache) {
147                 min_cache_size = map_cache;
148
149                 set_cache_size(requested_cache_size);
150         }
151
152         public void dispose() {
153                 AltosPreferences.unregister_map_cache_listener(this);
154
155                 for (int i = 0; i < cache_size; i++) {
156                         MapCacheElement element = elements[i];
157
158                         if (element != null)
159                             element.flush();
160                 }
161         }
162
163         public AltosMapCache(AltosMapInterface map_interface) {
164                 this.map_interface = map_interface;
165                 min_cache_size = AltosPreferences.map_cache();
166
167                 set_cache_size(0);
168
169                 AltosPreferences.register_map_cache_listener(this);
170         }
171 }