On Friday, 15 March 2013 at 03:44:51 UTC, Ali Çehreli wrote:
On 03/14/2013 04:58 PM, Jesse Phillips wrote:
On Thursday, 14 March 2013 at 21:40:34 UTC, Ali Çehreli wrote:
I had toyed with the idea of making a ForwardRange from an
InputRange
by caching the elements. Without any guarantees, :) here is
the code:
http://forum.dlang.org/thread/ifg5ei$2qc7$1...@digitalmars.com
Ali
I attempted to create a sliceable forward range from an input
range. I
think I ran into a problem of keeping the buffer in sync when
doing
lookahead.
list2 = list1.save();
while(true) {
list1.popFront();
list2.popFront();
assert(list1.front == list2.front);
}
What happens when your buffer needs to fill, how do you get
the data in
list 1 & 2? I'm not posing this question as impossible only
something to
make work.
I had to study that old code of mine to understand how it
works. :)
The popFront() on the range itself dispatches the call to
ForwardRangeLazyCache by providing the id of this "view". In a
sense, it says "the range with this id would like to pop an
element":
@property void popFront()
{
lazyCache.popFront(myId);
}
ForwardRangeLazyCache.popFront simply increments the pointer of
the range that is associated with that id:
void popFront(size_t id)
{
++(viewPtrs[id]);
}
I am not sure whether this is a good idea but the actual
filling of the cache and synchronizing the "views" happen in
front():
@property immutable(E) front(size_t id)
{
ensureRead(viewPtrs[id]);
return *(viewPtrs[id]);
}
The above says "ensure that the element that this view is
trying to access is in the cache", and then returns that
element. It looks like there is even some optimization if the
array elements have not been moved:
void ensureRead(immutable(E) * ptr)
{
if (ptr == endPtr) {
immutable oldPtr = cache.ptr;
cache ~= range.front.idup;
range.popFront();
if (cache.ptr != oldPtr) {
/* The cache has been relocated */
adjustPtrs(oldPtr, cache.ptr);
} else {
++endPtr;
}
}
}
etc. :) I am really not sure whether it works correctly. :/
Ali
It *seems* to work :) Funny. The only problem is that caching db
results maybe it's not a good idea if i read too much data.
I'm not sure if it's fine or not but:
- I've changed AsForwardRange from class to struct
- I've added a method (it's an "hack" to make it works):
this(this)
{
auto dummy = lazyCache.newView(lazyCache.cache.ptr);
myId = dummy.myId;
}
- I've add @property to save() -> isForwardRange gives false
without this.
I did this to make it similar to other ranges (original topic!)
Shouldn't a view unregister pointer on its d-tor?
I'm not sure it's correct, is it?