summaryrefslogtreecommitdiff
path: root/docs/RefCnt
blob: 1a6d515eb4868df0d6590777a5b86db84e7a662e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
Reference counting
------------------

Overview
--------

  DOM Nodes are reference counted, so as to ensure they are only destroyed
  when nothing is using them. Each node has a reference count member
  variable, which is a count of external references upon the node. Links
  between nodes in the DOM tree (internal references) are not counted, as
  they are implicitly available by consulting the relevant pointers.

Destruction semantics
---------------------

  A simplistic DOM tree might look like the following:
  
				Node1
				 | ^
				 | |
		   +-------------|-+---------------+
		 +-|-------------+-|-------------+ |
		 | |		 | |		 | |
		 v |		 v |		 v |
		Node2<--------->Node3<--------->Node4
		 | ^
		 | |
	   +-----|-+-------+
	 +-|-----+-------+ |
	 | |		 | |
	 v |		 v |
	Node5<--------->Node6

  Thus, each node possesses the following links:

    a) A link to its parent
    b) A link to each of its children
    c) A link to the sibling immediately prior to it
    d) A link to the sibling immediately after it

  None of these links are reference counted, as the reference can be 
  determined implicitly from the pointer value (i.e. a non-NULL pointer 
  implies a reference).

  A node becomes eligible for destruction when:
  
    a) its reference count variable equals 0
    b) its parent node pointer equals NULL

  I.E. There exist no external references upon the node and the node has 
  been detached from the tree.

  Note that the presence of children or siblings attached to a node has no
  impact upon its eligibility for destruction, as these links are "weak".

Destruction process
-------------------
  
  The node destruction process proceeds as follows:

    1) Any children of the node are detached from it and an attempt is
       made to destroy them.
    2) The node is destroyed.

  If, when attempting to destroy children of the node, a child is found
  to have a non-zero reference count (i.e. an external reference is
  being held upon the child), the child (and its children) is not 
  destroyed. The child is added to the list of nodes pending deletion 
  and will be destroyed once its reference count reaches zero.

Example
-------

  This example uses the DOM tree depicted above, and a system state as 
  follows:

    a) A NodeList collection references Node6. There are no other active
       collections. The NodeList has a reference count of 1.
    b) Node2 (and its subtree) has been removed from the document and
       is referenced solely by the client code that caused it to be 
       removed from the document.

  The client code unreferences Node2, thus reducing its reference count to
  zero. It is now eligible for destruction. Destruction occurs as follows:
  
    1) Node5 is detached from Node2 and an attempt is made to destroy it.
       a) Node5 has no children and has a reference count of zero, so it 
          is destroyed.
    2) Node6 is detached from Node2 and an attempt is made to destroy it.
       a) Node6's reference count is non-zero, so it is added to the list 
          of nodes pending deletion.
    3) Node2 has no further children, so it is destroyed.

  The client code unreferences the NodeList:
  
    1) The NodeList unreferences the node it's attached to (Node6).
       Node6's reference count is now zero, so it is eligible for 
       destruction.
       a) Node6 has no children, so it is destroyed (and removed from the
          list of nodes pending deletion).
    2) The NodeList is destroyed.

Destruction of Documents
------------------------

  Assumptions:
  
    1) Nodes within a document do not hold explicit references upon it.
    2) Container data structures which address nodes in a document hold
       an explicit reference upon the document. 
       [FIXME: and upon the root node of the subtree they address -- this
        implies that the explicit reference is unnecessary, as the 
        addressed node will be added to the list of nodes pending 
        deletion]
    3) A document has no parent (i.e. the parent pointer is always NULL).
    4) A given node may be located in either the document tree or the
       list of nodes pending deletion. It may not be located in both
       data structures simultaneously.
    5) Nodes in the list of nodes pending deletion are in use by the 
       client.

  The above assumptions imply the following:
  
    + If a document has a non-zero reference count, it is in use by
      the client. (1,2)
    + If the document's reference count reaches zero, it is no longer
      in use and is eligible for deletion. (1,2,3)
    + The document destructor must attempt to forcibly delete the 
      contents of the document tree as the nodes do not hold a reference
      upon the document. (1)
    + On destruction of a node, it must be removed from the list of nodes 
      pending deletion. (4)
    + The document may not be destroyed if the list of nodes pending
      deletion is non-empty after the destructor has attempted to
      destroy the document tree. (4,5)

  Therefore, document destruction proceeds as follows:
  
    1) Forcibly destroy the document tree.
    2) If the list of nodes pending deletion is non-empty, stop.
    3) The list of nodes pending deletion is empty, so destroy the 
       document.