From hoan at ton-that.org Wed Jun 7 10:55:17 2006 From: hoan at ton-that.org (Hoan Ton-That) Date: Wed, 7 Jun 2006 20:55:17 +1000 Subject: [cl-stm-devel] CL-STM started Message-ID: Hello! CL-STM has started, you can check it out with: darcs get http://common-lisp.net/project/cl-stm I've only implemented basic transaction logs. You can read, write transaction variables and commit them. Its not very much. I'm currently stuck on a circular bug with the MOP. Hoan From hoan at ton-that.org Sun Jun 11 13:00:00 2006 From: hoan at ton-that.org (Hoan Ton-That) Date: Sun, 11 Jun 2006 23:00:00 +1000 Subject: [cl-stm-devel] Transactional classes Message-ID: Hello again! I'll keep this short as it is getting late over here. Here is a recap of what has been happening. We define new classes with a `deftransactional-class' form. (deftransactional-class foo () ((a :initarg :a :accessor a))) Slots are automatically kept track of. Whenever we read or write to them, the changes are intercepted with the MOP's `slot-value-using-class'. We write it to the current transaction log, to be committed later. Today I worked on composing transactions. I've made them compose sequentially. Alternate composition is a while off. I think I need to make nested transactions possible first. I'll abruptly end now. Remember, to get the latest: darcs get http://common-lisp.net/project/cl-stm or alternatively browse it on the web at: http://common-lisp.net/cgi-bin/darcsweb/darcsweb.cgi?r=cl-stm%20cl-stm;a=summary Hoan From hoan at ton-that.org Wed Jun 14 07:56:28 2006 From: hoan at ton-that.org (Hoan Ton-That) Date: Wed, 14 Jun 2006 17:56:28 +1000 Subject: [cl-stm-devel] Example code Message-ID: Hey again, Here is a little example of CL-STM in action. ;; This is just like `defclass', but the slots are transactional. ;; Reading and writing will be done to the transaction log, to be ;; commited later. STM> (deftransactional-class counter () ((count :accessor count-of :initarg :count :initform 0))) COUNTER STM> (defvar *counter* (new 'counter)) # ;; Notice, that the slot value is actually a transactional variable. STM> (count-of *counter*) # ;; This is the real value of it, which corresponds to the initform. STM> (value-of (count-of *counter*)) 0 ;; `deftransaction' is just like `defun', but when passed arguments, ;; it returns a transaction to be executed by atomic. STM> (deftransaction increment (counter) (incf (count-of counter))) INCREMENT ;; Here is the transaction. Transactions can be composed sequentially ;; and alternatively. STM> (increment *counter*) # ;; But, we'll just run it for now in a separate thread. STM> (atomic (increment *counter*)) # ;; When commiting, we try to lock each transactional variable. Then ;; we check to see if the variables read in the transaction are the ;; same as the real ones. Then we update the real value. Any threads ;; that are waiting for the variable to change are woken up. ;; Regardless of what happens, the acquired locks are always released. --TIME MARK 2006-06-14-- 17:34 STM-LOGGER/+DRIBBLE+: Committing transaction 17:34 STM-LOGGER/+DRIBBLE+: Acquired lock # 17:34 STM-LOGGER/+DRIBBLE+: Version 0 is valid 17:34 STM-LOGGER/+DRIBBLE+: Value updated to 1 17:34 STM-LOGGER/+DRIBBLE+: Version updated to 1 17:34 STM-LOGGER/+DRIBBLE+: Notified threads waiting on # 17:34 STM-LOGGER/+DRIBBLE+: Transaction log committed 17:34 STM-LOGGER/+DRIBBLE+: Released lock # ;; We'll acquire the lock of the variable STM> (acquire-lock (lock-of (count-of *counter*))) T ;; And we'll run the transaction again. This time you can see that ;; the lock couldn't be acquired and so the transaction wasn't ;; committed. However, the thread is still running, waiting for the ;; variable to change and have another go committing. STM> (atomic (increment *counter*)) # 17:34 STM-LOGGER/+DRIBBLE+: Committing transaction 17:34 STM-LOGGER/+DRIBBLE+: Couldn't acquire lock # 17:34 STM-LOGGER/+DRIBBLE+: Transaction log not commited ;; Now we release the lock STM> (release-lock (lock-of (count-of *counter*))) NIL ;; These are the current transaction logs waiting for the ;; variable/slot `count'. STM> (waiting-for (count-of *counter*)) (#) ;; Now we wake them up! As you can see the previous transaction that ;; failed is rerun again, and this time it succeeds! STM> (mapc #'unwait (waiting-for (count-of *counter*))) (#) 17:34 STM-LOGGER/+DRIBBLE+: Committing transaction 17:34 STM-LOGGER/+DRIBBLE+: Acquired lock # 17:34 STM-LOGGER/+DRIBBLE+: Version 1 is valid 17:34 STM-LOGGER/+DRIBBLE+: Value updated to 2 17:34 STM-LOGGER/+DRIBBLE+: Version updated to 2 17:34 STM-LOGGER/+DRIBBLE+: Notified threads waiting on # 17:34 STM-LOGGER/+DRIBBLE+: Transaction log committed 17:34 STM-LOGGER/+DRIBBLE+: Released lock # ;; And now we've atomically incremented the counter twice. Phew! STM> (value-of (count-of *counter*)) 2 Hoan From fahree at gmail.com Wed Jun 14 10:06:54 2006 From: fahree at gmail.com (=?ISO-8859-1?Q?Far=E9?=) Date: Wed, 14 Jun 2006 06:06:54 -0400 Subject: [cl-stm-devel] Example code In-Reply-To: References: Message-ID: <653bea160606140306m2cbf7e53pac791f791189f796@mail.gmail.com> On 14/06/06, Hoan Ton-That wrote: > Hey again, > > Here is a little example of CL-STM in action. (1) Doesn't having to acquire a global lock defeat the purpose of so-called lightweight transaction commits and just open the system to live-locks? (Certainly locks can be detected by a monitor, but the locking needed to properly update dependency meta-information in presence of the monitor only shuffles around the complexity of dependency information maintenance.) (2) A minor non-urgent style issue: wouldn't it be nice to use a regular MOP-enabled defclass with a proper metaclass (or metaclass mixin) rather than use a special purpose deftransactional-class? Are other people on this list familiar with the MOP, and what do they think of it? [ Fran?ois-Ren? ?VB Rideau | Reflection&Cybernethics | http://fare.tunes.org ] No man would listen to you talk if he didn't know it was his turn next. -- Edgar Watson Howe From hoan at ton-that.org Wed Jun 14 13:16:53 2006 From: hoan at ton-that.org (Hoan Ton-That) Date: Wed, 14 Jun 2006 23:16:53 +1000 Subject: [cl-stm-devel] Example code In-Reply-To: <653bea160606140306m2cbf7e53pac791f791189f796@mail.gmail.com> References: <653bea160606140306m2cbf7e53pac791f791189f796@mail.gmail.com> Message-ID: Far?, > (1) Doesn't having to acquire a global lock defeat the purpose of > so-called lightweight transaction commits and just open the system to > live-locks? (Certainly locks can be detected by a monitor, but the > locking needed to properly update dependency meta-information in > presence of the monitor only shuffles around the complexity of > dependency information maintenance.) Locks are used for mutual exclusion purposes. They are allocated per-slot, per-instance--there is no one global lock. I could be misunderstanding you here... > (2) A minor non-urgent style issue: wouldn't it be nice to use a > regular MOP-enabled defclass with a proper metaclass (or metaclass > mixin) rather than use a special purpose deftransactional-class? Are > other people on this list familiar with the MOP, and what do they > think of it? The `deftransactional-class' is just a wrapper macro for `defclass' adding the metaclass option. Admittedly, its a bad name--if anyone could come up with a better one, I'd be glad to use it. I'll sleep on it. Zzz... Hoan From hoan at ton-that.org Fri Jun 30 11:23:29 2006 From: hoan at ton-that.org (Hoan Ton-That) Date: Fri, 30 Jun 2006 21:23:29 +1000 Subject: [cl-stm-devel] Counter example Message-ID: Hey folks, Transactions can be parametrized by other transactions. For testing purposes we may want a transaction to pause for two seconds after its calculation. We can define a higher order transaction that does this: (deftransaction sleep-after (seconds transaction) transaction (trans (sleep seconds))) With the counter example loaded (the source can be found in src/examples/counter.lisp) we can now see what happens when two transactions conflict. STM> (defvar *counter* (new 'counter)) *COUNTER* STM> (progn (perform (sleep-after 2 (increment *counter*))) (perform (sleep-after 2 (increment *counter*)))) [debugging output elided...] STM> (value-of (count-of *counter*)) 2 STM> If you looked at the debugging output you would see one of the transactions has retried due to an inconsistent log. I'm sorry that I haven't been posting regularly, but I've been making steady progress. I'm managing to work on it, however small everyday. I'll be posting more regularly this week with snippets like these. Hoan