On Sat, 2012-06-30 at 23:45 +0200, Stefan Risberg wrote:
> On Sat, Jun 30, 2012 at 02:26:29PM -0700, Evan Nemerson wrote:
> > On Sat, 2012-06-30 at 22:55 +0200, Stefan Risberg wrote:
> > > But if you don't need reference counting and just need data holding like
> > > in
> > > his example wouldn't a struct be much better then a class?
> >
> > Well, he didn't really go into detail about his use case, but we know
> > that he wants to use it with a Gee.HashMap, so he might be doing
> > something like this:
> >
> > Entry entry = {
> > id: 1,
> > name: "foo",
> > data: "data",
> > count: 42,
> > dirty: false
> > };
> > hash_map.set (id, entry);
> >
> > // somewhere else
> > Entry entry = hash_map.get (id);
> >
> >
> > Now first an entry struct gets created on the stack. So far, so good.
> > Next a copy of that struct gets put into the hash_map, since HashMap
> > needs a copy and we can't just give it ours since we might do something
> > else with entry later. Now, you might be thinking you could just do
> > hash_map.set (id, (owned) entry) to give it our copy, but our copy is on
> > the stack--it will be released when the function goes out of scope, so
> > we still need to copy it to the heap.
> >
> > Then, when you want to retrieve the entry from the HashMap, another copy
> > gets made... HashMap still needs its copy, and we need one too.
> >
> > If you were using GLib.HashTable instead of Gee.HashMap, the get method
> > would return an unowned reference, meaning we could avoid a copy with
> > unowned Entry? entry = hash_table.get (id). However, it's easy to
> > forget to add "unowned", especially if you use type inferencing.
> >
>
> That is true, I just think I'm thinking to much c/c++ for my own good.
If you want to think in terms of C/C++, just remember that in Vala
structs are allocated on the stack, classes are on the heap. C just
uses struct for everything with special functions (i.e., malloc) to
allocate on the heap.
> But I don't know how Gee.HashMap does after it is deallocated, but
> if it reacts like lists/maps usally does why no just store a pointer of
> the struct in the map and let it clean up all allocated structs after it
> goes out of scope?
I'm not sure I understand what you're asking. It always just stores a
pointer to the struct... that's why you have to use Entry? instead of
Entry for the type argument. And it does clean up all the structs it
owns when it goes out of scope... that's why it has to make a copy.
If you use a compact class instead of a struct and GLib.HashTable
instead of Gee.HashSet you can completely avoid copying and reference
counting:
var entries = new GLib.HashTable<int32, Entry?> (GLib.direct_hash,
GLib.direct_equal);
Entry entry = new Entry ();
entries[1] = (owned) entry;
At this point, entry is null, since we gave our reference to the hash
table. Of course, for this simple example you could just get rid of the
temporary variable and just do
entries[1] = new Entry ();
Then, look up an entry without copying, you just use an unowned variable
(this is where using GLib.HashTable instead of Gee.HashSet is
important):
unowned Entry? entry2 = entries[1];
At this point the hash table still has the only owned reference, so
there is no need to copy.
-Evan
_______________________________________________
vala-list mailing list
[email protected]
https://mail.gnome.org/mailman/listinfo/vala-list