KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jonathan > libs > resources > JChunkFactory


1 /***
2  * Jonathan: an Open Distributed Processing Environment
3  * Copyright (C) 1999-2000 France Telecom R&D
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Release: 3.0
20  *
21  * Contact: jonathan@objectweb.org
22  *
23  * Author: Bruno Dumant
24  *
25  */

26
27
28 package org.objectweb.jonathan.libs.resources;
29
30 import org.objectweb.jonathan.apis.resources.Chunk;
31 import org.objectweb.jonathan.apis.resources.ChunkFactory;
32
33 import org.objectweb.util.monolog.api.BasicLevel;
34
35 /**
36  * A Chunk Factory implementation.
37  * <p>
38  * A chunk factory creates and manages chunks. This chunk factory manages two
39  * pools of chunks of different sizes, so that a released chunk may be reused
40  * in a different context, saving the time for allocating and collecting the
41  * associated memory. The sizes of the chunks used, and of the preallocated
42  * pools may be changed.
43  */

44 public class JChunkFactory implements ChunkFactory {
45
46    /** a pool of chunks. */
47    BigPoolChunk[] big_pool;
48
49    /** Number of chunks in the big pool. */
50    int big_pool_size;
51
52    /** index of first free chunk */
53    int big_free;
54
55    /** Size of chunks in the big pool. */
56    int big_size;
57
58    /** a pool of chunks. */
59    SmallPoolChunk[] small_pool;
60
61    /** Number of chunks in the small pool. */
62    int small_pool_size;
63
64    /** index of first free small chunk */
65    int small_free;
66
67    /** Size of chunks in the small pool. */
68    int small_size;
69
70    /**
71     * Indicates whether warning message should be printed to stderr.
72     * <p>
73     * In particular, if verbose is true, and if all the chunks in a pool are used,
74     * a warning will be emitted. This may be useful to tune the pool sizes.
75     * <p>
76     * This value is defined under the name "/jonathan/JChunkFactory/verbose"
77     * in the {@link org.objectweb.jonathan.apis.kernel.Kernel#newConfiguration(Class)
78     * bootstrap context}.
79
80     */

81    public boolean verbose;
82
83    /**
84     * Returns a new chunk factory
85     */

86    public JChunkFactory() {
87       this(5,32768,10,8192,false);
88    }
89
90    /**
91     * Returns a new chunk factory
92     * @param big_pool_size size of the big chunks pool
93     * @param big_size size of the big chunks
94     * @param small_pool_size size of the small chunks pool
95     * @param small_size size of the small chunks
96     * @param verbose indicates whether warning messages should be printed to
97     * stderr.
98     * @see verbose
99     *
100     */

101    public JChunkFactory(int big_pool_size,int big_size,
102                         int small_pool_size, int small_size,
103                         boolean verbose) {
104       this.big_pool_size = big_pool_size;
105       this.big_size = big_size;
106       this.small_pool_size = small_pool_size;
107       this.small_size = small_size;
108       this.verbose = verbose;
109
110       big_free = big_pool_size;
111       big_pool = new BigPoolChunk[big_free];
112       for (int i = 0; i < big_free; i++) {
113          big_pool[i] = new BigPoolChunk();
114       }
115       small_free = small_pool_size;
116       small_pool = new SmallPoolChunk[small_free];
117       for (int i = 0; i < small_free; i++) {
118          small_pool[i] = new SmallPoolChunk();
119       }
120    }
121
122    /**
123     * Returns a chunk of a default (small) size.
124     *
125     * @return a chunk
126     */

127    public Chunk newChunk() {
128       synchronized(small_pool) {
129          PoolChunk chunk = null;
130          if (small_free > 0) {
131             chunk = small_pool[--small_free];
132             small_pool[small_free] = null;
133          } else {
134             // begin log
135
if ((LoggerProvider.logger != null)
136                 &&(LoggerProvider.logger.isLoggable(BasicLevel.INFO))) {
137                LoggerProvider.logger.log(BasicLevel.INFO,"Allocating chunk outside small pool");
138             }
139             // end log
140
chunk = new SmallPoolChunk();
141          }
142          return chunk;
143       }
144    }
145
146    /**
147     * Returns a chunk of (at least) the specified size.
148     * <p>
149     * This method may return a larger chunk than expected.
150     *
151     * @param size the expected size of the chunk.
152     * @return a chunk
153     */

154    public Chunk newChunk(int size) {
155       if (size <= small_size) {
156          return newSmallChunk();
157       } else if (size <= big_size) {
158          return newBigChunk();
159       } else {
160          // begin log
161
if ((LoggerProvider.logger != null)
162              &&(LoggerProvider.logger.isLoggable(BasicLevel.INFO))) {
163             LoggerProvider.logger.log(BasicLevel.INFO,"Chunk of size " + size + " requested.");
164          }
165          // end log
166
Chunk c = new Chunk(new byte[size],0,0);
167          //System.out.println("Non pool Chunk " + c + " returned.");
168
return c;
169       }
170    }
171
172
173    /**
174     * @return a big chunk
175     */

176    Chunk newBigChunk() {
177       synchronized(big_pool) {
178          BigPoolChunk chunk = null;
179          if (big_free > 0) {
180             chunk = big_pool[--big_free];
181             big_pool[big_free] = null;
182          } else {
183             // begin log
184
if ((LoggerProvider.logger != null)
185                 &&(LoggerProvider.logger.isLoggable(BasicLevel.INFO))) {
186                LoggerProvider.logger.log(BasicLevel.INFO,"Allocating chunk outside big pool");
187             }
188             // end log
189
// if (verbose) {
190
// System.err.println("Allocating chunk outside big pool");
191
// }
192
chunk = new BigPoolChunk();
193          }
194          return chunk;
195       }
196    }
197
198    /**
199     * @return a small chunk
200     */

201    Chunk newSmallChunk() {
202       synchronized(small_pool) {
203          SmallPoolChunk chunk = null;
204          if (small_free > 0) {
205             chunk = small_pool[--small_free];
206             small_pool[small_free] = null;
207          } else {
208             // if (verbose) {
209
// System.err.println("Allocating chunk outside small pool");
210
// }
211
// begin log
212
if ((LoggerProvider.logger != null)
213                 &&(LoggerProvider.logger.isLoggable(BasicLevel.INFO))) {
214                LoggerProvider.logger.log(BasicLevel.INFO,"Allocating chunk outside small pool");
215             }
216             // end log
217
chunk = new SmallPoolChunk();
218          }
219          return chunk;
220       }
221    }
222
223
224    /**
225     * Adds a chunk to the big pool.
226     *
227     * @param resource the chunk that must be added.
228     */

229    void addToBigPool(BigPoolChunk resource) {
230       synchronized(big_pool) {
231          if (big_free < big_pool.length) {
232             big_pool[big_free++] = resource;
233          }
234       }
235    }
236
237    /**
238     * Adds a chunk to the small pool.
239     *
240     * @param resource the chunk that must be added.
241     */

242    void addToSmallPool(SmallPoolChunk resource) {
243       synchronized(small_pool) {
244          if (small_free < small_pool.length) {
245             small_pool[small_free++] = resource;
246          }
247       }
248    }
249
250    /** Extension of Chunk as a controlled resource. */
251    static class PoolChunk extends Chunk {
252       /** count of acquired references to the associated chunk. */
253       protected int acquired;
254
255       PoolChunk(int size) {
256          super(new byte[size],0,0);
257          acquired = 1;
258       }
259
260       public Chunk duplicate() {
261          return new Duplicate(this,offset,top);
262       }
263
264       public Chunk duplicate(int offset, int top) {
265          return new Duplicate(this,offset,top);
266       }
267
268       synchronized void acquire() {
269          acquired++;
270       }
271    }
272
273    final class SmallPoolChunk extends PoolChunk {
274
275       SmallPoolChunk () {
276          super(JChunkFactory.this.small_size);
277       }
278
279       public synchronized void release() {
280          if (acquired == 1) {
281             next = null;
282             super.release();
283             addToSmallPool(this);
284          } else {
285             acquired--;
286          }
287       }
288    }
289
290    final class BigPoolChunk extends PoolChunk {
291
292       BigPoolChunk () {
293          super(JChunkFactory.this.big_size);
294       }
295
296       public synchronized void release() {
297          if (acquired == 1) {
298             next = null;
299             super.release();
300             addToBigPool(this);
301          } else {
302             acquired--;
303          }
304       }
305    }
306
307    static final class Duplicate extends Chunk {
308       PoolChunk target;
309
310       Duplicate(PoolChunk chunk,int offset, int top) {
311          super(chunk.data,offset,top);
312          this.target = chunk;
313          chunk.acquire();
314       }
315
316       public Chunk duplicate() {
317          return new Duplicate(target,offset,top);
318       }
319
320       public Chunk duplicate(int offset, int top) {
321          return new Duplicate(target,offset,top);
322       }
323
324       public void release() {
325          next = null;
326          target.release();
327          target = null;
328       }
329    }
330 }
331
Popular Tags