Next: , Previous: Persistent Classes, Up: Tutorial

2.6 Rules about Persistent Classes

Using the persistent-metaclass metaclass declares all slots to be persistent by default. To make a non-persistent slot use the :transient t flag. Class slots :allocation :class are never persisted, for either persistent or ordinary classes. (Someday, if we choose to store class objects, this policy may change).

Persistent classes may inherit from other classes. Slots inherited from persistent classes remain persistent. Transient slots and slots inherited from ordinary classes remain transient. Ordinary classes cannot inherit from persistent classes – otherwise persistent slots could not be stored!

     (defclass stdclass1 ()
       ((slot1 :initarg :slot1 :accessor slot1)))
     (defclass stdclass2 (stdclass1)
       ((slot2 :initarg :slot2 :accessor slot2)))
     (defpclass pclass1 (stdclass2)
       ((slot1 :initarg :slot1 :accessor slot1)
        (slot3 :initarg :slot3 :accessor slot3)))
     (make-instance 'pclass1 :slot1 1 :slot2 2 :slot3 3)
     => #<PCLASS1 {x10deb88a}>
     (add-to-root 'pinst *)
     => #<PCLASS1 {x10deb88a}>
     (slot1 pinst)
     => 1
     (slot2 pinst)
     => 2
     (slot3 pinst)
     => 3

Now we can simulate a new lisp session by flushing the instance cache, reloading our object then see what slots remain. Here persistent slot1 should shadow the standard slot1 and thus be persistent. Slot3 is persistent by default and slot2, since it is inherited from a standard class should be transient.

     (elephant::flush-instance-cache *store-controller*)
     => #<EQL hash-table with weak values, 0 entries {x11198a02}>
     (setf pinst (get-from-root 'pinst))
     => #<PCLASS1 {x1119b652}>
     (slot1 pinst)
     => 1
     (slot-boundp pinst slot2 pinst)
     => nil
     (slot3 pinst)
     => 3

Using persistent objects has implications for the performance of your system. Note that the database is read every time you access a slot. This is a feature, not a bug, especially in concurrent situations: you want the most recent commits by other threads, right? This can be used as a weak form of IPC. But also note that in particular, if your slot value is not an immediate value or persistent object, reading will cons or freshly allocate storage for the value.

Gets are not an expensive operation; you can perform thousands to tens of thousands of primitive reads per second. However, if you're concerned, cache large values in memory and avoid writing them back to disk as long as you can.