[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Chicken-users] code snippet (suggested for the wiki) - and several
From: |
Tobia Conforto |
Subject: |
Re: [Chicken-users] code snippet (suggested for the wiki) - and several newcomer questions |
Date: |
Sun, 17 Aug 2008 20:11:51 +0200 |
Thank you for this commented version!
I will raise my own "novice questions" if you don't mind.
No matter how careful you are, switching to kernel mode and back is
expensive in comparison to register arithmetic.
Yes, but do Chicken mutexes and condition variables incur in a switch
to kernel mode at all? It's not obvious they do, since we're not
using OS threads.
User level thread systems, as chicken provides one, schedule in a
way, which could be understood as cooperative under the hood. In
chicken, any C expression is never interrupted.
[[[ Is this actually true or just my understanding? ]]]
This is very interesting and I would like to know if it's true or not,
and what constitutes a "C expression" in this context.
(define string-ref++
(foreign-lambda*
char
((scheme-pointer buf) ((c-pointer integer) i))
"char *p=(char *)buf; return(p[(*i)++]);"))
Why are you using return instead of C_return? Is it intentional, or
just a mistake?
Beginners did ask, why all these [x x]-bindings? We keep a local
reference in case the global one becomes redefined. This is a
questionable practise. While it's just what the doctor ordered...
Is this standard Chicken practice? Why are you forbidding the user
(or another egg) to redefine these functions? What is the purpose?
(let ((mutex (make-mutex name))
(condition (make-condition-variable name))
(queue (make-queue))
(buf #f))
(define (eof?) (eq? #!eof buf))
(define (buf-empty?) (or (not buf) (fx>= off (string-length buf))))
What does it mean for buf to be #f, #!eof, and ""? Do all three mean
the same thing? (I hope not.)
Why is buf-empty? allowed to crash with an error when buf is #!eof?
Also, at this point it's not clear to me why you have both a buffer
and a queue, although I'm sure it will become clear in a moment, so
maybe you should write a paragraph about the purpose of your variables.
(define (read-input!)
(mutex-lock! mutex)
(if (buf-empty?)
(if (queue-empty? queue)
(begin
(mutex-unlock! mutex condition)
(read-input!))
(begin
(set! buf #f)
(set! buf (queue-remove! queue))
(set! off 0)
(mutex-unlock! mutex)))
(mutex-unlock! mutex)))
So: if both buf and the queue are empty, it waits on the condition
variable; if buf is empty but the queue is not, it pops a string (or #!
eof, I guess) from the queue into buf; if buf is not empty, it does
nothing. I'm starting to see what the queue and buf are for.
Why did you put (set! buf #f) just before another (set! buf)?
(define (read!)
(if (eof?) buf
(if (buf-empty?)
(begin (read-input!) (read!))
(string-ref++ buf (location off)))))
It would appear to me that this whole part should be inside your
critical section, as in read-input! and write!. Am I missing your
point here? I mean, even assuming string-ref++ is atomic in Chicken
threads (which still needs confirmation) you cannot hope to put this
whole if tree outside any mutex and don't run into trouble. The same
goes for ready?, read-string, and all the rest.
Tobia