November 23, 2006
On Sun, 19 Nov 2006 23:56:22 +0000 (UTC), Mike Capp
<mike.capp@gmail.com> wrote:

>Georg Wrede wrote:
>
>> Having such a library would make a huge difference
>> in every C++ vs D discussion! The opposition would
>> have a lot less ammunition against us.
>
>Huh? When did this become an adversarial thing? If you're trying to convince someone that D is a better fit for their needs, labelling them "the opposition" probably isn't going to help.

Yeah, but, well...

I often get told I'm oversensitive and I take things too literally. My view is that it happens to everyone.

There obviously is an 'us' in this issue, and at least one 'them'. And there is a disagreement between the 'us' and 'them' groups. No matter how benign and constructive the intent is, adversarial language can be hard to avoid.

-- 
Remove 'wants' and 'nospam' from e-mail.
November 23, 2006
On Mon, 20 Nov 2006 20:37:11 +1100, Jeff <jeffrparsons@optusnet.com.au> wrote:

>> Indeed.  The people who really need to be GC-free are a tiny minority. Wasting a lot of manpower creating a non-GC library just people who don't want to convert from C++ will have one less justification for not using D sees like a huge waste of effort to me.
>
>What about game developers? At least with the current GC, although use of malloc/free isn't strictly deterministic, aren't you far less likely to end up with huge (by game standards, and hence unacceptable) pauses to execution? Preallocation of everything isn't always possible.

You do the allocation/deallocation at times when you can afford the pauses, such as between levels. But then, sometimes there are no such times.

I've never seen the source of the GTA games, of course, but here is some reasoning based on playing them...

Consider Vice City. When crossing from one side of the map to another, you get a delay for loading etc.

Now consider San Andreas - a much larger game that avoids those delays. But if you drive fast enough in San Andreas, you can outrun the loading for LOD and textures, and can end up driving through low-detail scenery and crashing into things you can't see.

That is, San Andreas basically has (1) a high priority thread for
rendering and up-to-the-millisecond game logic, and (2) a low prioriy
thread that lags behind, loading new scenery using left-over time.

Thread (1) must read dynamically allocated memory - after all, the scenery that is loaded must get rendered - but I doubt that it dynamically allocates or frees any memory at all for itself.

Thread (2) could use GC or malloc/free. Either way, it has essentially the same issue. It is designed as a slow process that doesn't need to keep bang up to date, and so in some situations it may lag.

Thread 1 cannot afford to do dynamic allocation and freeing. Thread 2 could use either GC or malloc/free and it doesn't matter. I suspect that that's a very common pattern.

-- 
Remove 'wants' and 'nospam' from e-mail.
November 23, 2006
On Mon, 20 Nov 2006 16:57:36 +0100, xs0 <xs0@xs0.com> wrote:

>Miles wrote:
>> An extra field will be needed anyway since you need
>> reference count for the array, just put it along with the beginning of
>> the array and only a single pointer will be needed for both reference
>> count and beginning of array.
>
>But with GC, the extra field is not "needed anyway".. Furthermore, you can "slice" an arbitrary region of memory, and it still behaves like any other slice; with malloc, you can only slice regions specifically enabled for slicing (i.e. those that have the reference counter)

I haven't really tried to understand all these extra field and other bits about slices. I just can't help being reminded about an old COM criticism.

In COM, you only ever have pointers to interfaces, which are not considered to equate to the object itself. The object is created when you get the first interface, and deleted when the reference count drops to zero.

If you want an object for some reason, but don't want any particular interface, you acquire the IUnknown interface.

Reference counting is one of the main hassles in COM. It sounds like GC, but the programmer has to ensure for himself that every increment is correctly matched by a decrement.

According to one ex-Microsoft guy (sorry, I forget who) he pointed out the mistake in this before COM was every released, but they had already committed a lot to it and didn't make the proposed change.

The point is this - instead of reference counting, the programmer should explicitly create the object once. Then, he should request the needed interfaces. Requesting and releasing interfaces should not require reference counting. Its the programmers responsibility to not use interfaces after the object has been destroyed (though it would be possible to break the links to the interfaces when the object is destroyed, so using dead interfaces would trigger an exception).

If this sounds hard work, consider that programmers do exactly this all the time. You shouldn't use a record lock when the file has been closed, for instance, or (in Windows) send a message to a window that has been destroyed.

The same could apply to a slice. The slice is valid only as long as the sliced object is valid. If the slice will outlive the original object, you have to make a copy. Call it a 'slice pointer' or 'slice handle' and it should be understood that it is only valid as long as the original object is valid.

And there are efficiency arguments to doing this - the original object isn't artificially kept hanging around when you only need the slice. Just as there's other efficiency arguments for leaving it to the GC, of course.

It's horses for courses again. And while I doubt I'd ever really do slicing like that in D (or rather, I doubt I'd be concerned about losing the special syntax), it's nice to know that I can opt out of using the GC if I ever find a special case where I care.

-- 
Remove 'wants' and 'nospam' from e-mail.
November 24, 2006
On Tue, 21 Nov 2006 09:01:58 +0000 (UTC), Boris Kolar
<boris.kolar@globera.com> wrote:

>== Quote from Walter Bright (newshound@digitalmars.com)'s article
>> No. But most RAII usage is for managing memory, and Boris didn't say why he needed RAII for the stack allocated objects.
>
>Mostly for closing OS handles, locking, caching and stuff. Like:
>  getFile("a.txt").getText()
>
>Normally, one would have to:
>  1. open the file (which may allocate caching buffers, lock the file, etc.)
>  2. use the file (efficiently)
>  3. close the file (frees handles, buffers, releases locks, etc.)
>
>It's a common design pattern, really.

I do a lot the same too. And then I find that there are cases where I really wish I could switch off the constructor and destructor, since I want uninitialised memory ready to hold an object that I can't construct yet.

In C++ I fix that by using placement new and explicit destructor calls, and using types along the lines of char[sizeof(blah)].

In D it works out a bit different. I use a struct instead of a class, and so I opt out of having initialisation and cleanup by default. If I want them, I can use the scope statement to ensure they get done.

Of course that also means opting out of having inheritance etc.

Anyway, beyond a certain point, you cannot eliminate complexity. You can only move it from one place to another.

In the case stack-allocated objects, there is (currently) a bit more complexity in D. You can't really do RAII except in the slightly defeating-the-point approach of explicit initialisation and cleanup (though the scope statement at least allows you to keep them together in the code). It can be a bit annoying, I agree. But then, D is being actively developed and stack allocation of objects does seem to be on the to-do list.

-- 
Remove 'wants' and 'nospam' from e-mail.
November 24, 2006
On Mon, 20 Nov 2006 17:25:26 +0100, Frits van Bommel <fvbommel@REMwOVExCAPSs.nl> wrote:

>> Cyclic references is a problem only when using GC. If the programmer wants to use a malloc-based allocation, he knows he should handle cyclic references himself. Not a problem.
>
>Actually, cyclic references are not a problem for GC. Not having to handle them is in fact one of the benefits of GC, or (depending on how you look at it), having to handle them is a problem with reference counting.

The problem is ensuring proper cleanup, such as closing files, releasing handles and locks, etc when using an RAII approach. The GC cannot know what order to do the destructors/finalisers/whatever in. The Java solution is not to bother - it doesn't guarantee that finalisers will be called.

BUT - how do cyclic references occur in relation to slicing? It sounds very odd. I can certainly see the point of chains (slices of slices) but I can't see how cycles could arise at all.

Cycles are only common in certain types of programming, such as data structure handling (which should normally be packaged up in a container library). They can happen in user interface stuff (child and parent windows having references to each other) but even this should be easily avoidable. Don't save the parent/child references in your own objects - trust the platforms GUI data structures and request the references you need when you need them.

-- 
Remove 'wants' and 'nospam' from e-mail.
November 24, 2006
Steve Horne wrote:
> BUT - how do cyclic references occur in relation to slicing? It sounds
> very odd. I can certainly see the point of chains (slices of slices)
> but I can't see how cycles could arise at all.

Take this type:

struct S {
	S[] slice;
	// ... some more stuff
}

Then just allocate some arrays of these and set members of their elements to slices of them.
November 24, 2006
Boris Kolar wrote:
> == Quote from Steve Horne (stephenwantshornenospam100@aol.com)'s article
>> Most real world code has a mix of
>> high-level and low-level.
> 
> True. It feels so liberating when you at least have an option to
> cast reference to int, mirror internal structure of another class,
> or mess with stack frames. Those are all ugly hacks, but ability to
> use them makes programming much more fun.
> 
> The ideal solution would be to have a safe language with optional
> unsafe features, so hacks like that would have to be explicitly marked
> as unsafe. Maybe that's a good idea for D 2.0 :) If D's popularity
> keeps rising, there will be eventually people who will want Java or
> .NET backend. With unsafe features, you can really put a lot of extra

Good Gosh, I hope not, not if that means wrecking the language to conform to those runtimes. Look at what MS has done with (or to!) C++.Net - yikes!.

D is aimed primarily at the native compilation / systems programming space, with great support for general application programming. Just like C/++. And there will be plenty of room for all of the best native / JIT / interpreted languages for a long time to come.

It's the old 80-20 rule - 20% of the available .Net and Java libraries are used for 80% of development work. So if most of the effort is concentrated on the 20% most often used, D libraries will be a reasonable alternative for 80% of the applications out there. The other library fluff can come later. Actually I wouldn't be surprised to learn that it's more like 90-10.

> power in the language (opAssign, opIdentity,...) that may work or may
> not work as intended - but it's programmer's error if it doesn't
> (intimate knowledge of compiler internals is assumed).
November 24, 2006
On Fri, 24 Nov 2006 10:19:33 +0100, Frits van Bommel <fvbommel@REMwOVExCAPSs.nl> wrote:

>Steve Horne wrote:
>> BUT - how do cyclic references occur in relation to slicing? It sounds very odd. I can certainly see the point of chains (slices of slices) but I can't see how cycles could arise at all.
>
>Take this type:
>
>struct S {
>	S[] slice;
>	// ... some more stuff
>}
>
>Then just allocate some arrays of these and set members of their elements to slices of them.

OK, that certainly answers my question.

OTOH why would you do that? This doesn't look to me like something that would arise in practice.

If you have an object of type S that contains (a reference to) an array of type S, that suggests some kind of digraph data structure - eg a tree - to me. Recursive types are almost always data structure related. And in this case, it's a type that probably needs rethinking - it is generally much better for each node to have a (fixed size) array of references to other nodes rather than a single reference to an array of other nodes.

Anyway, if this is a data structure node, you really don't want to assign a slice to that array. If you remove items by slicing (using a reference-based slicing method) you never really remove dead items. You only hide them, since the original array remains so that the slice can reference it. To do genuine removal you need to either modify the original array, or else copy from the slice to create a replacement array.

-- 
Remove 'wants' and 'nospam' from e-mail.
November 24, 2006
On Thu, 23 Nov 2006 13:25:29 -0800, Steve Horne <stephenwantshornenospam100@aol.com> wrote:

> On Wed, 22 Nov 2006 09:20:17 +0000 (UTC), Boris Kolar
> <boris.kolar@globera.com> wrote:
>
>> == Quote from Steve Horne (stephenwantshornenospam100@aol.com)'s article
>>> Most real world code has a mix of
>>> high-level and low-level.
>>
>> True. It feels so liberating when you at least have an option to
>> cast reference to int, mirror internal structure of another class,
>> or mess with stack frames. Those are all ugly hacks, but ability to
>> use them makes programming much more fun.
>>
>> The ideal solution would be to have a safe language with optional
>> unsafe features, so hacks like that would have to be explicitly marked
>> as unsafe. Maybe that's a good idea for D 2.0 :) If D's popularity
>> keeps rising, there will be eventually people who will want Java or
>> .NET backend. With unsafe features, you can really put a lot of extra
>> power in the language (opAssign, opIdentity,...) that may work or may
>> not work as intended - but it's programmer's error if it doesn't
>> (intimate knowledge of compiler internals is assumed).
>
> Hmmm
>
> C# does that safe vs. unsafe thing, doesn't it. My reaction was
> basically that I never used the 'unsafe' stuff at all. I learned it,
> but for anything that would need 'unsafe' I avoided .NET altogether.
>
> Why?
>
> Well, what I didn't learn is exactly what impact it has on users. As
> soon as I realised there is an impact on users, I felt very nervous.
>
> If code could be marked as unsafe, and then be allowed to use some
> subset of unsafe features, I'd say that could be a good thing. But it
> should be an issue for developers to deal with, not users.
>
> D is in a good position for this, since basically unsafe blocks should
> be highlighted in generated documentation (to ensure they get more
> attention in code reviews etc).
>
> Also, possibly there should be a white-list of unsafe blocks to be
> allowed during compilation - something that each developer can hack
> for his own testing builds, but for the main build comes from some
> central source. Unsafe modules that aren't on the list should trigger
> either errors or warnings, depending on compiler options.
>


I think one problem with labeling things "unsafe" is that it could imply "buggy" or something else perhaps.  It's an unkown and the implication might /not/ be a popular one in large software projects.  I'm not quite sure how to express that thought completely, though.  I just wonder if developers might look at "unsafe" code section and think "why is it even here if it's unsafe?".  Would NASA like to have "unsafe" code in their projects? What does it really mean?  Does it have different meanings for different language?  I know Modula 3 went that route and obviously thought it was a good idea; but, then again, Modula 3 didn't catch on.

Another issue: C# is designed to be a VM-based language, while D is designed to be a both a general purpose language and a systems programming language.  It seems to me that an "unsafe" keyword has different implications on each language platform, given their different focus. While I understand the idea of "unsafe", I wonder at how such a term might affect D's representation as a system programming language.  What might work well for a VM-based language, might not be very good for D. Or it may be the other way around.  Either way, I don't think comparing C# and D can be done on the same level in this regard.

D likely has to work out these ideas on it's own merit, given the domain it's creating for itself.

-JJR
November 25, 2006
On Fri, 24 Nov 2006 11:52:20 -0800, "John Reimer" <terminal.node@gmail.com> wrote:

>I think one problem with labeling things "unsafe" is that it could imply "buggy" or something else perhaps.

Well, that is just terminology though. Change 'unsafe' to 'permit', as in perhaps some kind of 'permit <feature-name>' block. Reframing it as security permissions as opposed to unsafe code doesn't really change anything, but could make it sound more acceptable.

>Another issue: C# is designed to be a VM-based language, while D is designed to be a both a general purpose language and a systems programming language.  It seems to me that an "unsafe" keyword has different implications on each language platform, given their different focus.

To me, it's mostly about what users see. In particular, I don't want them to see...

"""
WARNING - WARNING - EVIL UNSAFE TERRORIST CODE IS TRYING TO INVADE
YOUR COMPUTER!!!!

PANIC IMMEDIATELY!!!!
"""

-- 
Remove 'wants' and 'nospam' from e-mail.