Re: [Vala] Documenting 'async' / WAS: Further speculations on couroutines, generators and threads : Emulating Go's goroutines and channels in Vala



On Fri, Jul 15, 2011 at 8:16 AM, Serge Hulne <serge hulne gmail com> wrote:

I am right in assuming that:


2. Async methods have virtually no use outside the scope of event-driven
GTK+ applications (except perhaps as a way to implement additional Vala
features like Luca Bruno's generator, but at the cost of
runtime-performance).

3. There is always a way to write an equivalent program without async
methods (with just ordinary function calls), except for applications with a
graphical interface (GTK+ applications).

4. That a program avoiding async methods will always :
        - be more readable (simpler).
        - perform faster.

5. That async methods are not about runtime performance, but exclusively
about:
        - callbacks for graphical interfaces.
        - convenience (as an alternative to an ordinary function call, when
it seems convenient to do so).

6. That async methods are not at all meant to provide a way to run
ancillary tasks in the background, in order to gain runtime performance.

Serge.






A concrete example:

In the example hereunder, the file shakes.txt is Shakespeare's complete
work, from :

http://www.gutenberg.org/cache/epub/100/pg100.txt

Serge.


////////////////
1) Trivial scanner : Version without async method calls
////////////////
using Posix;
using Gee;


void scanner(string fname) {

    var f = FileStream.open(fname, "r");

    if (f==null) {
        Posix.stdout.printf("File missing !\n");
        exit(1);
    }

    StringBuilder wordBuffer = new StringBuilder("");
    char c = ' ';
    int wordBuffer_length = 0;
    var erased = true;

    while (!f.eof()) {
        c = (char) f.getc();
        //if (!isalnum(c))
        if (isspace(c)) {
            if (wordBuffer.len>0) {
                Posix.stdout.printf("word = %s\n", wordBuffer.str);
                if (erased == false) {
                    wordBuffer.erase(0,-1);
                    wordBuffer_length = 0;
                    erased = true;
                }
            }
        } else {
            wordBuffer_length++;
            //Posix.stdout.printf("%d\n", wordBuffer_length);
            wordBuffer.append_c(c);
            erased = false;
        }
    }

}



void main(string[] args) {
    var fname = "../corpora/shakes.txt";
    // -- testing scanner --
    scanner(fname);
}
///////////




////////////////////////////
// 2)  Trivial scanner : version with async method calls
// Convenient, but much slower
////////////////////////////

using Posix;
using Gee;


class scanner : Generator<string> {

    public scanner() {
        Posix.stdout.printf("Starting !\n");
    }

    protected override async void generate() {

        var fname = "../corpora/shakes.txt";

        Posix.printf("fname = %s\n", fname);
        var f = FileStream.open(fname, "r");
        if (f==null) {
            Posix.stdout.printf("File missing !\n");
            exit(1);
        }

        StringBuilder wordBuffer = new StringBuilder("");
        char c = ' ';
        int wordBuffer_length = 0;
        var erased = true;
        unowned string word;
        while (!f.eof()) {
            c = (char) f.getc();
            if (isspace(c)) {
                if (wordBuffer.len>0) {
                    //Posix.stdout.printf("word = %s\n", wordBuffer.str);
                    word = wordBuffer.str;
                    yield feed(word);
                    if (erased == false) {
                        wordBuffer.erase(0,-1);
                        wordBuffer_length = 0;
                        erased = true;
                    }
                }
            } else {
                wordBuffer_length++;
                //Posix.stdout.printf("%d\n", wordBuffer_length);
                wordBuffer.append_c(c);
                erased = false;
            }
        }
    }
}


void main(string[] args) {
    var gen = new scanner();
    var i=0;
    foreach (var item in gen) {
        if(i<10) Posix.stdout.printf("%s\n", item);
        i++;
    }
}

//////////////////////////






/////////////////////////
// The generator class
/////////////////////////

abstract class Generator<G> {
    private bool consumed;
    private unowned G value;
    private SourceFunc callback;

    public Generator () {
        helper ();
    }

    private async void helper () {
        yield generate ();
        consumed = true;
    }

    protected abstract async void generate ();

    protected async void feed (G value) {
        this.value = value;
        this.callback = feed.callback;
        yield;
    }

    public bool next () {
        return !consumed;
    }

    public G get () {
        var result = value;
        callback ();
        return result;
    }

    public Generator<G> iterator () {
        return this;
    }
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]