Commit bc4b0f34 authored by David Byers's avatar David Byers
Browse files

New data structure for membership list

Detailed changes:
> 2004-07-18  David Byers  <byers@lysator.liu.se>
>
> 	New membership list data structure:
> 	* mship-edit.el (lyskom-change-membership-priority): New API for
> 	lyskom-replace-membership.
> 	(lyskom-change-membership-position): Ditto.
> 	(lyskom-prioritize-flag-toggle): Ditto.
> 	(lp--set-entry-pri-and-pos): Ditto. Set position correctly.
>
> 	* macros.el (lyskom-traverse-membership): New implementation.
>
> 	* reading.el: New implementation of the sorted conference list.
> 	Using AVL trees ended up causing too much trouble when changing
> 	position and priority of memberships.
> 	(mship-list-node): New type.
> 	(membership-list): New type.
> 	(lyskom-membership-list-compare-next): New function (internal)
> 	(lyskom-membership-list-compare-prev): New function (internal)
> 	(lyskom-membership-list-insert): New function (API)
> 	(lyskom-membership-list-prepend): New function (internal)
> 	(lyskom-membership-list-append): New function (internal)
> 	(lyskom-membership-list-delete): New function (API)
> 	(lyskom-membership-list-move): New function (API)
> 	(lyskom-mship-cache-create): Don't use AVL trees.
> 	(lyskom-mship-cache-get): Now returns mship-list-nodes.
> 	(lyskom-mship-cache-put): Don't use AVL trees.
> 	(lyskom-mship-cache-append): New function (internal)
> 	(lyskom-mship-cache-del): Don't use AVL trees.
> 	(lyskom-update-membership-positions): Do nothing.
> 	(lyskom-add-memberships-to-membership): Append memberships
> 	(lyskom-try-get-membership): Deal with a cache that returns
> 	mship-list-nodes instead of memberships.
> 	(lyskom-replace-membership): Function, not macro, again.
> 	(lyskom-membership-<): Removed
>
> 2004-07-16  David Byers  <byers@lysator.liu.se>
>
> 	* reading.el (lyskom-membership-<): If the conf-nos are not the
> 	same, always return t.
>
1a42,45
>
> 	* commands1.el (lyskom-add-member): Delete the new conference from
> 	the to-do-list so we get the correct number of unread when
> 	accepting an invitation.
parent a2376eaf
2004-07-18 David Byers <byers@lysator.liu.se>
New membership list data structure:
* mship-edit.el (lyskom-change-membership-priority): New API for
lyskom-replace-membership.
(lyskom-change-membership-position): Ditto.
(lyskom-prioritize-flag-toggle): Ditto.
(lp--set-entry-pri-and-pos): Ditto. Set position correctly.
* macros.el (lyskom-traverse-membership): New implementation.
* reading.el: New implementation of the sorted conference list.
Using AVL trees ended up causing too much trouble when changing
position and priority of memberships.
(mship-list-node): New type.
(membership-list): New type.
(lyskom-membership-list-compare-next): New function (internal)
(lyskom-membership-list-compare-prev): New function (internal)
(lyskom-membership-list-insert): New function (API)
(lyskom-membership-list-prepend): New function (internal)
(lyskom-membership-list-append): New function (internal)
(lyskom-membership-list-delete): New function (API)
(lyskom-membership-list-move): New function (API)
(lyskom-mship-cache-create): Don't use AVL trees.
(lyskom-mship-cache-get): Now returns mship-list-nodes.
(lyskom-mship-cache-put): Don't use AVL trees.
(lyskom-mship-cache-append): New function (internal)
(lyskom-mship-cache-del): Don't use AVL trees.
(lyskom-update-membership-positions): Do nothing.
(lyskom-add-memberships-to-membership): Append memberships
(lyskom-try-get-membership): Deal with a cache that returns
mship-list-nodes instead of memberships.
(lyskom-replace-membership): Function, not macro, again.
(lyskom-membership-<): Removed
2004-07-16 David Byers <byers@lysator.liu.se>
* reading.el (lyskom-membership-<): If the conf-nos are not the
same, always return t.
2004-07-15 David Byers <byers@lysator.liu.se>
* commands1.el (lyskom-add-member): Delete the new conference from
the to-do-list so we get the correct number of unread when
accepting an invitation.
* startup.el (lyskom-refetch): Prefetch membership *after*
prefetching unread confs. This should let us get started reading
just a little quicker.
......
......@@ -70,9 +70,6 @@ LANGUAGE-EL := $(LANGUAGES:=-strings.el) $(LANGUAGES:=-help.el)
# Finally, other source files.
SOURCES = komtypes.el \
clienttypes.el \
elib-node.el \
stack-m.el \
avltree.el \
faces.el \
deferred-insert.el \
utilities.el \
......
......@@ -794,6 +794,7 @@ be called from a callback."
lyskom-pers-no
(conf-stat->conf-no whereto)
t 0)))
(read-list-delete-read-info (conf-stat->conf-no whereto) lyskom-to-do-list)
(if (< (membership->priority mship) lyskom-session-priority)
(lyskom-format-insert-before-prompt
'member-in-conf-with-low-priority
......@@ -803,9 +804,7 @@ be called from a callback."
(if (lyskom-try-get-membership (conf-stat->conf-no whereto) t)
(progn (lyskom-replace-membership mship)
(lyskom-fetch-start-of-map whereto mship))
(lyskom-add-membership mship
whereto
t))))
(lyskom-add-membership mship whereto t))))
(lp--update-buffer (conf-stat->conf-no whereto)))
(lyskom-insert-string 'done))))))))
became-member))
......
......@@ -617,6 +617,7 @@ Read all about it at http://www.lysator.liu.se/history/")
(pers-is-not-member-of-conf . "No, %#1P is not a member of the conference %#2M.\n")
(pers-is-member-of-conf-2 . "Number of unread: %#2D (last access %#1s)\n")
(pers-will-receive-async . "Reception of group messages %#1?b%[enabled%]%[disabled%]\n")
(pers-mship-priority . "Membership priority: %#1d\n")
(Unknown-number . "Unknown number")
(text-to-check-will-read-for . "...for membership in recipients of text: ")
(pers-to-check-will-read-for . "Person to check: ")
......@@ -789,7 +790,9 @@ The message you were sending to %#1M was:
(Author . "Author")
(Subject . "Subject")
(Comments . "Co")
(Num-marks . "Mk")
(mark-type . "Type")
(mark-no . "Mrk")
(could-not-read . "You couldn't read the text (%#1n).\n")
(multiple-choice . "There are several alternatives.")
......
......@@ -70,12 +70,20 @@ Value returned is always nil."
,@body
(setq ,idx-sym (1+ ,idx-sym))))))))
(defmacro lyskom-traverse-membership (var &rest forms)
"Traverse the membership list.
Variable VAR is bound to each membership, in turn, and FORMS are evaluated."
`(catch 'lyskom-traverse
(lyskom-avltree-traverse
(lambda (,var) ,@forms) (lyskom-with-lyskom-buffer (lyskom-mship-cache-data)))))
(let ((el-sym (make-symbol "el")))
`(catch 'lyskom-traverse
(let ((,el-sym (membership-list->head
(lyskom-with-lyskom-buffer (lyskom-mship-cache-data))))
(,var nil))
(while ,el-sym
(setq ,var (mship-list-node->data ,el-sym))
,@forms
(setq ,el-sym (mship-list-node->next ,el-sym)))))))
(defmacro lyskom-traverse-aux (atom sequence &rest body)
"Bind ATOM to each element in SEQUENCE and execute BODY.
......
......@@ -159,8 +159,8 @@ This function does not tell the server about the change."
(let* ((mship (lyskom-get-membership conf-no t))
(old-priority (and mship (membership->priority mship))))
(when mship
(lyskom-replace-membership mship
(set-membership->priority mship new-priority))
(set-membership->priority mship new-priority)
(lyskom-replace-membership mship)
(cond
((and (>= old-priority lyskom-session-priority)
......@@ -183,11 +183,11 @@ This function does not tell the server about the change."
(defun lyskom-change-membership-position (conf-no new-position)
"Change the position of memberhip for CONF-NO to NEW-POSITION.
This function does not tell the server about the change."
(let ((mship (lyskom-get-membership conf-no t)))
(let* ((mship (lyskom-get-membership conf-no t))
(old-position (membership->position mship)))
(when mship
(lyskom-replace-membership mship
(set-membership->position mship new-position))
(lyskom-update-membership-positions))))
(set-membership->position mship new-position)
(lyskom-replace-membership mship))))
;;; ============================================================
......@@ -1082,14 +1082,15 @@ lp--update-membership is called automatically before this function exits."
(old-pos (lp--entry-position entry))
(lp--inhibit-update t)
(need-redraw nil))
(lyskom-replace-membership (lp--entry->membership entry)
(when (and priority (not (eq priority old-pri)))
(set-lp--entry->priority entry priority)
(set-membership->priority (lp--entry->membership entry) priority)
(setq need-redraw t))
(when (and position (not (eq position old-pos)))
(lp--move-entry entry position)
(setq need-redraw nil)))
(when (and priority (not (eq priority old-pri)))
(set-lp--entry->priority entry priority)
(set-membership->priority (lp--entry->membership entry) priority)
(setq need-redraw t))
(when (and position (not (eq position old-pos)))
(lp--move-entry entry position)
(set-membership->position (lp--entry->membership entry) position)
(setq need-redraw nil))
(lyskom-replace-membership (lp--entry->membership entry))
(sit-for 0)
(lp--update-membership entry old-pri old-pos)
(when need-redraw (lp--redraw-entry entry))))
......
......@@ -108,7 +108,271 @@ reasonable guess."
;;; ================================================================
;;; Fundamental membership cache functions
;;; (require 'lyskom-avltree)
(def-komtype mship-list-node (prev next data))
(def-komtype membership-list ((head :automatic nil)
(tail :automatic nil)
(size :automatic 0)))
;;; (def-komtype smship (id priority position))
;;; ----------------------------------------------------------------
;;; INSERTION FUNCTIONS
;;;
;;; There are three functions for inserting memberships into a list.
;;;
;;; Use lyskom-membership-list-insert when inserting memberships in
;;; random order. It uses a heuristic based on the priority of the
;;; membership to determine whether to search from the front of back
;;; of the list.
;;;
;;; Use lyskom-membership-list-append when you know that the position
;;; of the membership is towards the end of the list.
;;;
;;; Use lyskom-membership-list-prepend when you know that the position
;;; of the membership is towards the front of the list.
;;;
;;;
;;; The heuristic is optimized for randomly inserting memberships. If
;;; the list is near-full and a single membership is to be inserted,
;;; other heuristics might perform better. If the approximate position
;;; of the membership is already known, this heuristic is not the best.
;;;
(defun lyskom-membership-list-compare-next (mship next &optional after)
(and next
(or (> (membership->priority (mship-list-node->data next))
(membership->priority mship))
(and (= (membership->priority (mship-list-node->data next))
(membership->priority mship))
(membership->position mship)
(if after
(>= (membership->position mship)
(membership->position (mship-list-node->data next)))
(> (membership->position mship)
(membership->position (mship-list-node->data next))))))))
(defun lyskom-membership-list-compare-prev (mship prev)
(and prev
(or (< (membership->priority (mship-list-node->data prev))
(membership->priority mship))
(and (= (membership->priority (mship-list-node->data prev))
(membership->priority mship))
(membership->position mship)
(<= (membership->position mship)
(membership->position (mship-list-node->data prev)))))))
(defun lyskom-membership-list-insert (mship-list mship)
"Insert a new membership MSHP into MSHIP-LIST."
(if (and (membership-list->head mship-list)
(membership-list->tail mship-list)
(< (- (membership->priority mship)
(membership->priority (mship-list-node->data (membership-list->head mship-list))))
(- (membership->priority (mship-list-node->data (membership-list->tail mship-list)))
(membership->priority mship))))
(lyskom-membership-list-append mship-list mship)
(lyskom-membership-list-prepend mship-list mship)))
(defun lyskom-membership-list-prepend (mship-list mship)
"Insert new membership MSHIP into MSHIP-LIST."
(let ((cur (membership-list->head mship-list))
(prev nil))
;; Search for the element in the list at which we want to insert
;; the new membership.
(while (lyskom-membership-list-compare-next mship cur)
(setq prev cur cur (mship-list-node->next cur)))
(let ((new (lyskom-create-mship-list-node prev cur mship)))
;; Set the position of the membership
;;
;; If it already has a position that is between the positions of cur and prev
;; then we do not alter that position. If it has some other position or no
;; position, set its position to the position of cur (which is appropriate
;; when adding a new membership). We do this even if there is room between
;; prev and cur since such a hole probably indicates that we haven't gotten
;; the entire membership from the server -- once we have all memberships there
;; shouldn't be any holes left.
(if (or (null (membership->position mship))
(<= (membership->position mship)
(if prev (membership->position (mship-list-node->data prev)) -1))
(>= (membership->position mship)
(if cur (membership->position (mship-list-node->data cur)) lyskom-max-int)))
(set-membership->position mship
(cond (cur (membership->position (mship-list-node->data cur)))
(prev (1+ (membership->position (mship-list-node->data prev))))
(t 0))))
;; If cur is nil, then we want to insert at the end of the list
;; If prev is nil, then we want to insert at the beginning of the list
;; If both are nil, the list is empty and we are inserting the first element
(if prev
(set-mship-list-node->next prev new)
(set-membership-list->head mship-list new))
(if cur
(set-mship-list-node->prev cur new)
(set-membership-list->tail mship-list new))
(setq prev new)
;; If the position we chose for the new element collides with the position of
;; the element following it, we adjust the positions of following elements
;; until all elements again have unique positions.
(while (and cur (eq (membership->position (mship-list-node->data prev))
(membership->position (mship-list-node->data cur))))
(set-membership->position (mship-list-node->data cur)
(1+ (membership->position (mship-list-node->data cur))))
(setq prev cur cur (mship-list-node->next cur)))
(set-membership-list->size mship-list (1+ (membership-list->size mship-list)))
new)))
(defun lyskom-membership-list-append (mship-list mship)
"Like lyskom-insert-membership, but searches from the end of the list"
(let ((cur (membership-list->tail mship-list))
(prev nil))
(while (lyskom-membership-list-compare-prev mship cur)
(setq prev cur cur (mship-list-node->prev cur)))
(let ((new (lyskom-create-mship-list-node cur prev mship)))
;; Set the position of the membership
;;
;; If it already has a position that is available and between the
;; positions of the current and previous elements, then use that.
;; If not, use the position of the previous element (after it in
;; the list). If there isn't one, use one plus the position of the
;; last element in the list. If the list is empty, set position to
;; zero.
(if (or (null (membership->position mship))
(<= (membership->position mship)
(if cur (membership->position (mship-list-node->data cur)) -1))
(>= (membership->position mship)
(if prev (membership->position (mship-list-node->data prev)) lyskom-max-int)))
(set-membership->position mship
(cond (prev (membership->position (mship-list-node->data prev)))
(cur (1+ (membership->position (mship-list-node->data cur))))
(t 0))))
;; If cur is nil, then we want to insert at the end of the list
;; If prev is nil, then we want to insert at the beginning of the list
;; If both are nil, the list is empty and we are inserting the first element
(if cur
(set-mship-list-node->next cur new)
(set-membership-list->head mship-list new))
(if prev
(set-mship-list-node->prev prev new)
(set-membership-list->tail mship-list new))
;; Set up for scanning back to the end of the list to adjust positions
;; of elements that are after the newly inserted element.
(setq prev new cur (mship-list-node->next new))
;; If the position we chose for the new element collides with the position of
;; the element following it, we adjust the positions of following elements
;; until all elements again have unique positions.
(while (and cur (eq (membership->position (mship-list-node->data prev))
(membership->position (mship-list-node->data cur))))
(set-membership->position (mship-list-node->data cur)
(1+ (membership->position (mship-list-node->data cur))))
(setq prev cur cur (mship-list-node->next cur)))
(set-membership-list->size mship-list (1+ (membership-list->size mship-list)))
new)))
(defun lyskom-membership-list-delete (mship-list node)
"Remove NODE from MSHIP-LIST"
(if (mship-list-node->next node)
(set-mship-list-node->prev (mship-list-node->next node)
(mship-list-node->prev node))
(set-membership-list->tail mship-list
(mship-list-node->prev node)))
(if (mship-list-node->prev node)
(set-mship-list-node->next (mship-list-node->prev node)
(mship-list-node->next node))
(set-membership-list->head mship-list (mship-list-node->next node)))
(setq node (mship-list-node->next node))
(while node
(set-membership->position (mship-list-node->data node)
(1- (membership->position (mship-list-node->data node))))
(setq node (mship-list-node->next node)))
(set-membership-list->size mship-list (1- (membership-list->size mship-list))))
(defun lyskom-membership-list-move (mship-list node)
"Move the node NODE in MSHIP-LIST to its new position."
(let* ((prev (mship-list-node->prev node))
(next (mship-list-node->next node))
(mship (mship-list-node->data node))
(new-pos nil))
(cond
((lyskom-membership-list-compare-next mship next t) ; Move right
(setq prev nil)
(while (lyskom-membership-list-compare-next mship next t)
(setq new-pos (membership->position (mship-list-node->data next)))
(set-membership->position (mship-list-node->data next) (1- new-pos))
(setq prev next next (mship-list-node->next next)))
(set-membership->position mship new-pos))
((lyskom-membership-list-compare-prev mship prev) ; Move left
(setq next nil)
(while (lyskom-membership-list-compare-prev mship prev)
(setq new-pos (membership->position (mship-list-node->data prev)))
(set-membership->position (mship-list-node->data prev) (1+ new-pos))
(setq next prev prev (mship-list-node->prev prev)))
(set-membership->position mship new-pos))
(t ; Stay in the same place
(setq prev (mship-list-node->prev node))
(setq next (mship-list-node->next node))
(setq new-pos (membership->position mship))))
;; Remove the node from its current position
(if (mship-list-node->prev node)
(set-mship-list-node->next (mship-list-node->prev node)
(mship-list-node->next node))
(set-membership-list->head mship-list (mship-list-node->next node)))
(if (mship-list-node->next node)
(set-mship-list-node->prev (mship-list-node->next node)
(mship-list-node->prev node))
(set-membership-list->tail mship-list (mship-list-node->prev node)))
;; Splice it into the list at the new position
(set-mship-list-node->prev node prev)
(set-mship-list-node->next node next)
(if prev
(set-mship-list-node->next prev node)
(set-membership-list->head mship-list node))
(if next
(set-mship-list-node->prev next node)
(set-membership-list->tail mship-list node)))
)
;;; ================================================================
;;; The following functions are concerned with managing the cache
(def-kom-var lyskom-mship-cache nil
"Membership cache. Do not alter directly."
......@@ -120,7 +384,7 @@ reasonable guess."
(defun lyskom-mship-cache-create ()
"Initialize the membership cache to empty."
(vector (lyskom-make-hash-table :size 300 :test 'eq)
(lyskom-avltree-create 'lyskom-membership-<)))
(lyskom-create-membership-list)))
(defun lyskom-mship-cache-get (conf-no)
"Get the membership for CONF-NO from the membership cache."
......@@ -128,68 +392,50 @@ reasonable guess."
(defun lyskom-mship-cache-put (mship)
"Add MSHIP to the membership cache."
(lyskom-avltree-enter (lyskom-mship-cache-data) mship)
(lyskom-puthash (membership->conf-no mship) mship (lyskom-mship-cache-index)))
(lyskom-puthash (membership->conf-no mship)
(lyskom-membership-list-insert (lyskom-mship-cache-data) mship)
(lyskom-mship-cache-index)))
(defun lyskom-mship-cache-append (mship)
"Add MSHIP to the membership cache."
(lyskom-puthash (membership->conf-no mship)
(lyskom-membership-list-append (lyskom-mship-cache-data) mship)
(lyskom-mship-cache-index)))
(defun lyskom-mship-cache-del (conf-no)
"Delete CONF-NO from the membership cache."
(let ((mship (lyskom-mship-cache-get conf-no)))
(when mship
(lyskom-avltree-delete (lyskom-mship-cache-data) mship)
(let ((node (lyskom-mship-cache-get conf-no)))
(when node
(lyskom-membership-list-delete (lyskom-mship-cache-data) node)
(lyskom-remhash conf-no (lyskom-mship-cache-index)))))
(defun lyskom-update-membership-positions ()
"Update the position field of all memberships."
(let ((num 0))
(lyskom-avltree-traverse (lambda (mship)
(set-membership->position mship num)
(setq num (1+ num)))
(lyskom-mship-cache-data))))
(defun lyskom-add-memberships-to-membership (memberships)
"Adds a newly fetched MEMBERSHIP-PART to the list in lyskom-membership.
If an item of the membership is already read and entered in the
lyskom-membership list then this item is not entered."
"Adds newly fetched MEMBERSHIPS to the membership list."
(lyskom-with-lyskom-buffer
(lyskom-traverse mship memberships
(unless (lyskom-mship-cache-get (membership->conf-no mship))
(lyskom-mship-cache-put mship)))))
(lyskom-mship-cache-append mship)))))
(defun lyskom-insert-membership (mship)
"Add MSHIP into lyskom-membership, sorted by priority."
(lyskom-with-lyskom-buffer
(lyskom-mship-cache-put mship)
(lyskom-update-membership-positions)
(lp--update-buffer (membership->conf-no mship))))
(defmacro lyskom-replace-membership (mship &rest body)
"Replace the membership MSHIP while evaluating BODY.
This function should be used when altering the priority or position of
a membership. The membership is removed from the cache, then BODY is
evaluated and finally the membership is inserted into the cache again.
Note that altering the priority or position without first removing the
membership from the cache may render it impossible to remove it later."
`(progn
(lyskom-with-lyskom-buffer
(when (lyskom-mship-cache-get (membership->conf-no ,mship))
(lyskom-mship-cache-del (membership->conf-no ,mship))))
,@body
(lyskom-with-lyskom-buffer
(lyskom-mship-cache-put ,mship)
(lyskom-update-membership-positions)
(lp--update-buffer (membership->conf-no ,mship)))))
(put 'lyskom-replace-membership 'lisp-indent-hook 1)
(put 'lyskom-replace-membership 'edebug-form-spec '(sexp body))
(defun lyskom-replace-membership (mship)
"Replace the membership MSHIP."
(lyskom-with-lyskom-buffer
(let ((node (lyskom-mship-cache-get (membership->conf-no mship))))
(if node
(lyskom-membership-list-move (lyskom-mship-cache-data) node)
(lyskom-mship-cache-put mship)))
(lp--update-buffer (membership->conf-no mship))))
(defun lyskom-remove-membership (conf-no)
"Remove the membership for CONF-NO from lyskom-membership."
(lyskom-with-lyskom-buffer
(lyskom-mship-cache-del conf-no)
(lyskom-update-membership-positions)
(lp--update-buffer conf-no)))
(defun lyskom-membership-position (conf-no)
......@@ -205,19 +451,7 @@ membership from the cache may render it impossible to remove it later."
(defun lyskom-membership-length ()
"Return the size of the membership list."
(lyskom-avltree-size (lyskom-mship-cache-data)))
(defun lyskom-membership-< (a b)
"Retuns t if A has a higher priority than B. A and B are memberships."
(cond ((> (membership->priority a)
(membership->priority b)) t)
((and (= (membership->priority a)
(membership->priority b))
(numberp (membership->position a))
(numberp (membership->position b)))
(< (membership->position a)
(membership->position b)))
(t nil)))
(membership-list->size (lyskom-mship-cache-data)))
(defun lyskom-get-membership (conf-no &optional want-passive)
"Return membership for conference CONF-NO.
......@@ -245,6 +479,85 @@ This call does not block. If the membership has not been cached, this
call will return nil."
(lyskom-with-lyskom-buffer
(let ((mship (lyskom-mship-cache-get conf-no)))
(when (or want-passive (not (membership-type->passive (membership->type mship))))
mship))))
(when (and mship
(or want-passive
(not (membership-type->passive
(membership->type
(mship-list-node->data mship))))))
(mship-list-node->data mship)))))
;;; ================================================================
;;; Testing
;;;(defun lps (l)
;;; (let ((cur (membership-list->head l))
;;; res)
;;; (while cur
;;; (setq res (cons (cons (smship->id (mship-list-node->data cur))
;;; (smship->position (mship-list-node->data cur)))
;;; res)
;;; cur (mship-list-node->next cur)))
;;; (nreverse res)))
;;;
;;;
;;;
;;;(progn (setq l (lyskom-create-membership-list))
;;;(setq a (lyskom-create-smship 'a 255 0))
;;;(setq b (lyskom-create-smship 'b 100 1))
;;;(setq c (lyskom-create-smship 'c 100 2))
;;;(setq d (lyskom-create-smship 'd 100 3))
;;;(setq e (lyskom-create-smship 'e 50 4))
;;;(setq f (lyskom-create-smship 'f 50 5))
;;;(setq g (lyskom-create-smship 'g 20 6))
;;;(setq h (lyskom-create-smship 'h 1 7)))
;;;
;;;(setq x (lyskom-create-smship 'x 100 nil))
;;;
;;;(mapcar (lambda (el) (lyskom-membership-list-insert l el)) (list c g f b d a x))
;; (let ((mx 0)
;; (times nil))
;; (while (<= mx 500)
;; ; (garbage-collect)
;; (message "%d" mx)
;; (let ((enter-time nil)
;; (exit-time nil)
;; (l (lyskom-create-membership-list))
;; (i 0)
;; (x 0)