Thread overview
struct vs. internal class
Jun 22, 2005
Charles Hixson
Jun 22, 2005
Regan Heath
Jun 22, 2005
Derek Parnell
Jun 22, 2005
Regan Heath
Jun 23, 2005
Charles Hixson
Jun 24, 2005
Regan Heath
June 22, 2005
I'm not quite clear about how structs are supposed to be used, e.g., consider:
class As
{
protected
  struct  B
  {  int  c;
     int  d;
  }
  B[]  bs;
public
  int assign(int e)
  {  B  b;
     b.c  = e;
     b.d  = e + e;
     bs  ~= b;
   }
}

Does that work dependably, of are pieces of the bs array likely to be removed by garbage collection?  Should I use:
...
  int assign(int e)
  {  B  b = new B;
...
That looks weird for a struct.  Or should B rather be defined as an internal class?  (That would almost certainly work, but I tend to think of classes as much heavier than are structs.)

It seems likely that I need to make B an internal class...but if it explains this in the documentation, I didn't see it. (Actually grepping class.html from dmd/html/d didn't find any mentions of internal at all...but I'm certain that I've encountered references to them in the newsgroups.)

June 22, 2005
On Wed, 22 Jun 2005 12:44:57 -0700, Charles Hixson <charleshixsn@earthlink.net> wrote:
> I'm not quite clear about how structs are supposed to be used, e.g., consider:
> class As
> {
> protected
>    struct  B
>    {  int  c;
>       int  d;
>    }
>    B[]  bs;
> public
>    int assign(int e)
>    {  B  b;
>       b.c  = e;
>       b.d  = e + e;
>       bs  ~= b;
>     }
> }
>
> Does that work dependably

I believe the line "bs  ~= b;" copies the contents of 'b' into a new B which exists at the end of the array.

Meaning a function like this:

  void assign2(int e)
  {
     bs.length = bs.length + 1;
     bs[$-1].c = e;
     bs[$-1].d = e + e;
  }

would be slighly more efficient, as it doesn't copy it simply creates in place at the end of the array.

> , or are pieces of the bs array likely to be removed by garbage collection?

'b' will be, the copy won't be.

Regan

p.s. This code demonstrates what I think happens. Note: bs.ptr changes as it's reallocated (you can stop this by pre-allocating and using an index variable).

import std.stdio;

class As
{
protected
  struct  B
  {  int  c;
     int  d;
  }
  B[]  bs;
public
  void assign(int e)
  {
     B  b;
     B* p;
     b.c  = e;
     b.d  = e + e;
     bs  ~= b;
     p = bs.ptr + (bs.length-1);
     writefln("bs(%x) - (%x){%d,%d} - b(%x)",bs.ptr,p,p.c,p.d,&b);
  }
  void assign2(int e)
  {
     B* p;
     bs.length = bs.length + 1;
     bs[$-1].c = e;
     bs[$-1].d = e + e;
     p = bs.ptr + (bs.length-1);
     writefln("bs(%x) - (%x){%d,%d}",bs.ptr,p,p.c,p.d);
  }
  void print()
  {
     B* p;
     writefln("");
     for(int i = 0; i < bs.length; i++) {
        p = bs.ptr + i;
        writefln("bs(%x) - (%x)",bs.ptr,p,"{",bs[i].c,",",bs[i].d,"}");
     }
  }
}

void main()
{
	As a = new As();
	a.assign(1);
	a.assign(2);
	a.assign(3);
	a.assign(4);
	a.assign2(5);
	a.assign2(6);
	a.assign2(7);
	a.assign2(8);
	a.print();
}
June 22, 2005
On Wed, 22 Jun 2005 12:44:57 -0700, Charles Hixson wrote:

> I'm not quite clear about how structs are supposed to be used,
> e.g., consider:
> class As
> {
> protected
>    struct  B
>    {  int  c;
>       int  d;
>    }
>    B[]  bs;
> public
>    int assign(int e)
>    {  B  b;
>       b.c  = e;
>       b.d  = e + e;
>       bs  ~= b;
>     }
> }
> 
> Does that work dependably, of are pieces of the bs array likely
> to be removed by garbage collection?  Should I use:
> ...
>    int assign(int e)
>    {  B  b = new B;
> ...
> That looks weird for a struct.  Or should B rather be defined as
> an internal class?  (That would almost certainly work, but I tend
> to think of classes as much heavier than are structs.)
> 
> It seems likely that I need to make B an internal class...but if it explains this in the documentation, I didn't see it. (Actually grepping class.html from dmd/html/d didn't find any mentions of internal at all...but I'm certain that I've encountered references to them in the newsgroups.)

Your code seems to work okay. I guess the "bs ~= b" is actually adding a copy of the stack entity 'b' to the 'bs' array. However to totally make it look safer you might code it like this instead ...

   void assign(int e)
   {
      bs.length = bs.length + 1;
      bs[$-1].c  = e;
      bs[$-1].d  = e + e;
   }

No local struct is created in the scope of the 'assign' function that way.

-- 
Derek Parnell
Melbourne, Australia
23/06/2005 7:14:19 AM
June 22, 2005
On Thu, 23 Jun 2005 07:17:15 +1000, Derek Parnell <derek@psych.ward> wrote:
>    void assign(int e)
>    {
>       bs.length = bs.length + 1;
>       bs[$-1].c  = e;
>       bs[$-1].d  = e + e;
>    }

<snap>! I was first! ;)

Regan
June 23, 2005
Derek Parnell wrote:
> On Wed, 22 Jun 2005 12:44:57 -0700, Charles Hixson wrote:
> 
>> I'm not quite clear about how structs are supposed to be used, e.g., consider:
>> class As
>> {
>> protected
>>    struct  B
>>    {  int  c;
>>       int  d;
>>    }
>>    B[]  bs;
>> public
>>    int assign(int e)
>>    {  B  b;
>>       b.c  = e;
>>       b.d  = e + e;
>>       bs  ~= b;
>>     }
>> }
>>
>> Does that work dependably, of are pieces of the bs array likely to be removed by garbage collection?  Should I use:
>> ...
>>    int assign(int e)
>>    {  B  b = new B;
>> ...
>> That looks weird for a struct.  Or should B rather be defined as an internal class?  (That would almost certainly work, but I tend to think of classes as much heavier than are structs.)
>>
>> It seems likely that I need to make B an internal class...but if it explains this in the documentation, I didn't see it. (Actually grepping class.html from dmd/html/d didn't find any mentions of internal at all...but I'm certain that I've encountered references to them in the newsgroups.)
> 
> Your code seems to work okay. I guess the "bs ~= b" is actually adding a
> copy of the stack entity 'b' to the 'bs' array. However to totally make it
> look safer you might code it like this instead ...
> 
>    void assign(int e)
>    {  
>       bs.length = bs.length + 1;
>       bs[$-1].c  = e;
>       bs[$-1].d  = e + e;
>    }
> 
> No local struct is created in the scope of the 'assign' function that way.
> 
Well, I was nervous enough about it that I DID switch to a class based internal structure, where I'm CLEAR that what's happening is pointer manipulation.  That way I can trust that it won't be garbage collected/deleted from the stack as long as a pointer to it is live.  (If it's actually copying all the data, then I had no need to worry on that score...but I felt/feel unsure.)

June 24, 2005
On Thu, 23 Jun 2005 16:51:23 -0700, Charles Hixson <charleshixsn@earthlink.net> wrote:
> Derek Parnell wrote:
>> On Wed, 22 Jun 2005 12:44:57 -0700, Charles Hixson wrote:
>>
>>> I'm not quite clear about how structs are supposed to be used, e.g., consider:
>>> class As
>>> {
>>> protected
>>>    struct  B
>>>    {  int  c;
>>>       int  d;
>>>    }
>>>    B[]  bs;
>>> public
>>>    int assign(int e)
>>>    {  B  b;
>>>       b.c  = e;
>>>       b.d  = e + e;
>>>       bs  ~= b;
>>>     }
>>> }
>>>
>>> Does that work dependably, of are pieces of the bs array likely to be removed by garbage collection?  Should I use:
>>> ...
>>>    int assign(int e)
>>>    {  B  b = new B;
>>> ...
>>> That looks weird for a struct.  Or should B rather be defined as an internal class?  (That would almost certainly work, but I tend to think of classes as much heavier than are structs.)
>>>
>>> It seems likely that I need to make B an internal class...but if it explains this in the documentation, I didn't see it. (Actually grepping class.html from dmd/html/d didn't find any mentions of internal at all...but I'm certain that I've encountered references to them in the newsgroups.)
>>  Your code seems to work okay. I guess the "bs ~= b" is actually adding a
>> copy of the stack entity 'b' to the 'bs' array. However to totally make it
>> look safer you might code it like this instead ...
>>     void assign(int e)
>>    {        bs.length = bs.length + 1;
>>       bs[$-1].c  = e;
>>       bs[$-1].d  = e + e;
>>    }
>>  No local struct is created in the scope of the 'assign' function that way.
>>
> Well, I was nervous enough about it that I DID switch to a class based internal structure, where I'm CLEAR that what's happening is pointer manipulation.  That way I can trust that it won't be garbage collected/deleted from the stack as long as a pointer to it is live.  (If it's actually copying all the data, then I had no need to worry on that score...but I felt/feel unsure.)

I am fairly confident that my sample shows what is actually happening. It's more obvious if you preallocate the array and use an index variable to assign new structs to, then the data pointer for the array doesn't move and they all line up as you'd expect.

Then again, I *might* be wrong. ;)

Regan