[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Nilling for GC

Paganoni

4/2/2009 7:16:00 AM

Hi, I've read that
http://whytheluckystiff.net/articles/theFullyUpturn....
I have a background script that runs continuously and threads some tasks
on demand. I keep track of the launched tasks but, by keeping those
tracks, I certainly prevent tasks classes instances and threads
instances to be discarded by the garbage collector.

Data are stored like that :

@workers[:one_category] = []
@workers[:one_category] << {:started_at => Time.now, :thread => th}

So, I'm trying to setup a cleaner that would nil old references but I'm
lost in maps :

@semaphore.synchronize do
@workers.map{|k,v| v.map{|worker| (Time.now - worker[:started_at] > 5
&& worker[:thread].status == false) ? (cleaned +=1; nil) : worker}}
end

When condition is true, cleaned is incremented but the nil does not
replace @workers entry.

So, I did another test :
hs = {}
hs[:toto] = []
hs[:toto] << {:kk => 28, :so => 'yes'}
hs[:toto] << {:kk => 30}
hs[:tata] = []
hs[:tata] << {:kk => 2}

hs = hs.map{|k,v| v.map {|a| a[:kk] > 28 ? nil : a} }
pp hs displays
[[{:kk=>28, :so=>"yes"}, nil], [{:kk=>2}]]

This one works right, for each hs entry, array is nilled if :kk value is
> to 28

Obviously there is a mistake somewhere in the first code source but I
don't find it.

Any help appreciated, thank you

9 Answers

Rick DeNatale

4/2/2009 7:58:00 AM

0

[Note: parts of this message were removed to make it a legal post.]

On Thu, Apr 2, 2009 at 3:19 AM, Paganoni <noway@fakenullvoid.com> wrote:

> Hi, I've read that
> http://whytheluckystiff.net/articles/theFullyUpturn....
> I have a background script that runs continuously and threads some tasks
> on demand. I keep track of the launched tasks but, by keeping those
> tracks, I certainly prevent tasks classes instances and threads
> instances to be discarded by the garbage collector.
>
> Data are stored like that :
>
> @workers[:one_category] = []
> @workers[:one_category] << {:started_at => Time.now, :thread => th}
>
> So, I'm trying to setup a cleaner that would nil old references but I'm
> lost in maps :
>
> @semaphore.synchronize do
> @workers.map{|k,v| v.map{|worker| (Time.now - worker[:started_at] > 5
> && worker[:thread].status == false) ? (cleaned +=1; nil) : worker}}
> end
>
> When condition is true, cleaned is incremented but the nil does not
> replace @workers entry.
>
> So, I did another test :
> hs = {}
> hs[:toto] = []
> hs[:toto] << {:kk => 28, :so => 'yes'}
> hs[:toto] << {:kk => 30}
> hs[:tata] = []
> hs[:tata] << {:kk => 2}
>
> hs = hs.map{|k,v| v.map {|a| a[:kk] > 28 ? nil : a} }
> pp hs displays
> [[{:kk=>28, :so=>"yes"}, nil], [{:kk=>2}]]
>
> This one works right, for each hs entry, array is nilled if :kk value is
>
>> to 28
>>
>
> Obviously there is a mistake somewhere in the first code source but I don't
> find it.
>
> Any help appreciated, thank you
>

@workers.map{|k,v| v.map{|worker| (Time.now - worker[:started_at] > 5 #
...

vs.

hs = hs.map{|k,v| v.map {|a| a[:kk] > 28 ? nil : a} }

In the first case you create a new array from the nested map calls and then
THROW IT AWAY, @workers still refers to the old array.

In the second you compute a new array and assign it to hs.

--
Rick DeNatale

Blog: http://talklikeaduck.denh...
Twitter: http://twitter.com/Ri...
WWR: http://www.workingwithrails.com/person/9021-ric...
LinkedIn: http://www.linkedin.com/in/ri...

Eleanor McHugh

4/2/2009 8:27:00 AM

0

On 2 Apr 2009, at 08:19, Paganoni wrote:
> Hi, I've read that
> http://whytheluckystiff.net/articles/theFullyUpturn....
> I have a background script that runs continuously and threads some
> tasks
> on demand. I keep track of the launched tasks but, by keeping those
> tracks, I certainly prevent tasks classes instances and threads
> instances to be discarded by the garbage collector.
>
> Data are stored like that :
>
> @workers[:one_category] = []
> @workers[:one_category] << {:started_at => Time.now, :thread => th}
>
> So, I'm trying to setup a cleaner that would nil old references but
> I'm
> lost in maps :
>
> @semaphore.synchronize do
> @workers.map{|k,v| v.map{|worker| (Time.now - worker[:started_at] > 5
> && worker[:thread].status == false) ? (cleaned +=1; nil) : worker}}
> end

You could write something like:

def thread_dead? worker
(Time.now - worker[:started_at] > 5) && (worker[:thread].status ==
false)
end

@semaphore.synchronize do
hs.delete_if do |k, v|
v.map! { |worker| thread_dead?(worker) ? (cleaned += 1; nil) :
worker }.compact!
v.empty?
end
end


Ellie

Eleanor McHugh
Games With Brains
http://slides.games-with-...
----
raise ArgumentError unless @reality.responds_to? :reason



Paganoni

4/2/2009 2:04:00 PM

0

le 02/04/2009 09:57, Rick DeNatale nous a dit:
>
> In the first case you create a new array from the nested map calls and then
> THROW IT AWAY, @workers still refers to the old array.
>
> In the second you compute a new array and assign it to hs.
>

But can I miss this sort of things for hours ???

Thanks !

Paganoni

4/2/2009 8:11:00 PM

0

le 02/04/2009 10:27, Eleanor McHugh nous a dit:

>
> You could write something like:
>
> def thread_dead? worker
> (Time.now - worker[:started_at] > 5) && (worker[:thread].status ==
> false)
> end
>
> @semaphore.synchronize do
> hs.delete_if do |k, v|
> v.map! { |worker| thread_dead?(worker) ? (cleaned += 1; nil) :
> worker }.compact!
> v.empty?
> end
> end
>
>

Your delete_if solution is quite elegant because self explanatory !

Thanks

Eleanor McHugh

4/2/2009 9:47:00 PM

0

On 2 Apr 2009, at 21:14, Paganoni wrote:
> le 02/04/2009 10:27, Eleanor McHugh nous a dit:
>
>> You could write something like:
>> def thread_dead? worker
>> (Time.now - worker[:started_at] > 5) && (worker[:thread].status
>> == false)
>> end
>> @semaphore.synchronize do
>> hs.delete_if do |k, v|
>> v.map! { |worker| thread_dead?(worker) ? (cleaned += 1; nil) :
>> worker }.compact!
>> v.empty?
>> end
>> end
>
> Your delete_if solution is quite elegant because self explanatory !

Thank you :)

The delete_if could also be written as a one-liner, but it looks uglier:

hs.delete_if { |k, v| (v.map! { |worker| thread_dead?(worker) ?
(cleaned += 1; nil) : worker }.compact! || v).empty? }

It always bugs me that compact! returns nil if no changes occur,
rather than the enum as I seem to use this particular idiom a lot *sigh*


Ellie

Eleanor McHugh
Games With Brains
http://slides.games-with-...
----
raise ArgumentError unless @reality.responds_to? :reason



Michael Malone

4/2/2009 9:54:00 PM

0


> It always bugs me that compact! returns nil if no changes occur,
> rather than the enum as I seem to use this particular idiom a lot *sigh*
>
>
> Ellie
>
> Eleanor McHugh
> Games With Brains
> http://slides.games-with-...
> ----
> raise ArgumentError unless @reality.responds_to? :reason
>
>
>
Yes, I find it equally annoying that strip! has the same bahviour

=======================================================================
This email, including any attachments, is only for the intended
addressee. It is subject to copyright, is confidential and may be
the subject of legal or other privilege, none of which is waived or
lost by reason of this transmission.
If the receiver is not the intended addressee, please accept our
apologies, notify us by return, delete all copies and perform no
other act on the email.
Unfortunately, we cannot warrant that the email has not been
altered or corrupted during transmission.
=======================================================================


Martin DeMello

4/2/2009 9:56:00 PM

0

On Fri, Apr 3, 2009 at 3:16 AM, Eleanor McHugh
<eleanor@games-with-brains.com> wrote:
>
> It always bugs me that compact! returns nil if no changes occur, rather than
> the enum as I seem to use this particular idiom a lot *sigh*

yeah, it seems like a very c-like thing to do :( i'd rather have it
set a (pseudo-)global variable the way regexp matches do.

martin

David Masover

4/2/2009 11:14:00 PM

0

On Thursday 02 April 2009 16:46:37 Eleanor McHugh wrote:

> hs.delete_if { |k, v| (v.map! { |worker| thread_dead?(worker) ?
> (cleaned += 1; nil) : worker }.compact! || v).empty? }
>
> It always bugs me that compact! returns nil if no changes occur,
> rather than the enum as I seem to use this particular idiom a lot *sigh*

It could also be written like this, if I understand it:

hs.delete_if { |k, v| (v.map! { |worker| thread_dead?(worker) ? (cleaned += 1;
nil) : worker }.tap(&:compact!).empty? }

I don't feel strongly about compact! -- after all, it may be useful to know
whether it found anything. But this is exactly what tap is for, right?

For those on 1.8.6:

class Object
def tap
yield self
self
end
end

Eleanor McHugh

4/3/2009 12:24:00 AM

0

On 3 Apr 2009, at 00:13, David Masover wrote:
> On Thursday 02 April 2009 16:46:37 Eleanor McHugh wrote:
>
>> hs.delete_if { |k, v| (v.map! { |worker| thread_dead?(worker) ?
>> (cleaned += 1; nil) : worker }.compact! || v).empty? }
>>
>> It always bugs me that compact! returns nil if no changes occur,
>> rather than the enum as I seem to use this particular idiom a lot
>> *sigh*
>
> It could also be written like this, if I understand it:
>
> hs.delete_if { |k, v| (v.map! { |worker| thread_dead?(worker) ?
> (cleaned += 1;
> nil) : worker }.tap(&:compact!).empty? }
>
> I don't feel strongly about compact! -- after all, it may be useful
> to know
> whether it found anything. But this is exactly what tap is for, right?

I've only just started moving over to 1.9 so I've not used tap(), I'll
bear it in mind for the future. To be honest though I can't recall a
single occasion where I've used compact!() that I didn't find the nil
result inconvenient and have even been known to redefine it to work
the way I prefer when it's been frequently used in a program :)


Ellie

Eleanor McHugh
Games With Brains
http://slides.games-with-...
----
raise ArgumentError unless @reality.responds_to? :reason