comparison tango/tango/io/protocol/Allocator.d @ 132:1700239cab2e trunk

[svn r136] MAJOR UNSTABLE UPDATE!!! Initial commit after moving to Tango instead of Phobos. Lots of bugfixes... This build is not suitable for most things.
author lindquist
date Fri, 11 Jan 2008 17:57:40 +0100
parents
children
comparison
equal deleted inserted replaced
131:5825d48b27d1 132:1700239cab2e
1 /*******************************************************************************
2
3 copyright: Copyright (c) 2004 Kris Bell. All rights reserved
4
5 license: BSD style: $(LICENSE)
6
7 version: Initial release: October 2004
8 Outback release: December 2006
9
10 author: Kris
11
12 Allocators to use in conjunction with the Reader class. These are
13 intended to manage array allocation for a variety of Reader.get()
14 methods
15
16 *******************************************************************************/
17
18 module tango.io.protocol.Allocator;
19
20 private import tango.io.protocol.model.IProtocol;
21
22
23 /*******************************************************************************
24
25 Simple allocator, copying into the heap for each array requested:
26 this is the default behaviour for Reader instances
27
28 *******************************************************************************/
29
30 class HeapCopy : IAllocator
31 {
32 private IProtocol protocol_;
33
34 /***********************************************************************
35
36 ***********************************************************************/
37
38 this (IProtocol protocol)
39 {
40 protocol_ = protocol;
41 }
42
43 /***********************************************************************
44
45 ***********************************************************************/
46
47 final IProtocol protocol ()
48 {
49 return protocol_;
50 }
51
52 /***********************************************************************
53
54 ***********************************************************************/
55
56 final void reset ()
57 {
58 }
59
60 /***********************************************************************
61
62 ***********************************************************************/
63
64 final void[] allocate (IProtocol.Reader reader, uint bytes, IProtocol.Type type)
65 {
66 return reader ((new void[bytes]).ptr, bytes, type);
67 }
68 }
69
70
71 /*******************************************************************************
72
73 Allocate from within a private heap space. This supports reading
74 data as 'records', reusing the same chunk of memory for each record
75 loaded. The ctor takes an argument defining the initial allocation
76 made, and this will be increased as necessary to accomodate larger
77 records. Use the reset() method to indicate end of record (reuse
78 memory for subsequent requests), or set the autoreset flag to reuse
79 upon each array request.
80
81 *******************************************************************************/
82
83 class HeapSlice : IAllocator
84 {
85 private uint used;
86 private void[] buffer;
87 private IProtocol protocol_;
88 private bool autoreset;
89
90 /***********************************************************************
91
92 ***********************************************************************/
93
94 this (IProtocol protocol, uint width=4096, bool autoreset=false)
95 {
96 protocol_ = protocol;
97 buffer = new void[width];
98 this.autoreset = autoreset;
99 }
100
101 /***********************************************************************
102
103 ***********************************************************************/
104
105 final IProtocol protocol ()
106 {
107 return protocol_;
108 }
109
110 /***********************************************************************
111
112 Reset content length to zero
113
114 ***********************************************************************/
115
116 final void reset ()
117 {
118 used = 0;
119 }
120
121 /***********************************************************************
122
123 No allocation: copy into a reserved arena.
124
125 With HeapSlice, it is normal to allocate space large
126 enough to contain, say, a record of data. The reserved
127 space will grow to accomodate larger records. A reset()
128 call should be made between each record read, to ensure
129 the space is being reused.
130
131 ***********************************************************************/
132
133 final void[] allocate (IProtocol.Reader reader, uint bytes, IProtocol.Type type)
134 {
135 if (autoreset)
136 used = 0;
137
138 if ((used + bytes) > buffer.length)
139 buffer.length = (used + bytes) * 2;
140
141 auto ptr = &buffer[used];
142 used += bytes;
143
144 return reader (ptr, bytes, type);
145 }
146 }
147
148
149 /*******************************************************************************
150
151 Alias directly from the buffer instead of allocating from the heap.
152 This avoids both heap activity and copying, but requires some care
153 in terms of usage. See methods allocate() for details
154
155 *******************************************************************************/
156
157 class BufferSlice : IAllocator
158 {
159 private IProtocol protocol_;
160
161 /***********************************************************************
162
163 ***********************************************************************/
164
165 this (IProtocol protocol)
166 {
167 protocol_ = protocol;
168 }
169
170 /***********************************************************************
171
172 ***********************************************************************/
173
174 final IProtocol protocol ()
175 {
176 return protocol_;
177 }
178
179 /***********************************************************************
180
181 Move all unconsumed data to the front of the buffer, freeing
182 up space for more
183
184 ***********************************************************************/
185
186 final void reset ()
187 {
188 protocol.buffer.compress;
189 }
190
191 /***********************************************************************
192
193 No alloc or copy: alias directly from buffer. While this is
194 very efficient (no heap activity) it should be used only in
195 scenarios where content is known to fit within a buffer, and
196 there is no conversion of said content e.g. take care when
197 using with EndianProtocol since it will convert within the
198 buffer, potentially confusing additional buffer clients.
199
200 With BufferSlice, it is considered normal to create a Buffer
201 large enough to contain, say, a file and subsequently slice
202 all strings/arrays directly from this buffer. Smaller Buffers
203 can be used in a record-oriented manner similar to HeapSlice:
204 invoke reset() before each record is processed to ensure here
205 is sufficient space available in the buffer to house a complete
206 record. GrowBuffer could be used in the latter case, to ensure
207 the largest record width is always accomodated.
208
209 A good use of this is in handling of network traffic, where
210 incoming data is often transient and of a known extent. For
211 another potential use, consider the quantity of distinct text
212 arrays generated by an XML parser -- would be convenient to
213 slice all of them from a single allocation instead
214
215 ***********************************************************************/
216
217 final void[] allocate (IProtocol.Reader reader, uint bytes, IProtocol.Type type)
218 {
219 return protocol_.buffer.slice (bytes);
220 }
221 }