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