Mercurial > projects > ldc
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tango/tango/io/protocol/Allocator.d Fri Jan 11 17:57:40 2008 +0100 @@ -0,0 +1,221 @@ +/******************************************************************************* + + copyright: Copyright (c) 2004 Kris Bell. All rights reserved + + license: BSD style: $(LICENSE) + + version: Initial release: October 2004 + Outback release: December 2006 + + author: Kris + + Allocators to use in conjunction with the Reader class. These are + intended to manage array allocation for a variety of Reader.get() + methods + +*******************************************************************************/ + +module tango.io.protocol.Allocator; + +private import tango.io.protocol.model.IProtocol; + + +/******************************************************************************* + + Simple allocator, copying into the heap for each array requested: + this is the default behaviour for Reader instances + +*******************************************************************************/ + +class HeapCopy : IAllocator +{ + private IProtocol protocol_; + + /*********************************************************************** + + ***********************************************************************/ + + this (IProtocol protocol) + { + protocol_ = protocol; + } + + /*********************************************************************** + + ***********************************************************************/ + + final IProtocol protocol () + { + return protocol_; + } + + /*********************************************************************** + + ***********************************************************************/ + + final void reset () + { + } + + /*********************************************************************** + + ***********************************************************************/ + + final void[] allocate (IProtocol.Reader reader, uint bytes, IProtocol.Type type) + { + return reader ((new void[bytes]).ptr, bytes, type); + } +} + + +/******************************************************************************* + + Allocate from within a private heap space. This supports reading + data as 'records', reusing the same chunk of memory for each record + loaded. The ctor takes an argument defining the initial allocation + made, and this will be increased as necessary to accomodate larger + records. Use the reset() method to indicate end of record (reuse + memory for subsequent requests), or set the autoreset flag to reuse + upon each array request. + +*******************************************************************************/ + +class HeapSlice : IAllocator +{ + private uint used; + private void[] buffer; + private IProtocol protocol_; + private bool autoreset; + + /*********************************************************************** + + ***********************************************************************/ + + this (IProtocol protocol, uint width=4096, bool autoreset=false) + { + protocol_ = protocol; + buffer = new void[width]; + this.autoreset = autoreset; + } + + /*********************************************************************** + + ***********************************************************************/ + + final IProtocol protocol () + { + return protocol_; + } + + /*********************************************************************** + + Reset content length to zero + + ***********************************************************************/ + + final void reset () + { + used = 0; + } + + /*********************************************************************** + + No allocation: copy into a reserved arena. + + With HeapSlice, it is normal to allocate space large + enough to contain, say, a record of data. The reserved + space will grow to accomodate larger records. A reset() + call should be made between each record read, to ensure + the space is being reused. + + ***********************************************************************/ + + final void[] allocate (IProtocol.Reader reader, uint bytes, IProtocol.Type type) + { + if (autoreset) + used = 0; + + if ((used + bytes) > buffer.length) + buffer.length = (used + bytes) * 2; + + auto ptr = &buffer[used]; + used += bytes; + + return reader (ptr, bytes, type); + } +} + + +/******************************************************************************* + + Alias directly from the buffer instead of allocating from the heap. + This avoids both heap activity and copying, but requires some care + in terms of usage. See methods allocate() for details + +*******************************************************************************/ + +class BufferSlice : IAllocator +{ + private IProtocol protocol_; + + /*********************************************************************** + + ***********************************************************************/ + + this (IProtocol protocol) + { + protocol_ = protocol; + } + + /*********************************************************************** + + ***********************************************************************/ + + final IProtocol protocol () + { + return protocol_; + } + + /*********************************************************************** + + Move all unconsumed data to the front of the buffer, freeing + up space for more + + ***********************************************************************/ + + final void reset () + { + protocol.buffer.compress; + } + + /*********************************************************************** + + No alloc or copy: alias directly from buffer. While this is + very efficient (no heap activity) it should be used only in + scenarios where content is known to fit within a buffer, and + there is no conversion of said content e.g. take care when + using with EndianProtocol since it will convert within the + buffer, potentially confusing additional buffer clients. + + With BufferSlice, it is considered normal to create a Buffer + large enough to contain, say, a file and subsequently slice + all strings/arrays directly from this buffer. Smaller Buffers + can be used in a record-oriented manner similar to HeapSlice: + invoke reset() before each record is processed to ensure here + is sufficient space available in the buffer to house a complete + record. GrowBuffer could be used in the latter case, to ensure + the largest record width is always accomodated. + + A good use of this is in handling of network traffic, where + incoming data is often transient and of a known extent. For + another potential use, consider the quantity of distinct text + arrays generated by an XML parser -- would be convenient to + slice all of them from a single allocation instead + + ***********************************************************************/ + + final void[] allocate (IProtocol.Reader reader, uint bytes, IProtocol.Type type) + { + return protocol_.buffer.slice (bytes); + } +}