[Anthy-dev 2324] Re: r5rs: bugfix, mutex (was: write/ss 実装)

Back to archive index

Jun Inoue jun.l****@gmail*****
2005年 9月 1日 (木) 18:14:28 JST


・write/ss で、SigScheme 特有の事情 (procedure, values が表示される) に
よるバグと、hash table が伸長する場合の戻り値の勘違いによるバグを直しま
した。

・prime.scm などの作業中のものがいくつか混ざってます。全部 trivial な変
更。PRIME 自体はまだうまく動いてないです…全体構造を理解してないから作業
が遅い。

↑が sscm-write-ss3.diff。↓が uim-lock.diff。

・uim_find_context() にバグがあったので直そうとすると、ちょうど徳永さん
が修正を commit されたのでやめようかと思ったんですが、違うやり方なので一
応投げてみます。ミソは sig_atomic_t より小さいオブジェクトの read/write
は atomic であると仮定するというところです。[1]によれば、大抵の環境では
ポインタは atomic object のようなので、これでロックが減らせると思ったん
ですが、ちょっとキモいですかね…

[1] "The GNU C Library" http://www.delorie.com/gnu/docs/glibc/libc_496.html
-- 
Jun Inoue
jun.l****@gmail*****
-------------- next part --------------
diff -Nur ./scm/hk.scm ../.r5rs/scm/hk.scm
--- ./scm/hk.scm	2005-03-11 01:26:50.000000000 -0800
+++ ../.r5rs/scm/hk.scm	2005-08-31 21:32:02.000000000 -0700
@@ -81,7 +81,7 @@
 
 (define hk-make-match-list
   (lambda (left)
-    (mapcar
+    (map
      (lambda(l)
        (car (cadr l)))
      left)))
@@ -94,7 +94,7 @@
 (define hk-left-string-match
   (lambda (hkc)
     (let* ((left (hk-left-string-list hkc))
-	   (match-list (mapcar
+	   (match-list (map
 			(lambda(l)
 			  (car (cadr l)))
 			left))
@@ -157,7 +157,7 @@
 (define hk-make-str-list
   (lambda (str)
     (if str
-	(mapcar 
+	(map 
 	 (lambda (s)
 	   (let ((splitted (string-split s " ")))
 	     (if splitted
@@ -214,7 +214,7 @@
 	  (table-id (hk-context-table-id hkc)))
       (if str-list
 	  (begin
-	    (mapcar (lambda (s)
+	    (map (lambda (s)
 		  ;    (print str)
 		      (if str
 			  (set! str (string-append str " " s))
@@ -232,7 +232,7 @@
 	  (table-id (hk-context-table-id hkc)))
       (if str-list
 	  (begin
-	    (mapcar (lambda (s)
+	    (map (lambda (s)
 		      (if str
 			  (set! str (string-append str " " s))
 			  (set! str s)))
@@ -247,7 +247,7 @@
 	  (table-id (hk-context-table-id hkc)))
       (if str-list
 	  (begin
-	    (mapcar 
+	    (map 
 	     (lambda (s)
 	       (set! str (string-append str " " s)))
 	     str-list)
diff -Nur ./scm/prime.scm ../.r5rs/scm/prime.scm
--- ./scm/prime.scm	2005-08-31 20:36:00.000000000 -0700
+++ ../.r5rs/scm/prime.scm	2005-09-01 01:52:29.000000000 -0700
@@ -142,24 +142,24 @@
 	  (language (prime-context-language context))
 	  (keymap))
       (cond
-       ((= state 'prime-state-segment)
+       ((eq? state 'prime-state-segment)
 	(set! keymap prime-keymap-segment-state))
 
-       ((= state 'prime-state-modifying)
+       ((eq? state 'prime-state-modifying)
 	(set! keymap prime-keymap-modify-state))
 
-       ((= state 'prime-state-converting)
-	(if (= language 'Japanese)
+       ((eq? state 'prime-state-converting)
+	(if (eq? language 'Japanese)
 	    (set! keymap prime-keymap-conv-state)
 	    (set! keymap prime-keymap-english-conv-state)))
 
-       ((= state 'prime-state-preedit)
-	(if (= language 'Japanese)
+       ((eq? state 'prime-state-preedit)
+	(if (eq? language 'Japanese)
 	    (set! keymap prime-keymap-preedit-state)
 	    (set! keymap prime-keymap-english-preedit-state)))
 
-       ((= state 'prime-state-fund)
-	(if (= language 'Japanese)
+       ((eq? state 'prime-state-fund)
+	(if (eq? language 'Japanese)
 	    (if (prime-context-parent-context context)
 		(set! keymap prime-keymap-child-fund-state)
 		(set! keymap prime-keymap-fund-state))
@@ -538,7 +538,7 @@
 	  (prime-lib-init prime-use-unixdomain?)
 	  (let ((session (prime-engine-session-start)))
 	    (prime-custom-init)
-	    (prime-context-set-fund-line!  context (cons (list) (list)))
+	    (prime-context-set-fund-line!  context (cons () ()))
 	    (prime-context-set-session!    context session)
 	    (prime-context-set-lang-session-list!
 	     context
@@ -567,7 +567,7 @@
 (define prime-context-pop
   (lambda (context)
     (let ((parent-context (prime-context-parent-context context)))
-      (mapcar
+      (map
        (lambda (lang-pair)
 	 (prime-engine-session-end (cdr lang-pair)))
        (prime-context-lang-session-list context))
@@ -585,7 +585,7 @@
 (define prime-context-history-update!
   (lambda (context)
     (let* ((state          (prime-context-state context))
-	   (selected-index (if (= state 'prime-state-segment)
+	   (selected-index (if (eq? state 'prime-state-segment)
 			       (prime-context-segment-nth context)
 			       (prime-context-nth context))))
       (prime-context-set-history!
@@ -602,7 +602,7 @@
   (lambda (context)
     (let* ((prev-data      (prime-context-history context))
 	   (state          (prime-context-state context))
-	   (selected-index (if (= state 'prime-state-segment)
+	   (selected-index (if (eq? state 'prime-state-segment)
 			       (prime-context-segment-nth context)
 			       (prime-context-nth context))))
       (cond
@@ -686,7 +686,7 @@
 
 (define prime-util-assoc-list
   (lambda (lst)
-    (mapcar 
+    (map 
      (lambda (str)
        (string-split str "="))
      lst)))
@@ -714,7 +714,7 @@
   (lambda (string)
     (let ((integer 0)
 	  (figure  1))
-      (mapcar
+      (map
        (lambda (digit-string)
 	 (if (string=? digit-string "-")
 	     (set! integer (- integer))
@@ -778,7 +778,7 @@
     (let* ((result
 	    (prime-engine-send-command (list command prime-session)))
 	   (index (prime-util-string-to-integer (car result)))
-	   (words (mapcar
+	   (words (map
 		   (lambda (string-line)
 		     (let ((word-data (prime-util-string-split string-line
 							       "\t")))
@@ -855,7 +855,7 @@
 
 (define prime-engine-session-language-set
   (lambda (language)
-    (let ((language-string (if (= language 'English) "English" "Japanese")))
+    (let ((language-string (if (eq? language 'English) "English" "Japanese")))
       (car (prime-engine-send-command
 	    (list "session_start" language-string))))))
 
@@ -990,7 +990,7 @@
 ;; This changes the typing mode specified by mode-string.
 (define prime-mode-set-mode
   (lambda (context mode-string)
-    (if (= (prime-context-state context) 'prime-state-converting)
+    (if (eq? (prime-context-state context) 'prime-state-converting)
 	(prime-convert-cancel context))
     (prime-engine-edit-set-mode (prime-context-session context) mode-string)))
     
@@ -1021,7 +1021,7 @@
 
 (define prime-command-language-toggle
   (lambda (context key key-state)
-    (let ((next-language (if (= (prime-context-language context) 'English)
+    (let ((next-language (if (eq? (prime-context-language context) 'English)
 			     'Japanese 'English)))
       (prime-mode-language-set context next-language))))
 
@@ -1308,8 +1308,8 @@
 (define prime-command-fund-space
   (lambda (context key key-state)
     (cond
-     ((= (prime-context-language context) 'Japanese)
-      (let ((space (if (= prime-custom-japanese-space 'wide) " " " ")))
+     ((eq? (prime-context-language context) 'Japanese)
+      (let ((space (if (eq? prime-custom-japanese-space 'wide) " " " ")))
 	(prime-commit-without-learning context space)))
      (t
       (prime-commit-without-learning context " ")))))
@@ -1317,8 +1317,8 @@
 (define prime-command-fund-altspace
   (lambda (context key key-state)
     (cond
-     ((= (prime-context-language context) 'Japanese)
-      (let ((space (if (= prime-custom-japanese-space 'wide) " " " ")))
+     ((eq? (prime-context-language context) 'Japanese)
+      (let ((space (if (eq? prime-custom-japanese-space 'wide) " " " ")))
 	(prime-commit-without-learning context space)))
      (t
       (prime-commit-without-learning context " ")))))
@@ -1407,7 +1407,7 @@
     (let ((key-data (car key-list)))
       (cond
        ;; there's no speficied command then pressed key is passed.
-       ((= key-list '())
+       ((eq? key-list '())
 	(prime-context-set-app-mode-key-list! context
 					      prime-app-mode-end-stroke-list)
 	(prime-commit-raw context))
@@ -1770,20 +1770,20 @@
   (lambda (context)
     (let ((diff (prime-context-history-compare context)))
       (cond
-       ((= diff 'state)
+       ((eq? diff 'state)
 	(let ((state     (prime-context-state context))
 	      (last-word (prime-context-last-word context)))
 	  (cond
-	   ((= state 'prime-state-preedit)
+	   ((eq? state 'prime-state-preedit)
 	    (prime-convert-get-prediction context))
-	   ((= state 'prime-state-converting)
+	   ((eq? state 'prime-state-converting)
 	    ;; Do nothing.  (prime-convert-get-conversion context) had been
 	    ;; already executed at prime-convert-start-internal
 	    )
-	   ((= state 'prime-state-fund)
+	   ((eq? state 'prime-state-fund)
 	    (prime-context-set-candidates! context '()))
 	    )))
-       ((= diff 'preedit)
+       ((eq? diff 'preedit)
 	(prime-convert-get-prediction context))
        ))))
 
@@ -1791,13 +1791,13 @@
   (lambda (context)
     (let ((diff (prime-context-history-compare context)))
       (cond
-       ((= diff 'state)
+       ((eq? diff 'state)
 	(let ((state (prime-context-state context)))
 	  (cond
-	   ((= state 'prime-state-fund)
+	   ((eq? state 'prime-state-fund)
 	    (im-deactivate-candidate-selector context))
 
-	   ((= state 'prime-state-preedit)
+	   ((eq? state 'prime-state-preedit)
 	    (if (> (prime-get-nr-candidates context) 0)
 		(im-activate-candidate-selector
 		 context
@@ -1805,15 +1805,15 @@
 		 3)))
 ;		 prime-nr-candidate-max)))
 
-	   ((= state 'prime-state-converting)
+	   ((eq? state 'prime-state-converting)
  	    (im-activate-candidate-selector
  	     context (prime-get-nr-candidates context) prime-nr-candidate-max)
 	    (im-select-candidate context (prime-context-nth context)))
 
-	   ((= state 'prime-state-modifying)
+	   ((eq? state 'prime-state-modifying)
 	    (im-deactivate-candidate-selector context))
 
-	   ((= state 'prime-state-segment)
+	   ((eq? state 'prime-state-segment)
  	    (im-activate-candidate-selector
 	     context
 	     (prime-segment-get-candidates-length context)
@@ -1821,12 +1821,12 @@
 	    (im-select-candidate context (prime-context-segment-nth context)))
 	    )))
 
-       ((= diff 'nth)
-	(if (= (prime-context-state context) 'prime-state-segment)
+       ((eq? diff 'nth)
+	(if (eq? (prime-context-state context) 'prime-state-segment)
 	    (im-select-candidate context (prime-context-segment-nth context))
 	    (im-select-candidate context (prime-context-nth context))))
 
-       ((= diff 'preedit)
+       ((eq? diff 'preedit)
 	(if (> (prime-get-nr-candidates context) 0)
 	    (im-activate-candidate-selector
 	     context (prime-get-nr-candidates context) prime-nr-candidate-max)
@@ -1859,12 +1859,12 @@
   (lambda (context)
     (let* ((state (prime-context-state context)))
       (cond
-       ((= state 'prime-state-converting)
+       ((eq? state 'prime-state-converting)
 	(list (cons 'converting (prime-get-current-candidate context))
 	      (cons 'cursor     "")))
 
-       ((or (= state 'prime-state-modifying)
-	    (= state 'prime-state-segment))
+       ((or (eq? state 'prime-state-modifying)
+	    (eq? state 'prime-state-segment))
 	(let* ((line (prime-context-modification context)))
 	  (list (cons 'segment           (nth 0 line))
 		(cons 'segment-highlight (nth 1 line))
@@ -2026,7 +2026,7 @@
 (define prime-get-candidate-handler
   (lambda (context index-no accel-enum-hint)
     (let ((candidate
-	   (if (= (prime-context-state context) 'prime-state-segment)
+	   (if (eq? (prime-context-state context) 'prime-state-segment)
 	       (nth index-no (prime-context-segment-candidates context))
 	       (nth index-no (prime-context-candidates context)))))
       ;; The return value is a list with a candidate string and the next index.
@@ -2042,18 +2042,18 @@
 	  (state      (prime-context-state context)))
       (if (and prime-custom-display-form?
 	       form
-	       (or (= state 'prime-state-converting)
-		   (= state 'prime-state-segment)))
+	       (or (eq? state 'prime-state-converting)
+		   (eq? state 'prime-state-segment)))
 	  (set! string (string-append string "  (" form ")")))
       (if (and prime-custom-display-usage?
 	       usage
-	       (or (= state 'prime-state-converting)
-		   (= state 'prime-state-segment)))
+	       (or (eq? state 'prime-state-converting)
+		   (eq? state 'prime-state-segment)))
 	  (set! string (string-append string "\t▽" usage)))
       (if (and prime-custom-display-comment?
 	       comment
-	       (or (= state 'prime-state-converting)
-		   (= state 'prime-state-segment)))
+	       (or (eq? state 'prime-state-converting)
+		   (eq? state 'prime-state-segment)))
 	  (set! string (string-append string "\t<" comment ">")))
       string)))
 
@@ -2070,7 +2070,7 @@
     (print "prime-set-candidate-index-handler")
     (if (prime-context-session context)
 	(begin
-	  (if (= (prime-context-state context) 'prime-state-segment)
+	  (if (eq? (prime-context-state context) 'prime-state-segment)
 	      (prime-commit-segment-nth context selection-index)
 	      (prime-commit-candidate context selection-index))
 	  (prime-update context)
diff -Nur ./scm/spellcheck.scm ../.r5rs/scm/spellcheck.scm
--- ./scm/spellcheck.scm	2005-03-11 01:26:50.000000000 -0800
+++ ../.r5rs/scm/spellcheck.scm	2005-08-31 21:31:30.000000000 -0700
@@ -141,7 +141,7 @@
 
 (define spell-make-assoc-list
   (lambda (lst)
-	(mapcar 
+	(map 
 	 (lambda (str)
 	   (string-split str "="))
 	 lst)))
@@ -174,7 +174,7 @@
 
 (define spell-parse-cands
   (lambda (cands-string)
-	(mapcar
+	(map
 	 (lambda (str-line)
 	   (string-split str-line "\t"))
 	 (cdr (delq "" (string-split cands-string "\n"))))))
diff -Nur ./sigscheme/debug.c ../.r5rs/sigscheme/debug.c
--- ./sigscheme/debug.c	2005-08-31 20:35:59.000000000 -0700
+++ ../.r5rs/sigscheme/debug.c	2005-08-31 22:21:56.000000000 -0700
@@ -77,19 +77,24 @@
 #define INTERESTINGP(obj)  \
     (CONSP(obj) \
      || (STRINGP(obj) && SCM_STRING_LEN(obj)) \
-     || VECTORP(obj))
+     || CLOSUREP(obj) \
+     || VECTORP(obj) \
+     || VALUEPACKETP(obj))
 #define SCM_INVALID NULL
 #define OCCUPIED(ent)      (!EQ((ent)->key, SCM_INVALID))
 #define HASH_EMPTY(table)  (!(table).used)
-#define DEFINING_DATUM      (-1)
+#define DEFINING_DATUM     (-1)
+#define NONDEFINING_DATUM  0
 #define GET_DEFINDEX(x)    ((unsigned)(x) >> 1)
+#define HASH_INSERT    1 /* insert key if it's not registered yet */
+#define HASH_FIND      0
 #endif /* SCM_USE_SRFI38 */
 
 /*=======================================
   Variable Declarations
 =======================================*/
 #if SCM_USE_SRFI38
-static write_ss_context *write_ss_ctx; /* list of shared structures in the object we're writing out */
+static write_ss_context *write_ss_ctx; /* misc info in priting shared structures */
 #endif
 
 /*=======================================
@@ -105,7 +110,7 @@
 
 #if SCM_USE_SRFI38
 static void hash_grow(hash_table *tab);
-static hash_entry *hash_lookup(hash_table *tab, ScmObj key, int insert);
+static hash_entry *hash_lookup(hash_table *tab, ScmObj key, int datum, int flag);
 static void write_ss_scan(ScmObj obj, write_ss_context *ctx);
 static int  get_shared_index(ScmObj obj);
 #endif /* SCM_USE_SRFI38 */
@@ -406,17 +411,13 @@
     size_t new_size = old_size * 2;
     size_t i;
     hash_entry *old_ents = tab->ents;
-    hash_entry *new_ent;
 
     tab->ents = calloc(new_size, sizeof(hash_entry));
     tab->size = new_size;
+    tab->used = 0;
 
-    for (i=0; i < old_size; i++) {
-        /* Don't change the last argument, or hash_lookup() will call
-         * us again. */
-        new_ent = hash_lookup(tab, old_ents[i].key, 0);
-        *new_ent = old_ents[i];
-    }
+    for (i=0; i < old_size; i++)
+        hash_lookup(tab, old_ents[i].key, old_ents[i].datum, HASH_INSERT);
 
     free (old_ents);
 }
@@ -424,7 +425,7 @@
 /**
  * @return A pointer to the entry, or NULL if not found.
  */
-static hash_entry *hash_lookup(hash_table *tab, ScmObj key, int insert)
+static hash_entry *hash_lookup(hash_table *tab, ScmObj key, int datum, int flag)
 {
     size_t i;
     unsigned hashval;
@@ -450,14 +451,14 @@
     for (i=0; i < tab->size; i++) {
         ent = &(tab->ents)[(hashval + i) & (tab->size - 1)];
         if (!OCCUPIED(ent)) {
-            if (insert) {
-                /* used > size * 2/3 --> overpopulated, grow table */
-                if (tab->used * 3 > tab->size * 2) {
-                    hash_grow(tab);
-                    return hash_lookup(tab, key, 1);
-                }
+            if (flag & HASH_INSERT) {
                 ent->key = key;
+                ent->datum = datum;
                 tab->used++;
+
+                /* used > size * 2/3 --> overpopulated */
+                if (tab->used * 3 > tab->size * 2)
+                    hash_grow(tab);
             }
             return NULL;
         }
@@ -480,7 +481,7 @@
     hash_entry *ent;
     /* (for-each mark-as-seen-or-return-if-familiar obj) */
     while (CONSP(obj)) {
-        ent = hash_lookup(&ctx->seen, obj, 1);
+        ent = hash_lookup(&ctx->seen, obj, NONDEFINING_DATUM, HASH_INSERT);
         if (ent) {
             ent->datum = DEFINING_DATUM;
             return;
@@ -489,22 +490,30 @@
         obj = CDR(obj);
     }
 
-    if (VECTORP(obj)) {
-        ent = hash_lookup(&ctx->seen, obj, 1);
+    if (INTERESTINGP(obj)) {
+        ent = hash_lookup(&ctx->seen, obj, NONDEFINING_DATUM, HASH_INSERT);
         if (ent) {
             ent->datum = DEFINING_DATUM;
             return;
         }
-        for (i=0; i < SCM_VECTOR_LEN(obj); i++)
-            write_ss_scan(SCM_VECTOR_CREF(obj, i), ctx);
-        return;
-    }
-    if (STRINGP(obj) && SCM_STRING_LEN(obj)) {
-        ent = hash_lookup(&ctx->seen, obj, 1);
-	if (ent) {
-	    ent->datum = DEFINING_DATUM;
-	    return;
-	}
+        switch (SCM_TYPE(obj)) {
+        case ScmClosure:
+            /* We don't need to track env because it's not printed anyway. */
+            write_ss_scan(SCM_CLOSURE_EXP(obj), ctx);
+            break;
+
+        case ScmValuePacket:
+            write_ss_scan(SCM_VALUEPACKET_VALUES(obj), ctx);
+            break;
+
+        case ScmVector:
+            for (i=0; i < SCM_VECTOR_LEN(obj); i++)
+                write_ss_scan(SCM_VECTOR_CREF(obj, i), ctx);
+            break;
+
+        default:
+            break;
+        }
     }
 }
 
@@ -519,7 +528,7 @@
     hash_entry *ent;
 
     if (write_ss_ctx) {
-        ent = hash_lookup(&write_ss_ctx->seen, obj, 0);
+        ent = hash_lookup(&write_ss_ctx->seen, obj, 0, HASH_FIND);
 
         if (ent->datum == DEFINING_DATUM) {
             ent->datum = write_ss_ctx->next_index++;
diff -Nur ./sigscheme/test/test-srfi38.scm ../.r5rs/sigscheme/test/test-srfi38.scm
--- ./sigscheme/test/test-srfi38.scm	1969-12-31 16:00:00.000000000 -0800
+++ ../.r5rs/sigscheme/test/test-srfi38.scm	2005-08-31 20:01:04.000000000 -0700
@@ -0,0 +1,21 @@
+;; No assertive tests for now, just print something and see if we bloat.
+;(load "test/unittest.scm")
+
+(let* ((s "abc")
+       (convolution `(,s 1 #(,s b) (2) () ,s)))
+  ; go crazy with mutators
+  (set-car! (cdr convolution) convolution)
+  (vector-set! (caddr convolution) 1 (cddr convolution))
+  (set-cdr! (cadddr convolution) (cdr convolution))
+  (write-with-shared-structure convolution))
+(display " <-- computed output\n")
+(display "#1=(#2=\"abc\" . #3=(#1# . #4=(#(#2# #4#) (2 . #3#) () #2#))) <-- expected output\n")
+
+(let* ((a-pair '(kar . kdr))
+	     (convolution (eval (list 'lambda () a-pair) (scheme-report-environment 5))))
+	(set-cdr! a-pair convolution)
+	(write-with-shared-structure convolution))
+(display " <-- computed output\n")
+(display "#1=#<closure:(() (kar . #1#))> <-- expected output\n")
+
+;(total-report)
diff -Nur ./uim/uim.c ../.r5rs/uim/uim.c
-------------- next part --------------
--- ./uim/uim.c	2005-08-31 20:36:00.000000000 -0700
+++ ../.r5rs/uim/uim.c	2005-09-01 01:45:32.000000000 -0700
@@ -97,9 +97,9 @@
 static void
 put_context_id(uim_context uc)
 {
-  UIM_LOCK_MUTEX(context_array_mtx);
+  if (!UIM_ATOMIC(uc)) UIM_LOCK_MUTEX(context_array_mtx);
   context_array[uc->id] = NULL;
-  UIM_UNLOCK_MUTEX(context_array_mtx);
+  if (!UIM_ATOMIC(uc)) UIM_UNLOCK_MUTEX(context_array_mtx);
 }
 
 uim_context
@@ -289,9 +289,11 @@
 uim_context
 uim_find_context(int id)
 {
-  UIM_LOCK_MUTEX(context_array_mtx);
-  return context_array[id];
-  UIM_UNLOCK_MUTEX(context_array_mtx);
+  uim_context ret;
+  if (!UIM_ATOMIC(ret)) UIM_LOCK_MUTEX(context_array_mtx);
+  ret = context_array[id];
+  if (!UIM_ATOMIC(ret)) UIM_UNLOCK_MUTEX(context_array_mtx);
+  return ret;
 }
 
 int


Anthy-dev メーリングリストの案内
Back to archive index