Re: [boost] Re: Cyclic smart pointers (holy grail: the uber-pointer)

2003-05-31 Thread Gregory Colvin
On Friday, May 30, 2003, at 11:58 America/Denver, Larry Evans wrote:

Gregory Colvin wrote:
> On Friday, May 30, 2003, at 10:18 America/Denver, Larry Evans wrote:
>
[snip]
>>
>> http://groups.yahoo.com/group/boost/files/shared_cyclic_ptr/
>> draft-compare.zip might be a good starting point.  It
>> doesn't include the latest additions and still needs work :(.
>
>
> Wow.
Thanks (I guess).

Since understanding some of the code was difficult,
I think you understood cyclic_ptr better than I do now, and maybe
better than I did then ;->
it would sure help
if the authors of each of the codes would analyze their own code to
check against what's already in draft-compare, or add to
draft-compare, as appropriate.  Also, it would most likely avoid the
"jumping to conclusions" which I was guilty of when evaluating
sp_collector earlier in a (this?) thread.
___
Unsubscribe & other changes: 
http://lists.boost.org/mailman/listinfo.cgi/boost
___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Cyclic smart pointers (holy grail: the uber-pointer)

2003-05-31 Thread Larry Evans
Gregory Colvin wrote:
> On Friday, May 30, 2003, at 10:18 America/Denver, Larry Evans wrote:
>
[snip]
>>
>> http://groups.yahoo.com/group/boost/files/shared_cyclic_ptr/
>> draft-compare.zip might be a good starting point.  It
>> doesn't include the latest additions and still needs work :(.
>
>
> Wow.
Thanks (I guess).

Since understanding some of the code was difficult, it would sure help
if the authors of each of the codes would analyze their own code to
check against what's already in draft-compare, or add to
draft-compare, as appropriate.  Also, it would most likely avoid the
"jumping to conclusions" which I was guilty of when evaluating
sp_collector earlier in a (this?) thread.
___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Cyclic smart pointers (holy grail: the uber-pointer)

2003-05-31 Thread Gregory Colvin
On Friday, May 30, 2003, at 10:18 America/Denver, Larry Evans wrote:
Gregory Colvin wrote:
On Friday, May 30, 2003, at 09:56 America/Denver, Chuck Messenger 
wrote:
...
What I'm trying to develop (or even better, find) is a workable C++
[snip]
their relative advantages and disadvantages are.  If someone could
pull this information together it might help to get this discussion
out of the cycle it seems caught in ;->
http://groups.yahoo.com/group/boost/files/shared_cyclic_ptr/
draft-compare.zip might be a good starting point.  It
doesn't include the latest additions and still needs work :(.
Wow.

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Cyclic smart pointers (holy grail: the uber-pointer)

2003-05-31 Thread Larry Evans
Gregory Colvin wrote:
On Friday, May 30, 2003, at 09:56 America/Denver, Chuck Messenger wrote:

...
What I'm trying to develop (or even better, find) is a workable C++ 
[snip]
their relative advantages and disadvantages are.  If someone could
pull this information together it might help to get this discussion
out of the cycle it seems caught in ;->
http://groups.yahoo.com/group/boost/files/shared_cyclic_ptr/
draft-compare.zip might be a good starting point.  It
doesn't include the latest additions and still needs work :(.
___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Cyclic smart pointers (holy grail: the uber-pointer)

2003-05-31 Thread Gregory Colvin
On Friday, May 30, 2003, at 09:56 America/Denver, Chuck Messenger wrote:
...
What I'm trying to develop (or even better, find) is a workable C++ 
library which supports cyclic structures, handling garbage collection 
for you, without resorting to a systemic (and non-portable) approach 
like the Boehm collector.  I want to build regular-old, C++ standard 
libraries upon this cyclic library -- I don't want to require users of 
my libraries to use my garbage collection system.  It needs to be 
perfectly invisible to the user (and ideally, as invisible as possible 
to the library writer).
There are a few attempts laying around various places in Boost, but
I've lost track of where they all are, how they all work, and what
their relative advantages and disadvantages are.  If someone could
pull this information together it might help to get this discussion
out of the cycle it seems caught in ;->
___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


RE: [boost] Re: Cyclic smart pointers (holy grail: the uber-pointer)

2003-05-30 Thread Schoenborn, Oliver


> -Original Message-
> From: Chuck Messenger [mailto:[EMAIL PROTECTED]
> Sent: Thursday, May 29, 2003 4:47 PM
> To: [EMAIL PROTECTED]
> Subject: [boost] Re: Cyclic smart pointers (holy grail: the
> uber-pointer)
> 
> 
> Schoenborn, Oliver wrote:
> 
> >>>- You always have A owns A_impl owns B owns B_impl refs A (what your
> >>>original code seems to say), in this case B_impl contains an RRef 
> >>>instead of a DynObj and everything works
> > 
> > I'd like to hear whether that's your case or not. 
> 
> No.  A and B are completely symmetrical.  They each equally 
> "own" the other.

Not possible. This has nothing to do with NoPtr or boost::shared_ptr, it's
even true for raw pointers. E.g.

// forget about forward declarations for brevity

struct A {
B* b;
~A() {delete b;} // A owns b
};
struct B {
A* a;
~B() {delete a;} // B owns a
};

A* a = new A;
a->b = new B;
a->b->a = a;

delete a;// *** illegal #1
delete a->b; // *** illegal #2

In illegal#1, a is owned by b means that only b is allowed to delete a, so
calling "delete a" ourselves is illegal (and will lead to double deletion).
In illegal#2, it's b that's being deleted, and same holds as illegal #1. So,
who destroys a and b? No one can and you have a memory leak. 

If on the other hand you have 

struct A {
B* b;
~A() {delete b;} // A owns b
};
struct B {
A* a; // B does NOT own a
};
 
then delete a is ok, but delete a->b is still not since a->b is owned by a. 

> I looked at NoPtr, and quickly determined that it didn't implement 
> garbage collection, so it couldn't solve my problem.  

That's good, because NoPtr has nothing to do with garbage collection (though
one could perhaps use it for a form of gc).

> However, I don't understand what NoPtr *does*.

Simplistically, 
- DynObj destroys what it owns when it goes out of scope, is reset or
acquires something new, and notifies any RRefs linked to it
- RRef refers to a DynObj, but asserts that DynObj still exists when
accessed

Note that I said simplistically.

Oliver

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Cyclic smart pointers (holy grail: the uber-pointer)

2003-05-30 Thread Larry Evans
Larry Evans wrote:
[snip]
See if the current stl_container.cpp can at least traverse your pointer 
graph correctly.
Unfortunately, stl_container.cpp can't work with the stl because it prototypes
a "slight" modification to stl to make stl easily gc'ed.  If you want to work
with the current stl, you'll have to do something similar to
scoped_cyclic_container, i.e. derive a class from the
stl container whose CTOR stores the method in the descriptor.  This is
on my todo list.
___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Cyclic smart pointers (holy grail: the uber-pointer)

2003-05-30 Thread Larry Evans
Chuck Messenger wrote:
Larry Evans wrote:
[snip]
Right.  scoped_cyclic_ptr (in shared_cyclic_ptr.zip) works around this by
using a smart ptr enumerator
function specialized for each type of container.  The specialized 
function
is then used to access all the smart ptrs in the container (via the 
begin() end()
iterator class).


OK, I see.

In fact, it seems like you don't need any special smart ptr enumerator 
function.  All you do is: you use derived-from versions of the std 
containers, so you can maintain an up-to-date list of references to each 
one.  During GC, for each such container c, "for (it = c.begin(); it != 
c.end(); ++it)", you treat *it as a Rangeable -- any {C} references in 
the range [&*it, &*it + sizeof(*it) - 1] are flagged as internal.
Not quite.  The scoped_cyclic_ptr was designed to work-around a limitation
of Detlef's method:
  http://www.cs.kent.ac.uk/people/staff/rej/cgi-bin/searchbib?pattern=Detl92
This limitation was that it didn't document how than handle container
classes.  It only documented how scalars were handled.  The adaptation
in scoped_cyclic_ptr (and stl_container) is, as you mentioned, to store
a pointer and offset into a prox_descriptor (see stl_container.cpp)
for each type which contains a proxy (i.e. smart pointer) or a container
of proxies.  The pointer and offset is stored by the CTOR for either scalar proxies
(prox_scalar_typed<...>) or the prox_indirect_typed forming part of any
container of proxies (e.g. the test::m_vec_ptest_shared).  The pointer points
to an instance of maker_proxiter_abs which produces an iterator over proxies
contained in a subject class (subject is term used for pointee or referent
in GOF) given the start of a subject.  (I know, its too complicated, but
I can't think of how to simplify it.  Any ideas?)
Nice!

Thanks.
[snip]
Is stl_container.cpp an experimental Boost lib?  Where can I get it?
It's in:
  http://groups.yahoo.com/group/boost/files/shared_cyclic_ptr/stl_container.cpp
You'll also need the col_io library in:
  http://groups.yahoo.com/group/boost/files/col_io/
and then there's a simple trace_scope.hpp which I'll upload.
I like your "iterate through tagged STL containers" method.  The library 
writer (the one using the cyclic smart pointer system) has to take care 
to store {C} objects only in appropriately tagged containers.  But they 
get to use any containers they want.

Not too shabby.
Thanks.
I'd love to examine your scoped_cyclic_ptr lib -- to see if I can make 
use of it.  Perhaps I can help you flesh out requirements, if it's close 
enough to what I need.  Is it available for download?
That's at:
  http://groups.yahoo.com/group/boost/files/shared_cyclic_ptr/shared_cyclic_ptr.zip
It uses an earlier version of method to enumerate pointers in an object.  It also
demonstrates how to adapt shared_ptr for to use the method.  It also shows
that the enumeration method is pretty much independent of the collection method because
it uses two different methods (one using Detlef's, or offset_iterator method and
one using Colvin's or assign_op_switch) to implement the same gc method (Lin's local
mark-scan).  BTW, Lin's method suffers from quadratic behavior with nested cycles
as pointed out in Bacon's paper (I think I made a reference to that earlier.  I know
I did in a post responding to one of Terekov's posts).  The work-around is
lazy-local mark-scan which maintains a queue of possible garbage nodes.  Anyway,
I had a version of this also, but it's been rm'ed from boost long ago.
See if the current stl_container.cpp can at least traverse your pointer graph 
correctly.
If it can, then it's easy to use any of the cyclic rc algorithms
(i.e. lazy local mark scan, eager local mark scan, global mark scan).
___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Cyclic smart pointers (holy grail: the uber-pointer)

2003-05-30 Thread Peter Dimov
Chuck Messenger wrote:
> What is the status of sp_collector.cpp?  It's distributed as part of
> Boost right now.  Is it intended to remain part of the shared_ptr
> library?  It sounds like it should suit my purposes quite well, after
> all...

sp_collector.cpp has a "gift" status. ;-) Meaning that it is not one of my
priorities to support or maintain it, but if someone finds it useful as a
starting point for further work, all the better.

Its main purpose was/is to demonstrate that it is possible to write a
collector for cyclic shared_ptr structures without altering the shared_ptr
specification, i.e. that the spec is flexible enough to handle an optional
collector should someone decide to provide one as part of their
std::shared_ptr.

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Cyclic smart pointers (holy grail: the uber-pointer)

2003-05-30 Thread Peter Dimov
Chuck Messenger wrote:
> Schoenborn, Oliver wrote:
>
> Imagine that I'm supplying a network simulation library.  I have:
>
>  #include 
>  #include 
>  #include 
>  #include 
>
>  using namespace std;
>  using namespace boost;
>
>  struct Node;
>
>  struct NodeImpl : noncopyable {
>  NodeImpl(int id) : id_(id) { cout << id_ << " lives\n"; }
>  ~NodeImpl() { cout << id_ << " dies\n"; }
>  private:
>  set nodes_;
>  int id_;
>  friend struct Node;
>  };
>
>  struct Node {
>  Node(int id) : pimpl_(new NodeImpl(id)) { }
>  Node(const Node& n) : pimpl_(n.pimpl_) { }
>  void Connect(const Node& n) { pimpl_->nodes_.insert(n); }
>  void Disconnect(const Node& n) { pimpl_->nodes_.erase(n); }
>  private:
>  shared_ptr pimpl_;
>  friend bool operator<(const Node& n1, const Node& n2);
>  };
>
>  bool operator<(const Node& n1, const Node& n2) {
>  return n1.pimpl_ < n2.pimpl_;
>  }
>
>  int main() {
>  {
>  Node n1(1);
>
>  {
>  Node n2(2), n3(3), n4(4);
>
>  n1.Connect(n2);
>  n2.Connect(n2);
>  n3.Connect(n3);
>  n4.Connect(n4);
>  }
>
>  cout << "n1 points to the cluster {n2, n3, n4}\n";
>  }
>
>  cout << "n2, n3, n4 remain alive.  That sucks.\n";
>  }

This is a graph. The classic "tree structure" combined with reference
counting can only represent (possibly multiply linked) DAGs, but not general
graphs.

One possible representation of a general graph is a vertex pool and a
separate edge pool. This avoids the ownership issues inherent in the tree
representation since now nodes don't own each other, the two pools are the
owners.

Perhaps the boost graph library can help here?

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Cyclic smart pointers (holy grail: the uber-pointer)

2003-05-29 Thread Larry Evans
Chuck Messenger wrote:
[snip]
Does the Boehm collector likewise do a full scan of the heap?  I assume 
so...
Yes. From p. 28 of _Garbage Collection_, 1996
( http://www.cs.kent.ac.uk/people/staff/rej/gcbook/gcbook.html )
  "all cells are examined by the sweep"
However, this is theory.  In actual implementation, there's workarounds.
(See next comment).


One big problem with this approach is that you end up having to scan 
all of your memory.  This could (and for me, would) be an outrageous 
proposition, as only a tiny portion of memory relates to my object 
set.  Most of it will be raw data (e.g. images, etc).
You can specify which cells to scan by specifying it's "kind" during
allocation ( http://www.hpl.hp.com/personal/Hans_Boehm/gc/gcdescr.html )
thus there's no need to scan the whole heap.  cyclic_ptr doesn't really
scan the whole heap, only those "cells" allocated by the cyclic_ptr
allocator.
[snip]
Interesting -- thanks!  I'll give it a look...

However, I thought about deriving from an STL container, and rejected 
it.  The reason is that you don't know how the STL container allocates 
memory.  In order to maintain the system's invariants, it is necessary 
that all "internal" C objects be contained physically within the bounds 
of an I:C object, which all derive from some common base class -- 
Rangeable, say.  The Rangeable 'structors add/remove 'this' to 
map_impl[].  OK, so we make our own map which is-a std::map and is-a 
Rangeable (multiple inheritance).  So far so good.  But what happens 
when std::map allocates memory internally?  We need those internal nodes 
to also be Rangeable, or the system won't work.

Right?
Right.  scoped_cyclic_ptr (in shared_cyclic_ptr.zip) works around this by
using a smart ptr enumerator
function specialized for each type of container.  The specialized function
is then used to access all the smart ptrs in the container (via the begin() end()
iterator class).  Thus, there's only the for the collector to know the
start of the container, not the start of each element of the container, which
can be derived from the smart ptr enumerator function.  (The stl_container.cpp
should provide another example of this).  The I:C pointers you're referring to
I think correspond to the prox_policied and the prox_indirect
classes in stl_container.cpp.
I suppose we could supply our own allocator to std::map -- hmmm
John Skaller suggested a similar solution, but said it wasn't
workable with current stl design:
( http://aspn.activestate.com/ASPN/Mail/Message/1149745 )

[snip]

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] Re: Cyclic smart pointers (holy grail: the uber-pointer)

2003-05-29 Thread Gregory Colvin
On Wednesday, May 28, 2003, at 13:04 America/Denver, Chuck Messenger 
wrote:

Larry Evans wrote:
Chuck Messenger wrote:
[snip]
collections, put them in object heirarchies, etc).  This freedom 
should ideally apply both internally (within library L code) and 
most importantly, externally (in the code of users of library L).  
Crucially,
Would you require the users to use a smart pointer instead of a raw?
If not, then you're only option, that I can tell, is use a 
conservative
collector like Boehm's.
No -- users don't use pointers -- only objects.  The objects each have 
one pimpl_ (which will be whatever "smart" type "we" - the 
uber-pointer framework designers - want), pointing to the underlying 
object.

Note:  This is essentially a plain-vanilla Java-style object system 
which I am describing.

 The consequence of mis-identification is
that you may fail to destroy some unused objects.  If this leads to 
nothing worse than some leaked memory, then it's not a real problem 
-- it will be a vanishingly small amount of memory.
This is the justification for Boehm's conservative collector.
 http://www.hpl.hp.com/personal/Hans_Boehm/gc/
Does the Boehm collector likewise do a full scan of the heap?  I 
assume so...
It marks all objects on the heap pointed to by the machine registers, 
and
all objects pointed to by those objects, and so on.  It is conservative 
in
the sense that it cannot generally tell whether a register or memory 
cell
contains a pointer or an integer.

One big problem with this approach is that you end up having to scan 
all of your memory.  This could (and for me, would) be an outrageous 
proposition, as only a tiny portion of memory relates to my object 
set.  Most of it will be raw data (e.g. images, etc).
Boehm's collector includes functions for allocating pointer-free memory.

This is what Christopher's (alias= global rc mark-scan) algorithm 
does.
It's also what mark-sweep algorithms do, i.e. they have to mark all 
reachable
objects, and then scan thru the whole heap sweeping the unmarked into 
the
garbage collector. However, since this global scan is done, usually,
infrequently, the time isn't that big a factor, at least compared 
with the
updating of reference counts during each pointer copy.
That's why Boehm's gc should work faster than refcounting.
It does.

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost