Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (582)
games submitted by our members
Games in WIP (503)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: 1 [2]
  ignore  |  Print  
  No Mr. GameObject, I expect you to die.  (Read 3568 times)
0 Members and 1 Guest are viewing this topic.
Offline nsigma
« Reply #30 - Posted 2012-11-05 11:09:51 »

WeakHashMap is perfectly capable to act as a cache, as long as it doesn't store strong references in its values. The only downside of WeakHashMap is that it can only function as a very volatile cache. A SoftHashMap would probably be a better fit for a cache, but it's missing from the JRE.

A SoftHashMap would be even less useful as a cache, unless you have a key object that usefully overrides equals().  The WeakHashMap is great for (designed for) a particular type of caching where you need a canonical map from a particular object to information about it - see this article for an example http://www.codeinstructions.com/2008/09/weakhashmap-is-not-cache-understanding.html.

Say you're caching expensive to construct information about an entity.  Once the entity is collected the cached info is irrelevant - hence the use of the WeakHashMap.

In other cases you wouldn't so much want a SoftHashMap as a normal map with SoftReference values (which obviously isn't missing in the JRE - you can just put SoftReferences in a HashMap).  In either case, the value should almost always be a SoftReference.

Yes, ignoring @ra4king's advice here ...  Wink

Praxis LIVE - open-source intermedia toolkit and live interactive visual editor
Digital Prisoners - interactive spaces and projections
Offline sproingie
« Reply #31 - Posted 2012-11-05 16:45:57 »

You don't need an isDead flag if the object can notify everything holding a reference to it when it dies.  Whether this notification is practical or not depends on how many things are holding the reference and what scope they're in.  It certainly is easiest to use the flag if all you're doing is removing and skipping over dead objects.

I think at this point however we may have long ago chased off the original poster  Roll Eyes
Online Riven
« League of Dukes »

JGO Overlord


Medals: 609
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #32 - Posted 2012-11-05 17:02:34 »

You don't need an isDead flag if the object can notify everything holding a reference to it when it dies.  Whether this notification is practical or not depends on how many things are holding the reference and what scope they're in.  It certainly is easiest to use the flag if all you're doing is removing and skipping over dead objects.

In your previous reply you repeated everything that was already said, and well, you did it again! Smiley

Let me join in on the fun! There are two simple, usable approaches:
  • eager cleanup: removing references from all known places, when the object dies
  • lazy cleanup: removing references when encountering them, after the object died

We also didn't chase off the OP, as he informed us he's doing lazy cleanups.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline actual

JGO Coder


Medals: 24



« Reply #33 - Posted 2012-11-05 17:36:28 »

I think at this point however we may have long ago chased off the original poster  Roll Eyes

Haven't scared me away yet! (I can' be awfully brave behind my laptop). As Riven said, I have gone with a mostly lazy approach, although true to form, it isn't lazy everywhere. Right now, my game entities don't all inherit from a commonWhat I am thinking of doing is create an

For convenience, I am thinking of creating an EntityIterator that will remove dead entities as it finds them. So if the entity list looks something like: (0)Alive, (1)Alive, (2)Dead, (3)Dead, (4)Alive, (5) Alive. and you are on element 1 and call next(), it will delete entities 2 and 3 and retrieve item 4. hasNext() would have to be written so that it returns true only if there are alive entities remaining in the list.

I assume that deleting items from the backing list in a next() or hasNext() call breaks the iterator contract. But since it's just for me, it should work fine.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
// I can write 
while (entityIter.hasNext()) {
   Entity e = entityIter.next();
  // do stuff
}

// instead of
while (iter.hasNext()) {

  Entity e = iter.next();
  if (e.isDead()) iter.remove();
  else {
     // do stuff
  }
}




Online Riven
« League of Dukes »

JGO Overlord


Medals: 609
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #34 - Posted 2012-11-05 17:53:12 »

How do you (lazily) cleanup references in fields? You can use the same approach, although it would be a wrapper instead of an iterator. The only downside is that it really affects the verbosity of the code.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline sproingie
« Reply #35 - Posted 2012-11-05 18:08:53 »

I assume that deleting items from the backing list in a next() or hasNext() call breaks the iterator contract. But since it's just for me, it should work fine.

Deleting through the list itself, yes, you'll either get ConcurrentModificationException if you're lucky, or duplicated/skipped items if not.  If you use the iterator's .remove() method, it's fine.  If a lot of your objects die between each pass, you might just want to keep two lists and copy over all the non-dead objects to the other list, then swap the list when done.  Basically a ghetto semispace collector.
Offline actual

JGO Coder


Medals: 24



« Reply #36 - Posted 2012-11-05 19:01:51 »

Quote from: sproingie
Deleting through the list itself, yes, you'll either get ConcurrentModificationException if you're lucky, or duplicated/skipped items if not.  If you use the iterator's .remove() method, it's fine.  If a lot of your objects die between each pass, you might just want to keep two lists and copy over all the non-dead objects to the other list, then swap the list when done.  Basically a ghetto semispace collector.

I meant having the backing list get modified by calling next() or hasNext() on the iterator. Normally, you would expect either of these to modify the backing list.

Quote from: Riven
How do you (lazily) cleanup references in fields? You can use the same approach, although it would be a wrapper instead of an iterator. The only downside is that it really affects the verbosity of the code.

Right now I am just performing the checks whenever I access the item.

1  
2  
3  
4  
5  
6  
7  
8  
9  
if (target != null) {

   if (target.isDead()) {
      // do cleanup
  }
   else {
      // Do whatever with the target
 }
}


I've toyed with the idea of writing a wrapper but haven't really tried that approach yet.
Offline sproingie
« Reply #37 - Posted 2012-11-05 19:12:17 »

I meant having the backing list get modified by calling next() or hasNext() on the iterator. Normally, you would expect either of these to modify the backing list.

If the iterator implements .remove() (it doesn't have to, it depends on the collection) then it's guaranteed to be safe.  It's just faster to do the collect/swap trick if you're doing a lot of modifications, plus it has the effect of making the updates appear atomic to other threads, as long as you synchronize the swap ... but of course it's incompatible with multiple threads actually updating the list (I only had to deal with one writer, multiple readers when I did it).  Tradeoffs all around.



Online Riven
« League of Dukes »

JGO Overlord


Medals: 609
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #38 - Posted 2012-11-05 19:18:49 »

@sproingie: 'actual' doesn't wonder whether it's safe to do, but whether it's correct to do, as it clearly breaks the contract of Iterator.

Calling .next() a number of times, should not have any side effects to the backing collection. As we now use an iterator to remove elements using an iterator of a collection, we are clearly being naughty. Having said that, I wouldn't even give it another thought. Just do what works, get your game playable, and fix issues with interface contracts when you are rich and feel like it.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline sproingie
« Reply #39 - Posted 2012-11-05 19:32:32 »

iterator.remove() doesn't break the contract of Iterator, it's part of the contract of Iterator, albeit an optional one.  As for .next(), the only case I can think of where calling .next() on an iterator would modify the thing being iterated over would be in the case of some kind of lazy stream(*), but that's not the case for any collection class in the JDK, guava, or any others I know of.

(*) - It's rare for stream type classes to implement Iterable/Iterator anyway, since .next() can't throw any checked exception, and IOException is a common one such classes would have to throw)
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Online Riven
« League of Dukes »

JGO Overlord


Medals: 609
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #40 - Posted 2012-11-05 19:34:15 »

iterator.remove() doesn't break the contract of Iterator, it's part of the contract of Iterator, albeit an optional one.
We were talking about iterator.next() modifying the backing collection, which obviously violates the contract of .next().

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Orangy Tang

JGO Kernel


Medals: 51
Projects: 11


Monkey for a head


« Reply #41 - Posted 2012-11-05 19:59:42 »

Calling .next() a number of times, should not have any side effects to the backing collection. As we now use an iterator to remove elements using an iterator of a collection, we are clearly being naughty. Having said that, I wouldn't even give it another thought. Just do what works, get your game playable, and fix issues with interface contracts when you are rich and feel like it.

I may have missed something, but couldn't the actual creation of the iterator (ie. collection.iterator()) actually strip out any dead objects? Then the iterator just behaves normally.

Although I'd be slightly worried that the reported size (via .size()) of a collection and the amount of objects you iterate over could not match up. That might trip you up if you're not careful (say, allocating an array and then iterating to fill it up). I don't think you can get a 100% safe collection with the iterator trick, but it's probably close enough that the bugs would be rare if you're aware of it.

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline sproingie
« Reply #42 - Posted 2012-11-05 20:13:51 »

We were talking about iterator.next() modifying the backing collection, which obviously violates the contract of .next().



Doh.  I missed that entirely.
Online Riven
« League of Dukes »

JGO Overlord


Medals: 609
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #43 - Posted 2012-11-05 20:48:46 »

I may have missed something, but couldn't the actual creation of the iterator (ie. collection.iterator()) actually strip out any dead objects? Then the iterator just behaves normally.
That's exactly how it is done. One iterator wrapping another.

I don't think you can get a 100% safe collection with the iterator trick, but it's probably close enough that the bugs would be rare if you're aware of it.
It isn't the aim to create a general purpose collection/iterator pair. The purpose is the write a specialized piece of code that solves a specific problem, and should be regarded an implementation detail, not part of a (defendable) public API.


I really wonder what makes this trivial problem so confusing.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Nate

JGO Kernel


Medals: 129
Projects: 3
Exp: 14 years


Esoteric Software


« Reply #44 - Posted 2012-11-05 21:07:21 »

You summarized everything that was already said Smiley
Aye he did, except he did it clearly in just a few words without any assumptions, egotism, or argumentativeness. Like a breath of fresh air!

Online Riven
« League of Dukes »

JGO Overlord


Medals: 609
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #45 - Posted 2012-11-05 22:24:30 »

You summarized everything that was already said Smiley
Aye he did, except he did it clearly in just a few words without any assumptions, egotism, or argumentativeness. Like a breath of fresh air!
The problem had long been solved, without assumptions, egotism or argumentativeness, before the part about weak references.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline xsvenson
« Reply #46 - Posted 2012-11-06 00:50:35 »

You guys are great. So much smart and fun in one thread.

“The First Rule of Program Optimization: Don't do it. The Second Rule of Program Optimization (for experts only!): Don't do it yet.” - Michael A. Jackson
Offline princec

JGO Kernel


Medals: 284
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #47 - Posted 2012-11-06 10:45:14 »

So much complexity for such a trivial thing  Emo

Cas Smiley

Offline actual

JGO Coder


Medals: 24



« Reply #48 - Posted 2012-11-06 12:11:18 »

So much complexity for such a trivial thing  Emo

What are you talking about? Just last night I got 90% done scoping out my AbstractEntityLifeCycleCollectionFactory. I just need to connect a concrete implementation thereof to one of my XMLConfigurationEnterprise Beans and I should be 60% of the way to being 30% done!  Smiley

Although the discussion has touched on a lot of different topics and whatnot, an iterator that removes dead entities in the background during iteration doesn't strike me as all that complex to write or to use. 
Pages: 1 [2]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xsi3rr4x (72 views)
2014-04-15 18:08:23

BurntPizza (68 views)
2014-04-15 03:46:01

UprightPath (79 views)
2014-04-14 17:39:50

UprightPath (65 views)
2014-04-14 17:35:47

Porlus (80 views)
2014-04-14 15:48:38

tom_mai78101 (104 views)
2014-04-10 04:04:31

BurntPizza (164 views)
2014-04-08 23:06:04

tom_mai78101 (260 views)
2014-04-05 13:34:39

trollwarrior1 (210 views)
2014-04-04 12:06:45

CJLetsGame (220 views)
2014-04-01 02:16:10
List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!