<div style="line-height:1.7;color:#000000;font-size:14px;font-family:Arial"><div style="line-height:1.7;color:#000000;font-size:14px;font-family:Arial">ping</div><div style="line-height:1.7;color:#000000;font-size:14px;font-family:Arial"><br></div><div style="line-height:1.7;color:#000000;font-size:14px;font-family:Arial">Hi Andrew and David:<br><div><br></div><div>The cyclic reference formed should be like this:</div><div><br></div><div>TreePatternNode <------------------------------------------------------------------+</div><div> PredicateFns (std::vector<TreePredicateFn>) |</div><div> PatFragRec ------> TreePattern |</div><div> ^ Trees (std::vector<TreePatternNodePtr>) +------------> Other TreePatternNode</div><div> |</div><div><span style="line-height: 1.7;">Other TreePatternNode --+</span></div><div><span style="line-height: 1.7;"> </span></div><div>In the design all these pointers are reference counted, and I have designed a "operator=" like this:</div><div><br></div><div><div>+ TreeNodePtr &operator=(const T *node) {</div><div>+ this->Release();</div><div>+ this->Member = const_cast<T *>(node);</div><div>+ this->AddRef();</div><div>+ return *this;</div><div>+ }</div></div><div><br></div><div>So if we assign "null" to "<span style="line-height: 23.7999992370605px;">PatFragRec"</span><span style="line-height: 23.7999992370605px;"> or "Trees", for example </span><span style="line-height: 23.7999992370605px;">"</span><span style="line-height: 23.7999992370605px;">PatFragRec", if it finds it's the </span><span style="line-height: 23.7999992370605px;">the last referrer, it will free the TreePattern pointed by</span></div><div><span style="line-height: 23.7999992370605px;">"</span><span style="line-height: 23.7999992370605px;">PatFragRec", which in turn frees "Trees" which contains the TreePatternNode referring the TreePattern</span><span style="line-height: 23.7999992370605px;">. So what we need to do is to assign all </span><span style="line-height: 23.7999992370605px;">"</span><span style="line-height: 23.7999992370605px;">PatFragRec" </span></div><div><span style="line-height: 23.7999992370605px;">or "Trees" to </span><span style="line-height: 23.7999992370605px;">"null".</span></div><div><span style="line-height: 23.7999992370605px;"><br></span></div><div><span style="line-height: 23.7999992370605px;">So in fact, FreeCycleRef::run can be simplified as:</span></div><div><span style="line-height: 23.7999992370605px;"><br></span></div><div><div>void FreeCycleRef::run() {</div><div><span style="line-height: 1.7;"> std::vector<TreePatternNodePtr> tmp; // temporarily holding </span><span style="line-height: 23.7999992370605px;">PatFragRec</span><span style="line-height: 23.7999992370605px;"> to prevent TreePatternNode from deleting,</span></div><div><span style="line-height: 23.7999992370605px;"> // which may erase some items from the container and break below for-loop</span></div><div> for (<span style="line-height: 23.7999992370605px;">TPContainerType::iterator it = TPContainer.begin(); it != </span><span style="line-height: 23.7999992370605px;">TPContainer.end(); ++it)</span></div><div><span style="line-height: 23.7999992370605px;"> {</span></div><div><span style="line-height: 23.7999992370605px;"> </span><span style="line-height: 23.7999992370605px;"> const std::vector<TreePredicateFn> &vec = </span><span style="line-height: 23.7999992370605px;">iter->second</span><span style="line-height: 23.7999992370605px;">->getPredicateFns();</span></div><div style="line-height: 23.7999992370605px;"> for (unsigned i = 0, e = vec.size(); i < e; ++i) {</div><div style="line-height: 23.7999992370605px;"> TreePredicateFn *p = const_cast<TreePredicateFn *>(&vec[i]);</div><div style="line-height: 23.7999992370605px;"><span style="line-height: 23.7999992370605px;"> tmp.pushback(</span><span style="line-height: 23.7999992370605px;">p->PatFragRec);</span></div><div style="line-height: 23.7999992370605px;"><span style="line-height: 23.7999992370605px;"> p->PatFragRec = nullptr;</span></div><div style="line-height: 23.7999992370605px;"><span style="line-height: 23.7999992370605px;"> }</span></div><div><span style="line-height: 23.7999992370605px;"> }</span></div></div><div><span style="line-height: 23.7999992370605px;">}</span><span style="line-height: 23.7999992370605px;"> // all Tree Nodes should be released here!</span></div><div></div><div id="divNeteaseMailCard"></div><div><br></div><div>However, I follow the cyclic chain and do the cleaning along the way just out of this consideration:</div><div><br></div><div>You see the algorithm to reclaim the cyclic reference is very special to current situation. In future, if the data layout changed, and </div><div>the algorithm may don't work, it should be found out as quick as possible -- that is the purpose of the assertion at line 2417:</div><div><br></div><div>+ assert(refCnt == 0 && "The RefCnt diverged");</div><pre><div><br></div><div><br></div><div><br></div>At 2014-09-23 06:04:25, "Andrew Trick" <<a href="mailto:atrick@apple.com">atrick@apple.com</a>> wrote:
>
>> On Sep 22, 2014, at 8:03 AM, David Blaikie <<a href="mailto:dblaikie@gmail.com">dblaikie@gmail.com</a>> wrote:
>>
>> If you haev cycles, reference counting is not the right tool.
>>
>> If you are working around the limitations of reference counting because you have cycles by defining a cleanup pass - why not just do all the ownership and destruction there? I'm still not really following, but haven't taken the time to look into the code in more detail.
>
>I have the same question.
>Andy
</pre></div><br><br><span title="neteasefooter"><span id="netease_mail_footer"></span></span></div><br><br><span title="neteasefooter"><span id="netease_mail_footer"></span></span>