Thread local resource management feature request/discussion

classic Classic list List threaded Threaded
22 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Re: Thread local resource management feature request/discussion

thurstonn
Nitsan Wakart-2 wrote
> And how would you propose dealing with the case where the ThreadLocal
"referent" (ByteBuffer in your case) is strongly reachable outside the
exiting thread's ThreadLocalMap?

I suggest we don't deal with it. If we limited ourselves to features
which cannot be abused we wouldn't have a programming language.
The method is optional, and the default implementation will be empty,
the same way init is.
IMO this is no more risky than leaving it to the user discretion to use
TL get() and at their discretion check/not check for null.
I don't necessarily disagree with that, but as this "thread's" digression (copying context) exposed, it could result in unexpected behavior, that can't just facilely be ascribed to developer error.

It doesn't seem (at least from your example), that your real problem is with a lack of a thread-local lifecycle; it's with a lack of *workable Java finalization*.  Unreachable DirectBytebuffers need to be "cleaned up" before being claimed, whether they be (small-t) thread local, or ThreadLocals, or inter-thread.
That's what finalization is putatively for; it's a violation of SOC to add to ThreadLocals what is a job for DirectByteBuffers, et al.

Questions of design purity aside, implementation has the merit of being very simple.  There is already a (private) exit() method in j.l.Thread, which is where all Thread variables are nulled (including #threadLocals)
It would be simple to add a method to ThreadLocalMap (discardAll?) that would just walk through its entries and invoke discard(T) on each ThreadLocal, as the entries are just {WeakReference<ThreadLocal<T>>, T) } tuples.  Then exit() could be amended to include a call to #threadLocals.discardAll() before nulling. Note: it's unclear which thread invokes Thread#exit(), I don't see why it wouldn't be the Thread's thread (it's awful to write sentences like that!)

Now this wouldn't cover the cases where the ThreadLocal instances were already GC'd (i.e. only weakly-reachable), so those T's wouldn't be discarded, so a slightly different approach would be needed if you want to cover those cases as well.

I don't really have a problem with this, I just wonder if it's plugging thumbs into dikes as opposed to fixing Java finalization, which is the real issue
Reply | Threaded
Open this post in threaded view
|

Re: Thread local resource management feature request/discussion

Nitsan Wakart-2
 > "I don't really have a problem with this, I just wonder if it's
plugging thumbs into dikes as opposed to fixing Java finalization, which
is the real issue"
While finalization is *an* issue I don't think it's the issue here. I
personally think that relying on GC to trigger cleanup logic is not
appropriate in most cases, but this is perhaps not the place to discuss
my aversions. ThreadLocals have an obvious relationship to the thread
lifecycle, that relationship is not well expressed by GC cycles. I would
like to have that relationship better expressed.
An alternative solution, with broader application perhaps, would be to
add a thread shutdown hook. This would solve the thread lifecycle
visibility problem more generally. Using this option to express the
original example:
   final static ThreadLocal<ByteBuffer> TL_BUFFER = new
ThreadLocal<ByteBuffer>() {
     @Override
     protected ByteBuffer initialValue() {
       ByteBuffer bb = ByteBuffer.allocateDirect(4096);
       Thread.currentThread().onThreadExit(() ->
((sun.nio.ch.DirectBuffer)bb).cleaner().clean());
       return bb;
     }
   };
Where onThreadExit (or maybe addThreadExitTask or something) would take
a Runnable.
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
12