Re: [Vala] Documenting 'async' / WAS: Further speculations on couroutines, generators and threads : Emulating Go's goroutines and channels in Vala
- From: Serge Hulne <serge hulne gmail com>
- To: Luca Bruno <lethalman88 gmail com>
- Cc: vala-list <vala-list gnome org>, Alexandre Rosenfeld <alexandre rosenfeld gmail com>, Jim Peters <jim uazu net>
- Subject: Re: [Vala] Documenting 'async' / WAS: Further speculations on couroutines, generators and threads : Emulating Go's goroutines and channels in Vala
- Date: Fri, 15 Jul 2011 08:52:18 +0200
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]