On 14.12.2010 22:02, Andrei Alexandrescu wrote:
I kept on literally losing sleep about a number of issues involving containers, sealing, arbitrary-cost copying vs. reference counting and copy-on-write, and related issues. This stops me from making rapid progress on defining D containers and other artifacts in the standard library.

Clearly we need to break this paralysis, and just as clearly whatever decision taken now will influence the prevalent D style going forward. So a decision needs to be made soon, just not hastily. Easier said than done!

I continue to believe that containers should have reference semantics, just like classes. Copying a container wholesale is not something you want to be automatic.

Sure thing.

I also continue to believe that controlled lifetime (i.e. reference-counted implementation) is important for a container. Containers tend to be large compared to other objects, so exercising strict control over their allocated storage makes a lot of sense. What has recently shifted in my beliefs is that we should attempt to implement controlled lifetime _outside_ the container definition, by using introspection. (Currently some containers use reference counting internally, which makes their implementation more complicated than it could be.)

What challenges do we face with this approach? Can you please outline the mechanics of that controlled lifetime outside the container part, e.g. is it by usage of some tricky wrappers?


Finally, I continue to believe that sealing is worthwhile. In brief, a sealing container never gives out addresses of its elements so it has great freedom in controlling the data layout (e.g. pack 8 bools in one ubyte) and in controlling the lifetime of its own storage. Currently I'm not sure whether that decision should be taken by the container, by the user of the container, or by an introspection-based wrapper around an unsealed container.

Your change looks like going with third option, am I correct?


* * *

That all being said, I'd like to make a motion that should simplify everyone's life - if only for a bit. I'm thinking of making all containers classes (either final classes or at a minimum classes with only final methods). Currently containers are implemented as structs that are engineered to have reference semantics. Some collections use reference counting to keep track of the memory used.

Advantages of the change:

- Clear, self-documented reference semantics

- Uses the right tool (classes) for the job (define a type with reference semantics)

- Pushes deterministic lifetime issues outside the containers (simplifying them) and factors such issues into reusable wrappers a la RefCounted.

Disadvantages:

- Containers must be dynamically allocated to do anything - even calling empty requires allocation.

I was of impression that you could allocate class instances almost anywhere (with help of emplace), it's just that heap being the safe default.


- There's a two-words overhead associated with any class object.

- Containers cannot do certain optimizations that depend on container's control over its own storage.

That must have something to do with sealed container being wrappers over unsealed ones, so as I observe your change implies not only a change to final classes. Clearly something is missing in your post can you please be more specific on that change?



What say you?

Andrei


--
Dmitry Olshansky

Reply via email to