chicken-users
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]