Is this range behaviour correct?

Andrea Fontana nospam at example.com
Fri Mar 15 02:57:24 PDT 2013


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?







More information about the Digitalmars-d-learn mailing list