1 package com.ctc.wstx.io;
2
3 /**
4  * This is a small utility class, whose main functionality is to allow
5  * simple reuse of raw byte/char buffers. It is usually used through
6  * <code>ThreadLocal</code> member of the owning class pointing to
7  * instance of this class through a <code>SoftReference</code>. The
8  * end result is a low-overhead GC-cleanable recycling: hopefully
9  * ideal for use by stream readers.
10  *<p>
11  * Regarding implementation: the key design goal is simplicity; and to
12  * that end, different types of buffers are handled separately. While
13  * code may look inelegant as a result (wouldn't it be neat to just
14  * have generic char[]/byte[] buffer accessors?), benefit is that
15  * no data structures are needed, just simple references. As long
16  * as usage pattern is well known (which it is, for stream readers)
17  * this should be highly optimal and robust implementation.
18  */

19 public final class BufferRecycler
20 {
21     private volatile char[] mSmallCBuffer = null// temp buffers
22     private volatile char[] mMediumCBuffer = null// text collector
23     private volatile char[] mFullCBuffer = null// for actual parsing buffer
24
25     private volatile byte[] mFullBBuffer = null;
26
27     public BufferRecycler() { }
28
29     // // // Char buffers:
30
31     // // Small buffers, for temporary parsing
32
33     public synchronized char[] getSmallCBuffer(int minSize)
34     {
35         char[] result = mSmallCBuffer;
36         if (result != null && result.length >= minSize) {
37             mSmallCBuffer = null;
38             return result;
39         }
40 //System.err.println("DEBUG: Alloc CSmall: "+result);
41         return null;
42     }
43
44     public synchronized void returnSmallCBuffer(char[] buffer)
45     {
46 //System.err.println("DEBUG: Return CSmall ("+buffer.length+"): "+buffer);
47         mSmallCBuffer = buffer;
48     }
49
50     // // Medium buffers, for text output collection
51
52     public synchronized char[] getMediumCBuffer(int minSize)
53     {
54         char[] result = mMediumCBuffer;
55         if (result != null && result.length >= minSize) {
56             mMediumCBuffer = null;
57             return result;
58         }
59 //System.err.println("DEBUG: Alloc CMed: "+result);
60         return null;
61     }
62
63     public synchronized void returnMediumCBuffer(char[] buffer)
64     {
65         mMediumCBuffer = buffer;
66 //System.err.println("DEBUG: Return CMed ("+buffer.length+"): "+buffer);
67     }
68
69     // // Full buffers, for parser buffering
70
71     public synchronized char[] getFullCBuffer(int minSize)
72     {
73         char[] result = mFullCBuffer;
74         if (result != null && result.length >= minSize) {
75             mFullCBuffer = null;
76             return result;
77         }
78 //System.err.println("DEBUG: Alloc CFull: "+result);
79         return null;
80     }
81
82     public synchronized void returnFullCBuffer(char[] buffer)
83     {
84         mFullCBuffer = buffer;
85 //System.err.println("DEBUG: Return CFull ("+buffer.length+"): "+buffer);
86     }
87
88     // // // Byte buffers:
89
90     // // Full byte buffers, for byte->char conversion (Readers)
91
92     public synchronized byte[] getFullBBuffer(int minSize)
93     {
94         byte[] result = mFullBBuffer;
95         if (result != null && result.length >= minSize) {
96             mFullBBuffer = null;
97             return result;
98         }
99 //System.err.println("DEBUG: Alloc BFull: "+result);
100         return null;
101     }
102
103     public synchronized void returnFullBBuffer(byte[] buffer)
104     {
105         mFullBBuffer = buffer;
106 //System.err.println("DEBUG: Return BFull ("+buffer.length+"): "+buffer);
107     }
108 }
109