Thursday 30 April 2015

hmmm

Playing with spliterators again.

This was my first go of the row spliterator forEachRemaining() func, and does what I believe the stream api expects:

public void forEachRemaining(Consumer<? super ByteRow> action) {
    for (int y = this.y, ey = y + height; y < ey; y++) {
        ByteRow row = ...;
        ...
        pixels.getRow(y, row);
        action.accept(row);
    }
}

And this is the way I would rather do it, because well any other way is a bit dumb:

public void forEachRemaining(Consumer<? super ByteRow> action) {
    ByteRow row = pixels.createByteRow();
    for (int y = this.y, ey = y + height; y < ey; y++) {
        ...
        pixels.getRow(y, row);
        action.accept(row);
    }
}

Because spliterators are single-threaded this actually works for some (all?) of the stream operations that make sense like "map()" (even multiple stages), "collect()", "forEach()", and a couple more. This is because these (or the parts which take the partial result) are all run on the same context as the spliterator. It wont provide meaningful results for others like "toArray()" or "sort()" but those operations wouldn't even if they did and one could always map to a new copy.

Of course, a different streams implementation could change that but I think it's one of those "i'll fix it if it breaks" things and I suspect it wont ever be able to be altered because someone who pays money to oracle will also think the same thing but wont want to fix it on their purse.

Maybe keeping valid instances around makes more sense for tiles, but if needed a copying collector could do that instead.

Update: Ok I decided not to post this originally because i just wasn't feeling like it, but now here goes, so this is a pre-post "update".

I followed on these ideas and did a bunch of re-arranging and settled on a consistent approach: by default any in the "stream" are just references to per-spliterator instances. If they need to be unique for further prorcessing they can be duplicated by clone() or the like. If it turns out this assumption is not sufficiently useful i can just change the spliterators then.

I did a bit of refactoring to try and save some small common bits of code in the spliterators but it just seemed like fiddling at the edges and adding extra classes for no real benefit.

Then I ran out of steam a bit and haven't really done much else on it.

Been doing some mildly interesting things with javafx though - i was going to say a few days ago how nice it is to work with, but then i hit some exceedingly frustrating problems with very simple layout needs which really gave me the shits. I got it working but damn it took way longer than it should have. I also spent too long trying to work out how to blend against a generated mask before I remembered about using the clip node. It's only a simple compositing task but having it running interactive speed with "so little work" is nice.

No comments: