
=====================================================================
                      Copy On Write Shared Memory
=====================================================================

Smart Pointers
--------------

to do COW shared memory, we use smart pointers for the image data.
these are small structures that encapsulate the actual data pointer.
user code obtains and keeps pointers to these structures rather than
the data itself.

a smart pointer never moves after it's been allocated.  however, the
internal variables, including the wrapped data pointer, may change at
any time.  in particular, the piece of memory it points to, or the
location of that memory, may change over time.  always use the macro
wrappers when dealing with a smart pointer.

the smart pointer object has a set of routines which implement a
lifecycle for the data.  this lifecycle is a small state machine.



Lifecycle States
----------------

 UNINIT
  - the smart pointer has not been constructed

 UNALLOC
  - the smart pointer itself is inited, but the encapsulated data
    pointer does not refer to any storage

 SHARABLE
  - the smart pointer refers to storage and will allow other smart
    pointers to refer to it as well

 UNSHARABLE
  - the smart pointer refers to storage but will not allow other smart
    pointers to refer to it.

 SHARED
  - the smart pointer refers to storage which other smart pointers
    also refer to.



Lifecycle State Transitions
---------------------------

UNINIT     -> UNALLOC
  d_init created an SP

UNALLOC    -> UNINIT
  d_uninit destroyed an SP

UNALLOC    -> SHARABLE
  d_alloc reserved storage for the SP

SHARABLE   -> UNALLOC
  d_unalloc killed storage for an SP

SHARABLE   -> SHARABLE
  d_read used an unused/readonly SP
  d_release let go of a readonly SP
  d_split tried to split an unused/readonly SP

SHARABLE   -> UNSHARABLE
  d_write used an unused/readonly SP

SHARABLE   -> SHARED
  d_join added an SP to an unused/readonly SP

UNSHARABLE -> UNSHARABLE
  d_read used a readwrite SP
  d_write used a readwrite SP
  d_release let go of a readwrite SP (not the last use though)
  d_join made a copy of us for the other SP and left us alone
  d_split tried to split a readwrite SP

UNSHARABLE -> SHARABLE
  d_release let go of a readwrite SP (the last use)

SHARED     -> SHARABLE
  d_write made a copy and detached one of our SP, we had 1 left
  d_split made a copy and detached one of our SP, we had 1 left

SHARED     -> SHARED
  d_read used an unused/readonly SP
  d_write made a copy and detached one of our SP, we had 2+ left
  d_release let go of a readonly SP
  d_join added an SP to an unused/readonly SP
  d_split made a copy and detached one of our SP, we had 2+ left

(new)      -> SHARABLE
  d_join made a copy of a readwrite SP and made it sharable
  d_split made a copy of an unused/readonly SP and made it sharable

(new)      -> UNSHARABLE
  d_write made a copy and detached us from our shared memory




Smart Pointer Routines w/ State Transitions
-------------------------------------------

d_init         UNINIT     -> UNALLOC

d_uninit       UNALLOC    -> UNINIT [1]

d_alloc        UNALLOC    -> SHARABLE

d_unalloc      SHARABLE   -> UNALLOC

d_read         SHARABLE   -> SHARABLE
               UNSHARABLE -> UNSHARABLE
               SHARED     -> SHARED

d_write        SHARABLE   -> UNSHARABLE
               UNSHARABLE -> UNSHARABLE
               SHARED     -> SHARED + UNSHARABLE [2]
               SHARED     -> SHARABLE + UNSHARABLE [2]

d_release      SHARABLE   -> SHARABLE
               UNSHARABLE -> UNSHARABLE
               UNSHARABLE -> SHARABLE [3]
               SHARED     -> SHARED

d_join         SHARABLE   -> SHARED
               SHARED     -> SHARED
               UNSHARABLE -> UNSHARABLE + SHARABLE [4]

d_split        SHARABLE   -> SHARABLE
               UNSHARABLE -> UNSHARABLE
               SHARED     -> SHARED + SHARABLE
               SHARED     -> SHARABLE + SHARABLE [5]

[1] can be called from any state, but bad things may happen

[2] does a copy-on-write, new copy is unsharable, old one is
    left unmodified, unless it now has only one smart pointer.
    then it's made sharable instead of shared

[3] the last release of unsharable leaves it sharable

[4] joining to unsharable will make a new sharable copy, old one is
    left unmodified

[5] splitting a shared memory always makes a new sharable copy.  if
    the old one now has only a single smart pointer, it reverts to
    sharable as well.



=====================================================================
                        MemMgr and ShmMgr
=====================================================================

MemMgr does the alloc, free, swapping and caching of the memory
referred to by the smart pointers.  there will be interfaces to MemMgr
to control the swapping and caching behavior.

ShmMgr manages OS shared memory segments.  each segment will have one
or more ShmPtr created for it which define regions inside the segment.
the intent is to create a GimpShmBuffer subclass of GimpBuffer that
will construct itself around a ShmPtr and manage the image data
contained within.

