Re: Fast temporary dynamic arrays? (And slicing of them)

2010-09-05 Thread bearophile
My first test shows that it may work. But I have to grow the array backwards, 
and push back the array start, because that's how my stack grows (using alloca 
to allocate geometrically bigger chunks). So unless you want to reverse the 
items once the array is built, you have to change the algorithm that uses the 
array a little.

Bye,
bearophile


Re: Fast temporary dynamic arrays? (And slicing of them)

2010-09-05 Thread Jonathan M Davis
On Sunday 05 September 2010 18:02:29 Tom Kazimiers wrote:
> Hi all,
> 
> so I have started to look at D and dug through the documentation, but
> could not get a good answer on the following:
> 
> How can I have a (temporary) dynamic array on stack and make references
> to it (no copying)? I successively put integers in an array (but don't
> know how much there will be in advance) with an appender!(int[]) and get
> the date out with appender.data(). Later on I pass the result to a
> method as an "in int[]" parameter. Is that already a reference or will
> it be copied? Are there better methods to accomplish this? The method
> receiving such an array will not modifiy contents of the array, but only
> read from it.

Static arrays are value types, but dynamic arrays are reference types.

void main()
{
int[] a = new int[](3);
a[0] = 1;
a[1] = 2;
a[2] = 3;

int[] b = a; //b now refers to a
assert(a == b);
assert(a is b);
assert(a.length == b.length);
assert(a[0] == b[0]);
assert(a[1] == b[1]);
assert(a[2] == b[2]);

b = new int[](2); //b now refers to a different array
b[0] = 5;
b[1] = 6;
assert(a != b);
assert(a !is b);
assert(a.length != b.length);
assert(a[0] != b[0]);
assert(a[1] != b[1]);

b = a[]; //b now refers to a full slice of a
assert(a == b);
assert(a is b);
assert(a.length == b.length);
assert(a[0] == b[0]);
assert(a[1] == b[1]);
assert(a[2] == b[2]);

b = a[1..$]; //b now refers to a partial slice of a
assert(a != b);
assert(a !is b);
assert(a.length != b.length);
assert(a[1] == b[0]);
assert(a[2] == b[1]);
}



No array copying takes place anywhere in that program. If you want to copy an 
array, you'd do one of the following

void main()
{
int[] a = new int[](3);
a[0] = 1;
a[1] = 2;
a[2] = 3;

int[] b = new int[](3);
b[] = a[]; //b is now a copy of a (the contents of a were copied to b)
assert(a == b);
assert(a !is b);
assert(a.length == b.length);
assert(a[0] == b[0]);
assert(a[1] == b[1]);
assert(a[2] == b[2]);

int[] c = a.dup; //c is now a copy of a (a new copy of a was created)
assert(a == c);
assert(a !is c);
assert(a.length == c.length);
assert(a[0] == c[0]);
assert(a[1] == c[1]);
assert(a[2] == c[2]);

immutable(int[]) d = a.idup; //d is now an immutable copy of a (a new copy 
of a was created)
assert(a == d);
assert(a !is d);
assert(a.length == d.length);
assert(a[0] == d[0]);
assert(a[1] == d[1]);
assert(a[2] == d[2]);
}


Passing dynamic arrays to functions passes the reference. So, as long as you 
don't alter the reference directly or resize the array in any way which would 
cause reallocation, the reference in the called function will refer to the 
array which was passed in and any alterations to its elements will alter the 
original. However, if you set the local reference to something else, or if you 
resize the array in a manner which would cause a reallocation, then the local 
reference would refer to a different chunk of memory, and any alteration to its 
elements would not affect the original.

- Jonathan M Davis


Re: Fast temporary dynamic arrays? (And slicing of them)

2010-09-05 Thread bearophile
Tom Kazimiers:
> How can I have a (temporary) dynamic array on stack and make references
> to it (no copying)? I successively put integers in an array (but don't
> know how much there will be in advance) with an appender!(int[]) and get
> the date out with appender.data(). Later on I pass the result to a
> method as an "in int[]" parameter. Is that already a reference or will
> it be copied? Are there better methods to accomplish this? The method
> receiving such an array will not modifiy contents of the array, but only
> read from it.

The appender.data() doesn't currently copy data.

There is no standard way to put a growable array on the stack. Maybe you can 
hack it with several successive calls to alloca(), but I have never tried it.

There many other solutions, like:
- Using a fixed-sized array on the stack, you keep its true length in a variable
- The same, with static array
- The same with a static gshared array
- pre-allocating a "large enough" dynamic array before all the calls to the 
function that uses them
- using a single alloca() when you know how many items you have to append
- use a deque data structure that uses a manually-managed pool of blocks of 
items, that you can concatenate in a linked list or index through a dynamic 
array of pointers

The cuter solution is to simulate a realloc on the stack (to keep a single 
growable array) with a series of calls to alloca. But I don't know if it works 
:-) I will try it.

Bye,
bearophile


Fast temporary dynamic arrays? (And slicing of them)

2010-09-05 Thread Tom Kazimiers
Hi all,

so I have started to look at D and dug through the documentation, but
could not get a good answer on the following:

How can I have a (temporary) dynamic array on stack and make references
to it (no copying)? I successively put integers in an array (but don't
know how much there will be in advance) with an appender!(int[]) and get
the date out with appender.data(). Later on I pass the result to a
method as an "in int[]" parameter. Is that already a reference or will
it be copied? Are there better methods to accomplish this? The method
receiving such an array will not modifiy contents of the array, but only
read from it.

Thanks in advance,
Tom

--

P.s. To put a bit of context around that, here some notes on what I am
working (some questions here as well, but above is the primary one):

My first try-out project in D is an Object file reader (often used in
computer graphics). Part of that is a parsing method which parses a
single line that contains a definition of a face (a polygon). It could
for instance look like this:

f 1//10 2//10 3//10

That means it is a triangle face of points 1, 2 and 3 (three groups,
first number is point index). Furthermore no texture coordinate index
(no number between two slashes) and each with normal vector index 10.
But I don't want to go into detail of that. Say I want to parse that
line with D and in the end call a method to process that face with
references to lists of the different point indices:

void process_face(int index, int vcount, in int[] vertices,
  in int[] texcoords = null, in int[] normals = null)
{
...
}

(I guess "in" means sth. like const reference)

The arrays should not be copied, but be references. The line parsing
method now has the following lines (line is a char[]):

//search face
int index = indexOf(line, "f ");
if(index != -1)
{
line = line[index+2 .. $];  // slice away the "f " part
fc++; // increment face count

int slash;
while(true)
{
 slash = indexOf(line, " /");  // leading spaces + slashes?
 if(slash != -1)
 // remove space
 line = line[0 .. slash] ~ line[slash+1 .. $];
 else
 break;
}
while(true)
{
slash = indexOf(line, "/ ");  // trailing spaces + slashes?
if(slash != -1)
// remove space 
line = line[0 .. slash+1] ~ line[slash+2 .. $];
else
break;
}

// dynamic vertex, texture and normal arrays
auto vIndices = appender!(int[])();
auto tIndices = appender!(int[])();
auto nIndices = appender!(int[])();

// some indices
int vi,ti,ni;

// split line on white spaces
char[][] vertexCoords = split( line );
// go through each part - are those splittings ok?
foreach(char[] coord; vertexCoords) {
vi = parse!(int)(coord); //get int from string
vIndices.put( vi ); // save it in vertex array
if (coord[0] == '/') { // follows a slash?
coord = coord[1 ..$]; // get rid of it
if (coord[0] == '/') { // follows another slash?
coord = coord[1 ..$]; // get rid of it
ni = parse!(int)( coord ); // git following int
nIndices.put( ni ); // save it in normal array
} else {
ti = parse!(int)( coord );
tIndices.put( ti );
if (coord[0] == '/') {
coord = coord[1 ..$];
int ni = parse!(int)( coord );
nIndices.put( ni );
}
}
}
}

// array references for passing to processing method
int[] varray = null, tarray = null, narray = null;

// if we have data, save it to appropriate varible
if( !(vIndices.data().empty()) )
varray = vIndices.data();

if( !(tIndices.data().empty()) )
tarray = tIndices.data();


if( !(nIndices.data().empty()) )
narray = nIndices.data();

// process it
process_face(fc, vIndices.data().length, varray, tarray, narray);

return;
}

I hope this rather lengthy explanation is no problem here (if looked on
it at all, since it was not my primary question :-) ). If you are in the
mood, please comment on how make parts on it better. It is pretty much
my first D code. Well, thanks.

Cheers
Tom


forks/pipes and std.socket

2010-09-05 Thread Nick Sabalausky
This may be a stupid question:

Does std.socket encorporate or replace pipe usage? Ie, if I'm going to do 
something along the lines of (psuedo-code):

auto parentToChild = pipe();
auto childToParent = pipe();
if(fork())
{
// talk to other process
}
else
{
// talk to other process
}

Is there anything in std.socket, or any way of using it that would aid in 
this sort of thing (ideally in a cross-platform way), or is it entirely 
orthogonal to this?

Does anyone who's done this sort of thing in D before, on Win or Lin, know 
of anything else in particular to be aware of? 




Re: Synchronized methods in D2

2010-09-05 Thread Era Scarecrow
> Jonathan M Davis:
> > Also, according to TDPL, either your _entire class_ is synchronized, or 
> > none of
> > it is. So, synchronized really belongs on the class, not the function, and I
> > wouldn't expect it to compile if only a portion of your functions are
> > synchronized (though I don't know how close the current dmd is to TPDL with
> > regards to synchronized).

  *smacks forehead* Of course. i forgot that detail. I don't work with
multi-threads or synchronized much yet.


Re: Synchronized methods in D2

2010-09-05 Thread bearophile
Jonathan M Davis:
> Also, according to TDPL, either your _entire class_ is synchronized, or none 
> of 
> it is. So, synchronized really belongs on the class, not the function, and I 
> wouldn't expect it to compile if only a portion of your functions are 
> synchronized (though I don't know how close the current dmd is to TPDL with 
> regards to synchronized).

If not already present, I suggest to add this to Bugzilla.

Bye,
bearophile


Re: Synchronized methods in D2

2010-09-05 Thread Jacob Carlborg

On 2010-09-05 02:18, Jonathan M Davis wrote:

On Saturday 04 September 2010 12:06:23 Era Scarecrow wrote:

I'm currently porting a D1 code base to D2 which has the
following class
hierarchy:

interface Map
{
   void clear ();
}

class Hashtable : Map
{
  synchronized void clear () {};
}

class HashMap : Map
{
  void clear () {};
}

When I compiler the code I get an error about the "clear"
method in
Hashtable not being covariant with the "clear" method in
Map. Any
suggestions how I could solve this, preferable working in
D1 as well?


   I remember reading about this; The signatures have to match EXACTLY for
it to work. The interface is a declaration of a contract, of what it
expects. If a part of the contract is broken, an error tells you where to
fix it.

  Even if technically it would be compatible, the compiler and type checking
won't allow it. So either synchronize your interface as well, or drop it
from the implementation.

  A third option, is to match the declaration, and have a private function
that is synchronized that is called from clear. At least, i believe this
is right.

  Era


Also, according to TDPL, either your _entire class_ is synchronized, or none of
it is. So, synchronized really belongs on the class, not the function, and I
wouldn't expect it to compile if only a portion of your functions are
synchronized (though I don't know how close the current dmd is to TPDL with
regards to synchronized).

- Jonathan M Davis


Ok, that is good to know.


--
/Jacob Carlborg


Re: Synchronized methods in D2

2010-09-05 Thread Jacob Carlborg

On 2010-09-04 21:06, Era Scarecrow wrote:

I'm currently porting a D1 code base to D2 which has the
following class
hierarchy:

interface Map
{
   void clear ();
}

class Hashtable : Map
{
  synchronized void clear () {};
}

class HashMap : Map
{
  void clear () {};
}

When I compiler the code I get an error about the "clear"
method in
Hashtable not being covariant with the "clear" method in
Map. Any
suggestions how I could solve this, preferable working in
D1 as well?

--
/Jacob Carlborg


   I remember reading about this; The signatures have to match EXACTLY for it 
to work. The interface is a declaration of a contract, of what it expects. If a 
part of the contract is broken, an error tells you where to fix it.

  Even if technically it would be compatible, the compiler and type checking 
won't allow it. So either synchronize your interface as well, or drop it from 
the implementation.

  A third option, is to match the declaration, and have a private function that 
is synchronized that is called from clear. At least, i believe this is right.

  Era


If a private method works then that might be the solution, thanks.


--
/Jacob Carlborg


Re: Generic collection/element function signatures in D2 versus D1

2010-09-05 Thread BLS

On 05/09/2010 02:16, Jonathan M Davis wrote:

void foo(T)(T[] collection, T elem)

 {
  // Blah, whatever
 }



I am curious, how this will look and feel once inout is working ?

inout void foo(T)(inout(T)[] collection, inout T elem)
{
  // Blah, whatever}
}