FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Mango Containers
Goto page 1, 2, 3, 4, 5, 6  Next
 
Post new topic   Reply to topic     Forum Index -> Mango
View previous topic :: View next topic  
Author Message
teqdruid



Joined: 11 May 2004
Posts: 390
Location: UMD

PostPosted: Fri May 27, 2005 1:56 pm    Post subject: Mango Containers Reply with quote

Since I'm interested in getting a containers lib in Mango pretty soon (read: last week) I figured I'd start the discussion.

Since there are at least a few containers libs out there, it probably doesn't make sense to start from square one. A few possibilites to consider (if the authors consent) are:
DTL
MinTL
Indigo
Any others?

Also, what features do people feel are important to a container lib in mango? A few to consider are:
Thread-safeness
Hierarchy (including interfaces, ect...)
Any others? Those are my important points.

So, what are people's thoughts on the subject? Any opinions on the above libraries, and features?

Kris, since a containers lib is my current big stumbling block, I'd like to get a move on this. What are you current thoughts? Do you mind if I investigate this?

-John
Back to top
View user's profile Send private message Send e-mail AIM Address
kris



Joined: 27 Mar 2004
Posts: 1494
Location: South Pacific

PostPosted: Fri May 27, 2005 2:41 pm    Post subject: Reply with quote

Go for it, John! I've got too many other things on my plate, so I'm very glad to hear you're willing to take this on.

FWIW, I'd prefer to see a class-based approach ~ a reasonably thin hierarchy, with possibly an Interface here or there to make certain things compatible (though D can sometimes have noticable overhead for interfaces).

I think thread-awareness is perhaps more important than thread-safety ~ meaning that I wouldn't want to see synchronization blocks scattered throughout the code (for performance reasons), but an optional synched version of some container would be very useful. Note that certain implementations can be both thread-safe and hi-performance: mango.cache.HashMap is such a beast, and hails from the house of Doug lea. Would be great to get a set of containers along those lines, but I think that might be expecting too much?

Again FWIW, I have a certain distaste for excessive use of Templates, useful though they are. But that's perhaps a personal issue Twisted Evil

I haven't seen Ben's recent attempts at wrapping classes around MinTL, but that's a pretty good approach; whereas Indigo is perhaps closest to Mango in terms of general notions? DTL may never see the light of day Shocked

Adopting Ben's Locks package would be a good thing. It's a straight port of Doug Lea's mid-level utilities ~ the same ones that are in the latest release of Java. Very useful for multi-threading.
Back to top
View user's profile Send private message
teqdruid



Joined: 11 May 2004
Posts: 390
Location: UMD

PostPosted: Sat May 28, 2005 1:01 am    Post subject: Reply with quote

I believe we are thinking along the same lines.

Does DTL even compile with the latest DMD? If it does, I'd rather not exclude it from investigation altogether.
Back to top
View user's profile Send private message Send e-mail AIM Address
kris



Joined: 27 Mar 2004
Posts: 1494
Location: South Pacific

PostPosted: Sat May 28, 2005 3:24 pm    Post subject: Reply with quote

Sounds good.

I'm gonna' have a go at migrating Ben's port of Doug Lea's Lock library.
Back to top
View user's profile Send private message
kris



Joined: 27 Mar 2004
Posts: 1494
Location: South Pacific

PostPosted: Sun May 29, 2005 12:02 am    Post subject: Reply with quote

That went along without too much trouble. Got the stuff operational on Ares too.

I moved Ben's 'atomic' utilities into the mango.sys package and fixed some bugs in the assembler code within. Prof Lea's designs are really well done ~ particularly for such a grungy area of functionality ~ and Ben seems to have done a nice job adding the appropriate D'isms.

If Prof Lea has more containers along the lines of ConcurrentHashMap, that might be a good place to look. Here's a write up on why Lea's ConcurrentHashMap is the real McCoy: http://www-106.ibm.com/developerworks/java/library/j-jtp08223/

And here's a link to some of his work on other containers: http://gee.cs.oswego.edu/dl/concurrency-interest/index.html

Here's a read on thread-safety: http://www-106.ibm.com/developerworks/java/library/j-jtp09263.html

Oh; here's an important one ~ the benefits of immutability: http://www-106.ibm.com/developerworks/java/library/j-jtp02183.html
Back to top
View user's profile Send private message
teqdruid



Joined: 11 May 2004
Posts: 390
Location: UMD

PostPosted: Mon May 30, 2005 12:46 am    Post subject: Reply with quote

Since I haven't gotten any other input, I've looked at Indigo and MinTL, although I haven't had a chance to take a look at Ben's new class-based stuff yet. The biggest difference, to me, is that Uwe's code is more readable and better documented (sorry Ben).

As they currently both stand, they both provide some solid containers. Neither of them appear to be thread-aware (with the notable exception of the concurrent stuff in MinTL) and neither of them provide a polymorphic approach. These (in my mind) are two characteristics that make something Mango-caliber.

As such, unless MinTL's polymoric stuff is pretty good, I'd like to go ahead and start the Mango containers with the OO skeleton- interfaces and such. Once that's done, we can merrily take the various implementations from both projects (pending their author's approval) and modify them to implement our structure.

I'm also inclined to design in a manner very similar to Java's collections. That is, a set for each basic container type, all of which extend a "Container" interface. I'd also like to go a similar route with thread-awareness and create wrapper classes like Java's Collections.synchronized*() does. This is not to say that this will be the only way to create synchronized containers, but it will provide a way to wrap any container to be "thread-safe".

In terms of mutability, I don't have any thoughts. We could provide an ImmutableSet (or other container) interface, and implement it, but I'm not certain how this should fit into the hierarchy, and how it should be related to the mutable containers. I do, however, think that (in naming) mutability should be assumed for containers. In other words, I'd rather not have MutableSet- just Set, and ImmutableSet, as I believe that mutable containers are far more common. I do see the advantages of immutable containers, and would like to provide them (mostly 'cause I wanna use them.)

Your thoughts?
Back to top
View user's profile Send private message Send e-mail AIM Address
kris



Joined: 27 Mar 2004
Posts: 1494
Location: South Pacific

PostPosted: Mon May 30, 2005 12:44 pm    Post subject: Reply with quote

As far as mutability goes, it might be sufficient to simply ensure all mutator methods are in a derived class; as in MutableList derives from List?

That way, one can specify the argument of a function to be just 'List' and the caller will thus be assured the content won't change. That approach can be very effective, but it can make a rat's nest out of an existing design; especially interfaces ~ it's something that has to be considered up-front.

- Kris
Back to top
View user's profile Send private message
teqdruid



Joined: 11 May 2004
Posts: 390
Location: UMD

PostPosted: Mon May 30, 2005 3:09 pm    Post subject: Reply with quote

Quote:
As far as mutability goes, it might be sufficient to simply ensure all mutator methods are in a derived class; as in MutableList derives from List?

That way, one can specify the argument of a function to be just 'List' and the caller will thus be assured the content won't change.


This is true, but look at it from the point of view of the function accepting the List. Since a List can be mutable, there is no guarantee that the list won't change. This is a problem if the function stores it somewhere, or in multi-threaded environments.

The most reasonable interface structure to me seems to be something like:
Code:
Collection
   List
      MutableList
      ImmutableList


The big problem here is that Interfaces are not covariant with classes in D. For those unfamiliar with this issue, that means that if the above interface structure is used, any implementing class would need signatures like:
Code:
class MyList : MutableList {
   MutableList opSlice(int a, int b);
}

Whereas one would usually prefer:
Code:
class MyList: MutableList {
   MyList opSlice(int a, int b);  //This won't work in D
}


This means that one must write code like:
Code:
 MutableList list = new MyList();
MutableList list1 = list[0..3];


Which prohibits one from using any "special" methods in MyList. Basically, all implementations of MutableList are just flat implementations. They can't do anything special unless they provide a set of methods with different names. It sucks.

Ben Hinkle has aparantly abandoned interfaces in creating his polymorphic MinTL. In using only classes, he's got total covariance. I'm not certain this is the way to go, as it precludes a few things. For instance, if one has an existing Queue class that furfills some special functionality, and he wants to be able to interface it with Mango container code, all he must do is have it implement one of Mango's interfaces. However, if Mango doesn't provide interfaces, he must subclass one of our abstract classes. If his Queue class already subclasses something, he's screwed.

So, here are our options, as I see it:
-Use just interfaces, and hope that someone figures out how to get interface covariance to work.
-Use abstract classes, and be a little restrictive. This probably won't affect too many people

Neither look appealing to me. While the latter is the pragmatic way to go at this point, I'd prefer to be an optimist and choose the former. I'm pretty confident that class/interface covariance can be achieved, and I feel it'll have to be done at some point.

Your thoughts?
Back to top
View user's profile Send private message Send e-mail AIM Address
kris



Joined: 27 Mar 2004
Posts: 1494
Location: South Pacific

PostPosted: Mon May 30, 2005 4:15 pm    Post subject: Reply with quote

teqdruid wrote:
Quote:
As far as mutability goes, it might be sufficient to simply ensure all mutator methods are in a derived class; as in MutableList derives from List?

That way, one can specify the argument of a function to be just 'List' and the caller will thus be assured the content won't change.


This is true, but look at it from the point of view of the function accepting the List. Since a List can be mutable, there is no guarantee that the list won't change. This is a problem if the function stores it somewhere, or in multi-threaded environments.

Small misunderstanding there, due to language usage: I was actually talking about the callee argument ~ the declared parameter list of the callee ~ not the caller. This inverts what you read ~ the contract exposed by the callee asserts it will not mutate the content. If the caller mutates said content concurrently to the callee invocation, then that's a different issue - but it's one in the hands of the caller instead. Much easier to deal with, and gives you much of what interfaces are designed to expose: a stated contractual obligation.

teqdruid wrote:
So, here are our options, as I see it:
-Use just interfaces, and hope that someone figures out how to get interface covariance to work.
-Use abstract classes, and be a little restrictive. This probably won't affect too many people

Neither look appealing to me. While the latter is the pragmatic way to go at this point, I'd prefer to be an optimist and choose the former. I'm pretty confident that class/interface covariance can be achieved, and I feel it'll have to be done at some point.

Your thoughts?

Yeah, it's a problem I've faced within Mango. In retrospect, I would take out some of the interfaces used there (IBuffer, for example) since one has to balance the reality of whether those 'bridges' would ever be built.

As a suggestion: if you were to design without Interfaces, and avoid the covariance issue, one could add corrected Interfaces at a later date; yes? I mean, once the convariance issue is fixed ...

If so, a possible hierarchy (sans interfaces) might look like so?
Code:
Collection
  List
    MutableList
Back to top
View user's profile Send private message
teqdruid



Joined: 11 May 2004
Posts: 390
Location: UMD

PostPosted: Tue May 31, 2005 4:43 pm    Post subject: Reply with quote

Quote:
Small misunderstanding there, due to language usage: I was actually talking about the callee argument ~ the declared parameter list of the callee ~ not the caller. This inverts what you read ~ the contract exposed by the callee asserts it will not mutate the content. If the caller mutates said content concurrently to the callee invocation, then that's a different issue - but it's one in the hands of the caller instead. Much easier to deal with, and gives you much of what interfaces are designed to expose: a stated contractual obligation.


Actually, it's the caller changing the Object that I'm referring to. To be able to support both contracts I'd create a hierarchy like:
Code:
Container
   List
      MutableList
      ImmutableList


Also, I've been leaning towards Container instead of Collection because I think it's more suscinct. I think both you and I are more used to Java's Collection name, but didn't they only call it Colletion because AWT was using Container? Either way, do you particularly care?

Quote:
As a suggestion: if you were to design without Interfaces, and avoid the covariance issue, one could add corrected Interfaces at a later date; yes? I mean, once the convariance issue is fixed ...

I can't think of a reason why one couldn't go from classes to interfaces, but it feels like one of those things that'll come back to bite us on the ass.

For instance, if anyone using our initial classes does something like:
Code:
List[] lists = ...; //populate
Containers[] containers = cast(Containers[])lists;

It'll work while we're using classes (I think), but once we switch to interfaces, it'll break.

I don't feel like changing from abstract classes to interfaces mid-stream, and using the same names would be a wise idea. An alternative would be to do this hierarchy:
Code:
AbstractContainer
   AbstractList
      AbstractMutableList
      AbstractImmutableList

And use those instead of interfaces until the covariance problem is solved, and we can use interfaces. This, in my opinion, is an ugly solution, as we'll end up with some people using a lot of code with hard (although abstract) classes, instead of interfaces, even once we get interfaces. Seems like a bad road to go down. Unfortunately, D's interfaces aren't transparent as they are in Java.

At this point, I'd like to wait and see how Walter feels about this issue, and if there's any way it's going to get fixed. I just tried it out, and it looks like DMD doesn't even support return type covariance between interfaces, so interfaces, at this point, aren't even an option. This is worse than I thought.
Back to top
View user's profile Send private message Send e-mail AIM Address
kris



Joined: 27 Mar 2004
Posts: 1494
Location: South Pacific

PostPosted: Tue May 31, 2005 5:22 pm    Post subject: Reply with quote

Container? Collection? I don't care Smile

Regarding the covariance issue, it seems to me you might do without interfaces for the most part. I mean, Collection could be an abstract base, and everything else could (on the face of it) be a concrete? What I'm getting at is that Interfaces might be relegated to things like ISortable, or IComparable? You know ~ the "bolt-on" things that you can't do cleanly with a single-object hierarchy?

If that were the case, I think it would be perfectly acceptable to avoid an Interface altogether at the root level. Would probably execute quite a bit faster too! ~ ignoring the vTable, code for converting an object handle into an interface argument is not pretty at all: the two "unnecessary" jmp's executed, just in case the object handle is null, will put perhaps as many bubbles in the CPU pipeline as a scuba tank could. This is arguably OK for large-grained function calls, but totally bogus for the small ones. Of course, it could be that interfaces don't get passed to Containers as method arguments ~ if so, this would not be of concern.

If you went without an Interface at the root, that could mean more difficulty in adopting other, existing, containers. However, given the number of containers we're likely talking about, and the nature of them, I would argue that's not such a big problem ~ even if the covariance concern did not exist. The same might be said for a deep layer of abstract classes. I'm seriously thinking of trying to remove one or two interfaces from the Mango IO layer ~ the only thing stopping me are concerns over backward compatability.

I guess what I'm saying is this: I'm not sure there is actually enough true and tangible value in using interfaces to the degree that's been suggested? Sometimes it's better to just back away a little; kinda like playing less notes in a solo, in order to allow other dynamics a chance to shine through Twisted Evil
Back to top
View user's profile Send private message
teqdruid



Joined: 11 May 2004
Posts: 390
Location: UMD

PostPosted: Sun Jun 05, 2005 4:22 am    Post subject: Reply with quote

OK, so I've been writing an abstract class hierarchy (and started on some basic implementations to test it all) and I've been thinking about the naming and hierarchy for mutable/immutable stuff. Here's my current line of thinking:
Code:
abstract class Container
   abstract class BimutableList
      abstract class List
      final class ImmutableList

Here's my reasoning:
It's pointless to have an ImmutableList abstract class- it doesn't add any methods, and doesn't guarantee any immutability. Therefore, within the List module, I'd like to provide a stock ImmutableList class which is final. I don't see any advantages to letting users add their own immutable list implementations, but I do see many disadvantages.

As for the naming: I stated earlier that I'd rather the name "List" assume mutability. This is for two reasons: most of the time, one wants a mutable list when they use a list. Second, anyone coming from the Java Collections API (and quite possibly others) will be used to using List as a mutable list.

Because there needs to be a list which is a parent of both List and ImmutableList, there is BimutableList. It's neither immutable nor mutable- it can go either way, thus "Bimutable". I kinda like the name.

Obviously, this pattern would be used for other container types as well.

It's a pity that we can't use interfaces, as I would have also liked to do this at the Container level as well. IE:
Code:
interface BimutableContainer;
interface ImmutableContainer: BimutableContainer;
interface Container: BimutableContainer;

interface BimutableList: BimutableContainer;
interface List : BimutableList, Container;
final class ImmutableList: BimutableList, ImmutableContainer;

Or something similar, since I'd like to have methods like:
Code:
addAll(Container c);

in Container, but since there will be immutable containers down the tree from it, we can't have this- we have to assume that Container is bimutable. Smile... ya think that term will catch on?

Your thoughts?
-John
Back to top
View user's profile Send private message Send e-mail AIM Address
Stefan



Joined: 15 May 2005
Posts: 8

PostPosted: Sun Jun 05, 2005 2:34 pm    Post subject: Bimutable Reply with quote

teqdruid wrote:
... we have to assume that Container is bimutable. :)... ya think that term will catch on?

Your thoughts?
-John


+1

I like it :)

Steve
Back to top
View user's profile Send private message
kris



Joined: 27 Mar 2004
Posts: 1494
Location: South Pacific

PostPosted: Mon Jun 06, 2005 5:07 pm    Post subject: Reply with quote

teqdruid wrote:
OK, so I've been writing an abstract class hierarchy (and started on some basic implementations to test it all) and I've been thinking about the naming and hierarchy for mutable/immutable stuff. Here's my current line of thinking:
Code:
abstract class Container
   abstract class BimutableList
      abstract class List
      final class ImmutableList

Here's my reasoning:
It's pointless to have an ImmutableList abstract class- it doesn't add any methods, and doesn't guarantee any immutability. Therefore, within the List module, I'd like to provide a stock ImmutableList class which is final. I don't see any advantages to letting users add their own immutable list implementations, but I do see many disadvantages.

One thing to contemplate is that developers will inevitably declare methods accepting List parameters, though the List itself is not mutated within the code body. They should perhaps be using BimutableList instead, but they just won't ~ people do seem to like using concrete things rather than abstract ones. The problem there is that now one cannot pass an ImmutableList to said method.

This is why Mango makes the read-only class be the root, and concrete, name (such as Url & MutableUrl). That is, the 'default' type is read-only.

Read-only arguments are much more common in OO than one might think, and it's good to get into the habit of making things mutable only when you really have to. The latter is a fundamental within Mango (as a server-oriented/thread-aware library), which makes the focus just a little different from Java containers.

In some respects this comes down to a question of API education. Unfortunately, developers don't read manuals. This is why I tend to steer the obvious name towards read-only to begin with. It's a pretty easy to remember the convention "Oh; this basic class doesn't allow me to edit the content; I should prefix the name with 'Mutable' instead".

Please consider Smile
Back to top
View user's profile Send private message
teqdruid



Joined: 11 May 2004
Posts: 390
Location: UMD

PostPosted: Mon Jun 06, 2005 6:59 pm    Post subject: Reply with quote

kris wrote:

This is why Mango makes the read-only class be the root, and concrete, name (such as Url & MutableUrl). That is, the 'default' type is read-only.

Read-only arguments are much more common in OO than one might think, and it's good to get into the habit of making things mutable only when you really have to. The latter is a fundamental within Mango (as a server-oriented/thread-aware library), which makes the focus just a little different from Java containers.

In some respects this comes down to a question of API education. Unfortunately, developers don't read manuals. This is why I tend to steer the obvious name towards read-only to begin with. It's a pretty easy to remember the convention "Oh; this basic class doesn't allow me to edit the content; I should prefix the name with 'Mutable' instead".

Please consider Smile


I didn't consider that the rest of Mango does it this way. I would say that this, alone, is enough reason to change it. Consistency within the library is of utmost importance.

So it becomes:
Code:
abstract class Container
   abstract class List
      abstract class MutableList
      final class ImmutableList

No structural changes, just naming changes. This does look more Mango-esque. I still think that final class ImmutableList should be provided so that functions can require immutable containers. Yes?
Back to top
View user's profile Send private message Send e-mail AIM Address
Display posts from previous:   
Post new topic   Reply to topic     Forum Index -> Mango All times are GMT - 6 Hours
Goto page 1, 2, 3, 4, 5, 6  Next
Page 1 of 6

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group