2006-11-17

DebianAMD64 and Samsung ML1740 (or othere printers)

Today, M. Aurélien Croc, the author of Splix, informed me that a new version of Splix, 0.0.2, is now usable in 64-bit.

Of course I am happy because now I am no longer limited to submitting 4294967296 documents to the spooler; now I can submit 18446744073709551616 documents at a time. I mean why else would you even bother running a spooler in a 64-bit environment? (I kid).

Packages needed:

libcupsys2-dev
libcupsimage2-dev



/tmp/splix-0.0.2 $ make
make[1]: Entering directory `/tmp/splix-0.0.2/src'
g++ -O2 `cups-config --cflags` -I../include -c -o rastertospl2.o rastertospl2.cpp
g++ -O2 `cups-config --cflags` -I../include -c -o raster.o raster.cpp
g++ `cups-config --ldflags` -lcups -lcupsimage -o rastertospl2 spl2.o printer.o band.o compress.o rastertospl2.o raster.o
make[1]: Leaving directory `/tmp/splix-0.0.2/src'
make[1]: Entering directory `/tmp/splix-0.0.2/ppd'
make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `/tmp/splix-0.0.2/ppd'


/tmp/splix-0.0.2 $ sudo make install
make[1]: Entering directory `/tmp/splix-0.0.2/src'
install -m 755 -s rastertospl2 `cups-config --serverbin`/filter
make[1]: Leaving directory `/tmp/splix-0.0.2/src'
make[1]: Entering directory `/tmp/splix-0.0.2/ppd'
install -d -m 755 `cups-config --datadir`/model/samsung
for filename in ml1510 ml1520 ml1610 ml1710 ml1740 ml1750 ml2010 ml2150 ml2250 ml2550; do \
install -m 644 $filename.ppd `cups-config --datadir`/model/samsung;\
for lang in fr it de; do \
install -m 644 $filename$lang.ppd `cups-config --datadir`/model/samsung;\
done; \
done \

make[1]: Leaving directory `/tmp/splix-0.0.2/ppd'

--- Everything is done! Have fun ---





The files installed are:


/usr/lib/cups/filter/rastertospl2
/usr/share/cups/model/samsung/*.ppd (among them is ml1740.ppd)


We can add the printer from cups's web interface (typically found at http://localhost:631). When prompted for printer model, just provide the ppd (in my case it is /usr/share/cups/model/samsung/ml1740.ppd).


(originally from http://microjet.ath.cx/WebWiki/2006.11.17_DebianAMD64_and_SamsungML1740_Part2.html)

2006-11-05

Continuation support in ruby

I heard today that Ruby 2.0 is going to abandon support for continuation, at least initially until things have stabilised a bit. It is no longer a news, it is just that I have not been active in Ruby community for a while.

The Problem with Continuation Support in Ruby 1.x


My initial reaction upon hearing that was "What a pity". On second thought, I realised that dropping continuation initially makes sense. The support for continuation in Ruby 1.x is missing an ensure procedure that is continuation-friendly; meaning one that is called only once one a given path is no longer accessible.

$create_cont_k=nil

def do_something(k)
  puts "Do something called"
  $create_cont_k = k
end

def do_something_else
  return unless $create_cont_k
  puts "Do something else called"
  k = $create_cont_k
  $create_cont_k = nil
  k.call
end


def create_cont
  callcc{|create_cont_k| do_something(create_cont_k)}
ensure
  puts "Ensure called"
end

create_cont
do_something_else

# /tmp $ ruby1.8  /tmp/ensure-run-multiply.rb 
# Do something called
# Ensure called
# Do something else called
# Ensure called


A proper ensure mechanism that supports explicit continuation formation system, like Ruby 1.8, would have produced:

# /tmp $ ruby1.8  /tmp/ensure-run-multiply.rb 
# Do something called
# Do something else called
# Ensure called


Notice how "ensure" is supposed to be called only once. I have a sample implementation of such continuation-observant ensure mechanism in system-managed-unwind-protect-in-sisc for SISC, a scheme implementation.

"But, but, what if I really want something like ensure that is called each time a code section is called?", you asked. In other words, you want something like Ruby 1.8's multiple-shot ensure in this new world of single-shot ensure.

That is not a problem and don't think that you are being unreasonable for asking this feature. It is useful to be able to guarantee execution of some code upon exiting a dynamic environment.

A dynamic environment is the environment that your program can access at any given time. The environment can change with each instruction executed by the machine.

But such one-sided guarantee does not really do anything interesting. How about a guarantee that some code is also executed upon entering a dynamic environment, thus having a symmetric aspect.

Scheme has dynamic-wind that does the above:

(define *CREATE-CONT-K* #f)

(define (do-something k)
  (display "Do something called\n")
  (set! *CREATE-CONT-K* k))

(define (do-something-else)
  (when *CREATE-CONT-K*
    (display "Do something else called\n")
    (let ((k *CREATE-CONT-K*))
      (set! *CREATE-CONT-K* #f)
      (k))))

(define (create-cont)
  (dynamic-wind
      (lambda () (display "Entering...\n"))
      (lambda ()
        (call/cc
         (lambda (create-cont-k)
           (do-something create-cont-k))))
      (lambda () (display "Exiting...\n"))))

(create-cont)
(do-something-else)

;; /tmp $ sisc -x /tmp/dynwind.scm 
;; Entering...
;; Do something called
;; Exiting...
;; Do something else called
;; Entering...
;; Exiting...

The utility in having a in/excursion guard can't be understated. In SRFI-34, dynamic-wind is used to install a custom exception handler. Yes, a custom exception handler; this is probably a strange concept for some people. Why would one have different exception handlers on the same piece of code? The first reason is "why not?". A dynamic language restricted to having a static exception handler feels incomplete. The second reason is more practical. Since you can in/ex-curse from/to any context (via calling a provided continuation object), how an exception is handled in a given context is not necessarily the same as in other different contexts.

Thus, a complete example of how multiple-shot and single-shot ensure example co-existing (sorry, in scheme as there is no Ruby implementation with single-shot ensure yet):

(class-path-extension-append! (list "file:/home/ysantoso/share/project/scheme/unwind-protect/"))

(require-library 'unwind-protect)
(import unwind-protect)

(import s2j)
(define (do-gc) ((generic-java-method '|gc|) (java-null (java-class '|java.lang.System|))))

;; do-something and do-something-else functions are elided for brevity

(define (create-cont)
  (dynamic-wind
      (lambda () (display "Entering...\n"))
      (lambda ()
        (unwind-protect
          (call/cc
            (lambda (create-cont-k)
              (do-something create-cont-k)))
         (display "Ensure\n")))
      (lambda () (display "Exiting...\n"))))


(create-cont)
(do-gc)
(do-something-else)
(do-gc)

;; /tmp $ sisc -x /tmp/dynwind.scm 
;; Entering...
;; Do something called
;; Exiting...
;; Do something else called
;; Entering...
;; Exiting...
;; Ensure

Notice how "ensure" is called just once even though there are two incursion into the protected code block.

The last deficiency in Ruby 1.x is the restriction that a continuation has to be resumed from the same thread that reifies it.

def do_something_else
  return unless $create_cont_k
  puts "Do something else called"
  k = $create_cont_k
  $create_cont_k = nil
  t=Thread.new { k.call}
  t.join
end

# /tmp $ ruby1.8  ensure-run-multiply.rb 
# Do something called
# Ensure called
# Do something else called
# ensure-run-multiply.rb:13:in `call': continuation called across threads (RuntimeError)
#       from ensure-run-multiply.rb:14:in `join'
#       from ensure-run-multiply.rb:14:in `do_something_else'
#       from ensure-run-multiply.rb:25


(originally from http://microjet.ath.cx/WebWiki/2006.11.05_Continuation_Support_in_Ruby.html)