JNAJack / Callbacks and thread attachment

935 views
Skip to first unread message

neilcsmith.net

unread,
Aug 5, 2011, 6:36:08 AM8/5/11
to Java Native Access
Hi,

A couple of years back I wrote a JNA based binding to JACK (audio
connection kit) for my own application. There was some early code
released separately, but I've just got around to getting the current
code up (http://code.google.com/p/java-audio-utils/ - if anyone's
interested).

My next priority is to work on improving some aspects of the
performance, and I've now implemented direct mapping and better
caching of buffers. However, while I was profiling the library I
noticed a huge number (100,000s) of thread objects claiming to be
created, which I assume are due to AttachCurrentThread being called
every callback into the VM from the native JACK thread (upwards of 500
times a second). Is this going to cause as much of a performance and
GC hit as I expect it might? And, if it is, is there any way of
caching this or manually controlling this from JNA (maybe calling
AttachCurrentThread manually)? I assume the important thing would be
a way to detach the thread when done?

Thanks for your input.

Best wishes, Neil


--
Neil C Smith
Artist : Technologist : Adviser
http://neilcsmith.net

Timothy Wall

unread,
Aug 5, 2011, 8:37:07 AM8/5/11
to jna-...@googlegroups.com
If it's not already attached, JNA attaches on entry and detaches on exit to the callback. It's up to the VM implementation whether this actually results in object creation. You should actually measure the resulting performance hit, because the VM is likely to keep re-using the same allocations since they never have a chance to make it to older GC generations.

If the AttachCurrentThread operation itself has a substantial overhead, you'd need to figure out a way to keep the callback thread mapped. I believe it's possible (I did some work a while back to make it possible to call various JNI methods directly) but it'd probably be nice to have easier access to that option if it turns out it's required.

The VM spec says DetachCurrentThread always detaches, so the only documented way would be to ensure the callback thread is already attached on callback entry.

Neil C Smith

unread,
Aug 5, 2011, 11:48:29 AM8/5/11
to jna-...@googlegroups.com
Hi,

Thanks for the swift response.

On 5 August 2011 13:37, Timothy Wall <tw...@famos.com> wrote:
> If it's not already attached, JNA attaches on entry and detaches on exit to the callback.  It's up to the VM implementation whether this actually results in object creation.  You should actually measure the resulting performance hit, because the VM is likely to keep re-using the same allocations since they never have a chance to make it to older GC generations.
>

Any idea what the standard Oracle VM does? What I've found to read
would suggest 3 different objects but I really don't have much of a
clue with this. Whether this is a performance hit or not I don't know
for sure - would be great to be able to force the thread to remain
attached to see what the difference is, but there seems to be a bit of
a catch-22 with this ...

> If the AttachCurrentThread operation itself has a substantial overhead, you'd need to figure out a way to keep the callback thread mapped.  I believe it's possible (I did some work a while back to make it possible to call various JNI methods directly) but it'd probably be nice to have easier access to that option if it turns out it's required.
>
> The VM spec says DetachCurrentThread always detaches, so the only documented way would be to ensure the callback thread is already attached on callback entry.
>

As far as I can tell, even if there was a way to call the JNI methods
directly, by the time I'm in the JNA callback (which is the only place
I can get access to the callback thread from JACK while using JNA),
then I'm past the if-not-attached logic that will cause the thread to
be detached on callback exit anyway? Would be great if there was a
flag to force no detachment, though I guess that could bring its own
wealth of problems! :-)

neilcsmith.net

unread,
Aug 6, 2011, 5:33:27 AM8/6/11
to Java Native Access
Hi,

A quick follow up to my previous email. This is definitely a big
performance hit. I've tried compiling a version of JNA with thread
detachment commented out in callback.c (I'm not suggesting that as a
fix! :-) ). Using the simple sine wave example from JNAJack, I was
able to get much better low-latency stability from the test version.
Object creation and GC frequency is much lower (in visualvm). And
using top it's very noticeable - the standard JNA version hovers
around 8-9% CPU, and my test version hovers around 2-3% CPU!

Not sure what the actual solution to this problem would be. I assume
thread detach does more important things than just allow the VM to
shutdown, otherwise attach-as-daemon might be a solution? Barring
that, JNA methods along the lines of Native.retainThreadAttachment()
and Native.forceThreadDetachment() (and possibly
Native.retainThreadAttachmentAsDaemon() ) to selectively override the
logic in callback.c while in a callback would seem *really* useful.

fyi - my test was carried out with 3.2.7 as Praxis (the app I use
JNAJack in) is NetBeans RCP based. I can't see any changes in 3.3.0
that would affect this result, but I might be wrong.

Best wishes,

Neil

Neil C Smith
Artist : Technologist : Adviser
http://neilcsmith.net

Timothy Wall

unread,
Aug 6, 2011, 1:28:19 PM8/6/11
to jna-...@googlegroups.com
The callback could indicate a preference for Thread cacheing (i.e. no detach), but you probably also need to be able to force the detach at some point, which is a bit tricky without actually calling the callback or providing additional native hooks.

I don't recall there being any daemon/non-daemon flags available in the JNI for thread attach.

Timothy Wall

unread,
Aug 6, 2011, 2:12:15 PM8/6/11
to jna-...@googlegroups.com

On Aug 6, 2011, at 5:33 AM, neilcsmith.net wrote:

> Hi,
>
> A quick follow up to my previous email. This is definitely a big
> performance hit. I've tried compiling a version of JNA with thread
> detachment commented out in callback.c (I'm not suggesting that as a
> fix! :-) ). Using the simple sine wave example from JNAJack, I was
> able to get much better low-latency stability from the test version.
> Object creation and GC frequency is much lower (in visualvm). And
> using top it's very noticeable - the standard JNA version hovers
> around 8-9% CPU, and my test version hovers around 2-3% CPU!
>
> Not sure what the actual solution to this problem would be. I assume
> thread detach does more important things than just allow the VM to
> shutdown, otherwise attach-as-daemon might be a solution? Barring
> that, JNA methods along the lines of Native.retainThreadAttachment()
> and Native.forceThreadDetachment() (and possibly
> Native.retainThreadAttachmentAsDaemon() ) to selectively override the
> logic in callback.c while in a callback would seem *really* useful.

* The callback should probably have as part of its definition to attach as daemon and/or avoid detaching, just to avoid having to check it on every call
* The callback *may* need to be able to change the detach behavior on the fly. Not sure about that.

I'm not sure what the ramifications would be of always doing attachAsDaemon() and then never doing a detach (which might improve performance for everyone without having to do *any* configuration). Are there cases where you have native threads spawned that aren't technically children of the VM anyway?

Neil C Smith

unread,
Aug 6, 2011, 3:05:25 PM8/6/11
to jna-...@googlegroups.com

Guess you found AttachCurrentThreadAsDaemon now then? :-)

This is basically what I'm considering for my own hacking usage, but
it does feel a bit like a hack. I guess there's a possible memory
leak if lots of native threads are being spawned, because I guess the
Java objects wrapping them never get released. Maybe it could be a
system property, and off by default?

My thoughts on the Native.retainThreadAttachment() and
Native.forceThreadDetachment() were that if there's a simple way of
attaching 2 boolean flags to the thread (to JNIEnv? local frame?) the
code at the end of callback_dispatch in callback.c would become
something like -

if ( (!attached && !retain) || forceDetach) {
(*jvm)->DetachCurrentThread(jvm);
}


Then in the Java callback you could do something like -

if (firstTime) {
Native.retainThreadAttachment();
}
// normal callback code
if (lastTime) {
Native.forceThreadDetachment();
}


This would give the callback control of detaching when necessary and
retain the current semantics if not used at all. I don't know what
the overhead of this approach would be - my C and JNI knowledge is
limited - but, I'd guess it would be close for current usage and far
faster for anyone using the two new methods.

Best wishes and thanks for your time on this one,

Neil

--

Timothy Wall

unread,
Aug 6, 2011, 7:55:21 PM8/6/11
to jna-...@googlegroups.com

On Aug 6, 2011, at 3:05 PM, Neil C Smith wrote:

>
> This is basically what I'm considering for my own hacking usage, but
> it does feel a bit like a hack. I guess there's a possible memory
> leak if lots of native threads are being spawned, because I guess the
> Java objects wrapping them never get released. Maybe it could be a
> system property, and off by default?

Is your native library spawning the thread(s)? can you tell what happens to the java thread object with no detach when the thread exits?


>
> My thoughts on the Native.retainThreadAttachment() and
> Native.forceThreadDetachment() were that if there's a simple way of
> attaching 2 boolean flags to the thread (to JNIEnv? local frame?) the
> code at the end of callback_dispatch in callback.c would become
> something like -
>
> if ( (!attached && !retain) || forceDetach) {
> (*jvm)->DetachCurrentThread(jvm);
> }
>
>
> Then in the Java callback you could do something like -
>
> if (firstTime) {
> Native.retainThreadAttachment();
> }
> // normal callback code
> if (lastTime) {
> Native.forceThreadDetachment();
> }
>
>
> This would give the callback control of detaching when necessary and
> retain the current semantics if not used at all. I don't know what
> the overhead of this approach would be - my C and JNI knowledge is
> limited - but, I'd guess it would be close for current usage and far
> faster for anyone using the two new methods.
>
> Best wishes and thanks for your time on this one,

There is a bit of per-callback storage already so it's not a big deal to keep an extra state flag that you can toggle within the callback. However, the whole pattern doesn't seem quite right. Ideally you'd identify the thread near startup, attach it, and forget about it.

How exactly does your native library manage its threads? does it spawn more than one? is there any control over that behavior?

I'd like to understand better what happens in the VM to threads that are attached but not later detached.

Timothy Wall

unread,
Aug 6, 2011, 8:36:05 PM8/6/11
to jna-...@googlegroups.com
http://download.oracle.com/javase/6/docs/technotes/guides/jni/spec/invocation.html#wp1060

From what I understand above, you could attach your threads as daemon, and leave them attached. They will not prevent the VM from exiting. However, the thread *must* detach before it exits (though the doc doesn't say why), and that little tidbit will vary depending on the application. You don't want to have your callback leave the thread attached, never be called again, and then have the thread exit before the VM does.

On Aug 6, 2011, at 3:05 PM, Neil C Smith wrote:

Neil C Smith

unread,
Aug 7, 2011, 5:49:18 AM8/7/11
to jna-...@googlegroups.com
On 7 August 2011 01:36, Timothy Wall <twal...@java.net> wrote:
> http://download.oracle.com/javase/6/docs/technotes/guides/jni/spec/invocation.html#wp1060
>
> From what I understand above, you could attach your threads as daemon, and leave them attached.  They will not prevent the VM from exiting.  However, the thread *must* detach before it exits (though the doc doesn't say why), and that little tidbit will vary depending on the application.

That's the document where I got the attach-as-daemon information.
There's also this
http://openjdk.java.net/groups/hotspot/docs/RuntimeOverview.html#Thread%20Management|outline
and in particular this paragraph -

--
A native thread attaches to the VM using the JNI call
AttachCurrentThread. In response to this an associated OSThread and
JavaThread instance is created and basic initialization is performed.
Next a java.lang.Thread object must be created for the attached
thread, which is done by reflectively invoking the Java code for the
Thread class constructor, based on the arguments supplied when the
thread attached. Once attached, a thread can invoke whatever Java code
it needs to via the other JNI methods available. Finally when the
native thread no longer wishes to be involved with the VM it can call
the JNI DetachCurrentThread method to disassociate it from the VM
(release resources, drop the reference to the java.lang.Thread
instance, destruct the JavaThread and OSThread objects and so forth).
--

This is where I think the huge overhead in constantly reattaching is
coming from.

> You don't want to have your callback leave the thread attached, never be called again, and then have the thread exit before the VM does.
>

This is what the currently hacked version of JNA I've been
experimenting with does, and I haven't seen any ill effects. However,
from the quoted paragraph I would suggest this is a resource leak as
the references will never be cleared. Not something I guess would be
good in any long-running project.


In response to the email before -

> There is a bit of per-callback storage already so it's not a big deal to keep an extra state flag that you can toggle within the callback. However, the whole pattern doesn't seem quite right. Ideally you'd identify the thread near startup, attach it, and forget about it.

My suggestion is actually for 2 flags - 1 for forcing to remain
attached, and 1 for later forcing detachment. That way for the the
bulk of the time you don't have to do anything with those flags at all
from the Java side, and existing code would run with the same
semantics as now. I can't envisage any way of identifying a native
thread near startup without being in a callback already, in which case
it's inside all the current callback logic. You shouldn't just forget
about it though - if the user takes the decision to manually manage
attachment then they'd have to manually manage detachment too. I can
imagine for most people the extra overhead is not a huge issue and
it's safer to use the current code, but for anything that's callback
heavy then it would be worth it.

> How exactly does your native library manage its threads? does it spawn more than one? is there any control over that behavior?

JACK (http://jackaudio.org/) has a client<>server model. You open a
client in the server, register various callback functions (including
the main process callback) and activate the client. Clients can be
connected together in many different ways to control audio processing
order. The server calls the client process method in a real-time
priority thread - other callbacks for information purposes are called
in a separate lower-priority thread. JACK1 has only a single process
thread, JACK2 is multiprocessor capable and the process thread will
not always be the same one - changing connections between clients can
result in the process thread changing to best suit the client graph.
I'm targeting the common API of both versions.

JACK is sometimes run as a system service, or can be restarted
multiple times during the lifetime of the application. In other
words, the process thread may exist far before and after the Java
application is run, or process threads may be created and destroyed
numerous times during the lifetime of the Java application. (I'm not
seeing any issues from not detaching in either of these scenarios
except for the potential resource leakage, btw).

Best wishes, Neil

Neil C Smith

unread,
Aug 8, 2011, 7:06:16 AM8/8/11
to jna-...@googlegroups.com
Quick comment further to my previous email. I'm also slightly
concerned that at the moment I can't find a way in JACK to get any
notification (in the right thread) that any particular callback is the
last one, which would make manual detachment awkward or impossible
anyway. I was wondering whether it was possible to automatically
track the life of an external thread and detach it, and found these -

http://w01fe.com/blog/2009/05/c-callbacks-into-java-via-jni-made-easyier/
http://developer.android.com/guide/practices/design/jni.html

And just as I was about to send, noticed that you seem to have
commented on the first one in the last few days, so maybe you've had a
similar thought? The Android method is pthread specific using
pthread_key_create, so isn't a cross-platform solution. Would be
great if the JVM could have managed this itself(!) but failing that,
if JNA could I guess that could be a great solution to these issues.

Timothy Wall

unread,
Aug 8, 2011, 9:59:01 AM8/8/11
to jna-...@googlegroups.com
The main issue with not detaching is that "detach" tells the VM to dispose any Java stuff associated with the thread, and the fact that you can't detach outside of the thread itself.

If it's a native-spawned thread, the Java stuff is going to be cleaned up after the callback exits (with the "delete local frame" call). That just leaves the Thread object and housekeeping stuff. If the VM is shutting down, that's a non-issue.

It's the situation where the threads are coming and going that you'd have an issue, but in that case you don't want to avoid the detach anyway.

It's certainly feasible to provide a manual GC of these non-detached threads if there's a way to ping the thread's status if there's a way to effectively perform the detach from outside the thread, or otherwise force a Thread cleanup. That last bit's the tricky part.

Yeah, I was scavenging around the same places as you, I guess. I noticed that a lot of folks get the whole attach/detach thing wrong, but also that the "quick fix" of skipping the "detach" simply resulted in a memory leak of sorts. Worst case, I guess the leak is acceptable if you know what you're doing and why it's there.

Neil C Smith

unread,
Aug 8, 2011, 10:29:58 AM8/8/11
to jna-...@googlegroups.com
On 8 August 2011 14:59, Timothy Wall <twal...@java.net> wrote:
> It's certainly feasible to provide a manual GC of these non-detached threads if there's a way to ping the thread's status if there's a way to effectively perform the detach from outside the thread, or otherwise force a Thread cleanup.   That last bit's the tricky part.
>

Do you feel the approach of a thread-local destructor from both of
those links is not a suitable way to do this?

> Yeah, I was scavenging around the same places as you, I guess.  I noticed that a lot of folks get the whole attach/detach thing wrong, but also that the "quick fix" of skipping the "detach" simply resulted in a memory leak of sorts.  Worst case, I guess the leak is acceptable if you know what you're doing and why it's there.
>

Scavenging's the word! :-) I'd settle for being able to take over
manual control of this somehow from the Java side through JNA - though
automatic thread detachment would be a nice bonus. Do you think
there's a possibility of some fix for this issue finding its way into
JNA? I'd say that the sort of slowdown mentioned in that first linked
post feels about right.

Timothy Wall

unread,
Aug 8, 2011, 1:46:33 PM8/8/11
to jna-...@googlegroups.com

On Aug 8, 2011, at 10:29 AM, Neil C Smith wrote:

> On 8 August 2011 14:59, Timothy Wall <twal...@java.net> wrote:
>> It's certainly feasible to provide a manual GC of these non-detached threads if there's a way to ping the thread's status if there's a way to effectively perform the detach from outside the thread, or otherwise force a Thread cleanup. That last bit's the tricky part.
>>
>
> Do you feel the approach of a thread-local destructor from both of
> those links is not a suitable way to do this?

Well, it makes sense, except that it depends on boost :) Might be possible to extract that little bit of boost magic and convert it to vanilla C. Mainly would need a posix and win32 implementation. Might even be able to rig the native mappings using JNA, and bypass writing any native code altogether...


>
>> Yeah, I was scavenging around the same places as you, I guess. I noticed that a lot of folks get the whole attach/detach thing wrong, but also that the "quick fix" of skipping the "detach" simply resulted in a memory leak of sorts. Worst case, I guess the leak is acceptable if you know what you're doing and why it's there.
>>
>
> Scavenging's the word! :-) I'd settle for being able to take over
> manual control of this somehow from the Java side through JNA - though
> automatic thread detachment would be a nice bonus. Do you think
> there's a possibility of some fix for this issue finding its way into
> JNA? I'd say that the sort of slowdown mentioned in that first linked
> post feels about right.

I think being able to disable the detach operation (or force it) would be useful, and your scenario is not uncommon. It'd be a use at your own risk feature, though, until we can qualify it better.

Main reason I don't like it is that it requires a native recompile :)

Neil C Smith

unread,
Aug 9, 2011, 6:13:00 AM8/9/11
to jna-...@googlegroups.com
On 8 August 2011 18:46, Timothy Wall <twal...@java.net> wrote:
>
> On Aug 8, 2011, at 10:29 AM, Neil C Smith wrote:
>
>> On 8 August 2011 14:59, Timothy Wall <twal...@java.net> wrote:
>>> It's certainly feasible to provide a manual GC of these non-detached threads if there's a way to ping the thread's status if there's a way to effectively perform the detach from outside the thread, or otherwise force a Thread cleanup.   That last bit's the tricky part.
>>>
>>
>> Do you feel the approach of a thread-local destructor from both of
>> those links is not a suitable way to do this?
>
> Well, it makes sense, except that it depends on boost :)  Might be possible to extract that little bit of boost magic and convert it to vanilla C.  Mainly would need a posix and win32 implementation.  Might even be able to rig the native mappings using JNA, and bypass writing any native code altogether...
>

Well, the Android JNI tip doesn't use boost, just pthread, though I
can't seem to find an actual code sample anywhere. Did come across
this - http://www.netmite.com/android/mydroid/dalvik/vm/Thread.c which
shows it in use in Dalvik itself. Like you said though, I guess this
could be done using JNA without writing any native code (although only
if the manual retain/detach option was in?). I presume you could just
create a JNA callback as the destructor passed to pthread (or
windows?) and within that call the equivalent of my suggested
Native.forceThreadDetachment()?


> I think being able to disable the detach operation (or force it) would be useful, and your scenario is not uncommon.  It'd be a use at your own risk feature, though, until we can qualify it better.
>

Documenting it as "here be dragons" is fine with me. I think breaking
any of the current semantics by default would probably be a bad idea
anyway, even if it proves to be stable, but having the option
available would be fantastic.

> Main reason I don't like it is that it requires a native recompile :)

Yes, but it's *so* worth it (nudge, nudge) :-) Anything I can do to
help with testing, let me know.

Timothy Wall

unread,
Aug 9, 2011, 11:12:29 AM8/9/11
to jna-...@googlegroups.com

On Aug 9, 2011, at 6:13 AM, Neil C Smith wrote:

>>
>> Well, it makes sense, except that it depends on boost :) Might be possible to extract that little bit of boost magic and convert it to vanilla C. Mainly would need a posix and win32 implementation. Might even be able to rig the native mappings using JNA, and bypass writing any native code altogether...
>>
>
> Well, the Android JNI tip doesn't use boost, just pthread, though I
> can't seem to find an actual code sample anywhere. Did come across
> this - http://www.netmite.com/android/mydroid/dalvik/vm/Thread.c which
> shows it in use in Dalvik itself. Like you said though, I guess this
> could be done using JNA without writing any native code (although only
> if the manual retain/detach option was in?). I presume you could just
> create a JNA callback as the destructor passed to pthread (or
> windows?) and within that call the equivalent of my suggested
> Native.forceThreadDetachment()?

That'd be the idea. If you "activate" the non-detach, then JNA throws in a callback for thread destruction, and a pthreads solution covers everything except windows and a few mobile implementations. Need an implementation for Windows (probably is some sort of windows event hook to do that).

I generally prefer to use JNA where possible, since it's a lot less management effort over time, so any pthreads or w32 hookup, should definitely done in Java if possible.

>
>
>> I think being able to disable the detach operation (or force it) would be useful, and your scenario is not uncommon. It'd be a use at your own risk feature, though, until we can qualify it better.
>>
>
> Documenting it as "here be dragons" is fine with me. I think breaking
> any of the current semantics by default would probably be a bad idea
> anyway, even if it proves to be stable, but having the option
> available would be fantastic.
>
>> Main reason I don't like it is that it requires a native recompile :)
>
> Yes, but it's *so* worth it (nudge, nudge) :-) Anything I can do to
> help with testing, let me know.

Switch to branch nondetached-callbacks and we can see where it goes.

Requirements so far:

* add thread termination handler to non-detached threads
* add tagging to callback to indicate "attach as daemon"
* add tagging to callback to indicate "don't detach"

ways to do this:
o additional interface "CallbackNoDetach", "CallbackAsDaemon"
o register callback options with JNA: Native.setCallbackOptions(callback, options)
o explicit call from within callback: Native.noDetach() (won't work for "as daemon" without detaching and reattaching)

I think the second option makes the most sense. The first is commingling configuration with implementation, and the last is tweaking the options *after* you really needed them to be applied.


Timothy Wall

unread,
Aug 9, 2011, 11:17:28 AM8/9/11
to jna-...@googlegroups.com
make that branch "callback-threads".


Neil C Smith

unread,
Aug 10, 2011, 12:53:24 PM8/10/11
to jna-...@googlegroups.com
Hi,

On 9 August 2011 16:12, Timothy Wall <twal...@java.net> wrote:
> Switch to branch nondetached-callbacks and we can see where it goes.
>

Am I meant to be able to see this on GitHub in the list of branches?
Either this or "callback-thread"? Sorry, not used GitHub for anything
before so not sure how to find my way around. Do I need an account to
view some branches maybe?

> Requirements so far:
>
> * add thread termination handler to non-detached threads
> * add tagging to callback to indicate "attach as daemon"
> * add tagging to callback to indicate "don't detach"
>

I would be tempted to remove the termination handler for now, but add
in the "force detach" flag. That way it's up to the user to manage
for now, and a utility to manage terminations could happen in time. I
don't think the termination handler replaces the need for "force
detach" anyway. Consider a situation where you're attached to a long
running system service. The thread for this may keep on running long
after you need to be attached to it (ie. you've unregistered your
callback), but if there's no way to force the detach then the thread
is still there, and could stop the VM from closing down if not marked
as a daemon.

>   ways to do this:
>   o additional interface "CallbackNoDetach", "CallbackAsDaemon"
>   o register callback options with JNA: Native.setCallbackOptions(callback, options)
>   o explicit call from within callback: Native.noDetach() (won't work for "as daemon" without detaching and reattaching)
>
> I think the second option makes the most sense.  The first is commingling configuration with implementation, and the last is tweaking the options *after* you really needed them to be applied.
>
>

Agree wholeheartedly with you on option 1. Having not seen any code
you're suggesting yet, I'm still inclined to option 3, but that might
be because I'm not understanding option 2 correctly. The reason is, I
worry that your option 2 is tying the flags to the callback, whereas I
think it needs to be something tied to a particular thread and checked
during the callback handler. Consider a couple of scenarios -

* You have a callback registered to a multi-threaded library and need
to manage the thread attachment differently depending on the context
in which the callback is called. Flags per callback is too coarse
grained to manage this.
* You have a number of callbacks registered to a library (maybe
init(), process() and dispose() ) that will be called in one thread,
and therefore callback flags would be too fine grained to manage this
properly (ie. stay attached from init to dispose)

I understand that option 2 is tweaking some options after they need to
be set, but only in the case of daemon threads. The noDetach and
forceDetach options wouldn't need to be checked until returning from
Java code.

This also makes it clear that you can only call these methods within
the context of a callback. For example, what would forceDetach mean
outside of a callback - you'd have no way of ensuring that the thread
was ever detached unless it was calling in. Throwing an
IllegalStateException if these are called outside a callback would
make more sense to me.

Apologies if I've misunderstood anything you're proposing.

Final thought, while I've got you considering recompiling the native
code! :-) -- One thing I've added in to my hacked version of JNA when
benchmarking this is naming the thread within the attach thread
function. Naming the thread (ie. "JNA-Native"?), and possibly also
putting all callback attachments in their own threadgroup, would be
quite useful for profiling / debugging if this all gets in.

Timothy Wall

unread,
Aug 10, 2011, 2:02:12 PM8/10/11
to jna-...@googlegroups.com

On Aug 10, 2011, at 12:53 PM, Neil C Smith wrote:

> Hi,
>
> On 9 August 2011 16:12, Timothy Wall <twal...@java.net> wrote:
>> Switch to branch nondetached-callbacks and we can see where it goes.
>>
>
> Am I meant to be able to see this on GitHub in the list of branches?
> Either this or "callback-thread"? Sorry, not used GitHub for anything
> before so not sure how to find my way around. Do I need an account to
> view some branches maybe?

me too :) I think you won't be able to see the branch until I actually push something back to the main repo.


Timothy Wall

unread,
Aug 10, 2011, 4:00:40 PM8/10/11
to jna-...@googlegroups.com

On Aug 10, 2011, at 12:53 PM, Neil C Smith wrote:

> Hi,
>
> On 9 August 2011 16:12, Timothy Wall <twal...@java.net> wrote:
>
>> Requirements so far:
>>
>> * add thread termination handler to non-detached threads
>> * add tagging to callback to indicate "attach as daemon"
>> * add tagging to callback to indicate "don't detach"
>>
>
> I would be tempted to remove the termination handler for now, but add
> in the "force detach" flag.

perhaps "requirements" is to strong. "possible features" is better?

> That way it's up to the user to manage
> for now, and a utility to manage terminations could happen in time. I
> don't think the termination handler replaces the need for "force
> detach" anyway. Consider a situation where you're attached to a long
> running system service. The thread for this may keep on running long
> after you need to be attached to it (ie. you've unregistered your
> callback), but if there's no way to force the detach then the thread
> is still there, and could stop the VM from closing down if not marked
> as a daemon.

I think in this case you want to simply attach as daemon. When attached as daemon, eventual detach doesn't really matter.
However, I see no reason to prevent changing the state during the lifetime of the callback.

>
>> ways to do this:
>> o additional interface "CallbackNoDetach", "CallbackAsDaemon"
>> o register callback options with JNA: Native.setCallbackOptions(callback, options)
>> o explicit call from within callback: Native.noDetach() (won't work for "as daemon" without detaching and reattaching)
>>
>> I think the second option makes the most sense. The first is commingling configuration with implementation, and the last is tweaking the options *after* you really needed them to be applied.
>>
>>
>
> Agree wholeheartedly with you on option 1. Having not seen any code
> you're suggesting yet, I'm still inclined to option 3, but that might
> be because I'm not understanding option 2 correctly. The reason is, I
> worry that your option 2 is tying the flags to the callback, whereas I
> think it needs to be something tied to a particular thread and checked
> during the callback handler.

Yes, it's tying the flags to the callback, but are you *really* going to use the same callback objects in two or more places where the flags need to be different?


> Consider a couple of scenarios -
>
> * You have a callback registered to a multi-threaded library and need
> to manage the thread attachment differently depending on the context
> in which the callback is called. Flags per callback is too coarse
> grained to manage this.

This sounds awfully hypothetical. Why would a callback be called in substantially different contexts?


> * You have a number of callbacks registered to a library (maybe
> init(), process() and dispose() ) that will be called in one thread,
> and therefore callback flags would be too fine grained to manage this
> properly (ie. stay attached from init to dispose)

Not following your logic there. More like you're saying you'd like to encapsulate callback thread behavior for re-use.


>
> I understand that option 2 is tweaking some options after they need to
> be set, but only in the case of daemon threads. The noDetach and
> forceDetach options wouldn't need to be checked until returning from
> Java code.

I think you're going to want daemon thread whenever you want to avoid detach, unless you want to make absolutely certain that you don't shut down in the middle of a callback. At any rate, there has to be *some* method of designating "attachAsDaemon" before you get to the callback code. I think it'd be very ugly to set the flag after you get into the callback and then somehow "reattach" after the callback exits.

Another option might be to optionally invoke a "new thread" handler; whenever a new thread is seen in the callback space, a JNA handler is called to figure out what to do with it (which might include setting the thread name, group, etc.). For example:

interface CallbackThreadInitializer {
/* return some flags based on the incoming context, which probably includes the callback being called */
int initialize(context);
}

Then your callbacks don't do any of this stuff. kind of like an uncaught exception handler... just throwin' it out there.


>
> This also makes it clear that you can only call these methods within
> the context of a callback. For example, what would forceDetach mean
> outside of a callback - you'd have no way of ensuring that the thread
> was ever detached unless it was calling in. Throwing an
> IllegalStateException if these are called outside a callback would
> make more sense to me.
>
> Apologies if I've misunderstood anything you're proposing.
>
> Final thought, while I've got you considering recompiling the native
> code! :-) -- One thing I've added in to my hacked version of JNA when
> benchmarking this is naming the thread within the attach thread
> function. Naming the thread (ie. "JNA-Native"?), and possibly also
> putting all callback attachments in their own threadgroup, would be
> quite useful for profiling / debugging if this all gets in.

Perhaps can be done with the thread initializer?

Neil C Smith

unread,
Aug 10, 2011, 7:25:56 PM8/10/11
to jna-...@googlegroups.com
On 10 August 2011 21:00, Timothy Wall <twal...@java.net> wrote:

>> Agree wholeheartedly with you on option 1.  Having not seen any code
>> you're suggesting yet, I'm still inclined to option 3, but that might
>> be because I'm not understanding option 2 correctly.  The reason is, I
>> worry that your option 2 is tying the flags to the callback, whereas I
>> think it needs to be something tied to a particular thread and checked
>> during the callback handler.
>
> Yes, it's tying the flags to the callback, but are you *really* going to use the same callback objects in two or more places where the flags need to be different?
>

Probably not. I'm more considering the opposite scenario where you've
got lots of callbacks being called in the same thread. Doesn't this
approach mean you need to keep these flags in sync across all
callbacks to ensure the thread isn't retained or detached at the wrong
time?

>> Consider a couple of scenarios -
>>
>> * You have a callback registered to a multi-threaded library and need
>> to manage the thread attachment differently depending on the context
>> in which the callback is called.  Flags per callback is too coarse
>> grained to manage this.
>
> This sounds awfully hypothetical.  Why would a callback be called in substantially different contexts?
>
>
>> * You have a number of callbacks registered to a library (maybe
>> init(), process() and dispose() ) that will be called in one thread,
>> and therefore callback flags would be too fine grained to manage this
>> properly (ie. stay attached from init to dispose)
>
> Not following your logic there.  More like you're saying you'd like to encapsulate callback thread behavior for re-use.
>
>

OK, the first scenario was a bit too hypothetical! :-) The second is
basically what I mentioned above - the need to keep flags in a
consistent state across multiple callbacks. JACK (to be
non-hypothetical for a moment) uses lots of different callbacks to
give you information about various changes to the pipeline state.
These are all called in the same thread, so it would be good to keep
it attached, but not have to worry about keeping flags consistent
across all the different callbacks. Because these flags relate to
thread state it just feels like they should be thead-local not
callback-local.


>>
>> I understand that option 2 is tweaking some options after they need to
>> be set, but only in the case of daemon threads.  The noDetach and
>> forceDetach options wouldn't need to be checked until returning from
>> Java code.
>
> I think you're going to want daemon thread whenever you want to avoid detach, unless you want to make absolutely certain that you don't shut down in the middle of a callback.  At any rate, there has to be *some* method of designating "attachAsDaemon" before you get to the callback code.  I think it'd be very ugly to set the flag after you get into the callback and then somehow "reattach" after the callback exits.
>

I agree that feels ugly, though at the same time I'm getting less sure
about attachAsDaemon except in exceptional circumstances; maybe it's
not needed at all? The noDetach / forceDetach pair puts the onus on
wrapper authors to manually manage thread attachment, and ensure
threads are detached and callbacks unregistered at the right time.
Surely the bulk of the time when you want to avoid detach are when you
know you're going to be
called X times or until Y state is reached; you know when is the right
time to tidy up. By saying "keep me attached" aren't you saying that
you expect to be called again and there's more work to be done, in
which case it's not really the same semantics as a daemon thread.

Daemon could be useful if you've attached a callback to a long running
system process and don't know when you might next be called. But, is
relying on this potentially dangerous anyway? Doesn't this mean the
VM could decide just to stop mid-callback, and potentially leave the
system process in a corrupt state because you're only halfway through
interacting with it? Surely it's better to retain manual control, or
just rely on the current attach per callback approach in this case?

> Another option might be to optionally invoke a "new thread" handler; whenever a new thread is seen in the callback space, a JNA handler is called to figure out what to do with it (which might include setting the thread name, group, etc.).  For example:
>
> interface CallbackThreadInitializer {
>        /* return some flags based on the incoming context, which probably includes the callback being called */
>        int initialize(context);
> }
>
> Then your callbacks don't do any of this stuff.  kind of like an uncaught exception handler... just throwin' it out there.
>

Interesting, and could get around the ugliness needed for
attachAsDaemon. However, how would you envisage allowing the state to
be dynamic in this case?

>> Final thought, while I've got you considering recompiling the native
>> code! :-) -- One thing I've added in to my hacked version of JNA when
>> benchmarking this is naming the thread within the attach thread
>> function.  Naming the thread (ie. "JNA-Native"?), and possibly also
>> putting all callback attachments in their own threadgroup, would be
>> quite useful for profiling / debugging if this all gets in.
>
> Perhaps can be done with the thread initializer?

Or perhaps I could just use Thread.setName() in the callback for now -
for some reason I'd missed the fact that you can set this after thread
creation! :-)

Timothy Wall

unread,
Aug 10, 2011, 10:38:09 PM8/10/11
to jna-...@googlegroups.com

On Aug 10, 2011, at 7:25 PM, Neil C Smith wrote:

> On 10 August 2011 21:00, Timothy Wall <twal...@java.net> wrote:
>
>>> Agree wholeheartedly with you on option 1. Having not seen any code
>>> you're suggesting yet, I'm still inclined to option 3, but that might
>>> be because I'm not understanding option 2 correctly. The reason is, I
>>> worry that your option 2 is tying the flags to the callback, whereas I
>>> think it needs to be something tied to a particular thread and checked
>>> during the callback handler.
>>
>> Yes, it's tying the flags to the callback, but are you *really* going to use the same callback objects in two or more places where the flags need to be different?
>>
>
> Probably not. I'm more considering the opposite scenario where you've
> got lots of callbacks being called in the same thread. Doesn't this
> approach mean you need to keep these flags in sync across all
> callbacks to ensure the thread isn't retained or detached at the wrong
> time?

6 vs half dozen. Native.setCallbackFlags(cb, flags) vs (within the callback) Native.setCallbackStateX(). Either way you have to manage when you need to make the calls across which callbacks. If you restrict to within the callback, you can't change the state outside the thread. And the daemon setting *has* to be done outside the thread (or jump through some hoops with multiple attach/detach in order to be able to do it from java within the thread).

I'm about to push some code so you can see better what I mean.

>
>>> Consider a couple of scenarios -
>>>
>>> * You have a callback registered to a multi-threaded library and need
>>> to manage the thread attachment differently depending on the context
>>> in which the callback is called. Flags per callback is too coarse
>>> grained to manage this.
>>
>> This sounds awfully hypothetical. Why would a callback be called in substantially different contexts?
>>
>>
>>> * You have a number of callbacks registered to a library (maybe
>>> init(), process() and dispose() ) that will be called in one thread,
>>> and therefore callback flags would be too fine grained to manage this
>>> properly (ie. stay attached from init to dispose)
>>
>> Not following your logic there. More like you're saying you'd like to encapsulate callback thread behavior for re-use.
>>
>>
>
> OK, the first scenario was a bit too hypothetical! :-) The second is
> basically what I mentioned above - the need to keep flags in a
> consistent state across multiple callbacks. JACK (to be
> non-hypothetical for a moment) uses lots of different callbacks to
> give you information about various changes to the pipeline state.
> These are all called in the same thread, so it would be good to keep
> it attached, but not have to worry about keeping flags consistent
> across all the different callbacks. Because these flags relate to
> thread state it just feels like they should be thead-local not
> callback-local.

I agree, but outside the thread (potentially before the thread is even started) all you have available to identify the future thread is the callback. Even if you were to have JNA call a sort of Thread initializer, you'd still need the callback that was about to be called so you could identify the thread context. It's not like you get some client data that says "this is the connection callback thread" or "this is the data feedback thread". All you have is the callback that's about to be called.

>
>
>>>
>>> I understand that option 2 is tweaking some options after they need to
>>> be set, but only in the case of daemon threads. The noDetach and
>>> forceDetach options wouldn't need to be checked until returning from
>>> Java code.
>>
>> I think you're going to want daemon thread whenever you want to avoid detach, unless you want to make absolutely certain that you don't shut down in the middle of a callback. At any rate, there has to be *some* method of designating "attachAsDaemon" before you get to the callback code. I think it'd be very ugly to set the flag after you get into the callback and then somehow "reattach" after the callback exits.
>>
>
> I agree that feels ugly, though at the same time I'm getting less sure
> about attachAsDaemon except in exceptional circumstances; maybe it's
> not needed at all? The noDetach / forceDetach pair puts the onus on
> wrapper authors to manually manage thread attachment, and ensure
> threads are detached and callbacks unregistered at the right time.
> Surely the bulk of the time when you want to avoid detach are when you
> know you're going to be
> called X times or until Y state is reached; you know when is the right
> time to tidy up. By saying "keep me attached" aren't you saying that
> you expect to be called again and there's more work to be done, in
> which case it's not really the same semantics as a daemon thread.

Not really enough use cases to say.

* you could be saying "i'm listening to this thread forever, never going to remove the callback, but if you need to quit that's ok"
* or "at some point i'm going to unregister the callback, at which point I want to forget the thread" (tricky, since you can only detach from the callback)

Totally depends on the system what the callback semantics might be. DDE is one thing, ssl handshakes another, your system yet another. Some have finite durations and well-defined state machines, some do not.


>
> Daemon could be useful if you've attached a callback to a long running
> system process and don't know when you might next be called. But, is
> relying on this potentially dangerous anyway? Doesn't this mean the
> VM could decide just to stop mid-callback, and potentially leave the
> system process in a corrupt state because you're only halfway through
> interacting with it? Surely it's better to retain manual control, or
> just rely on the current attach per callback approach in this case?

Presumably if halting mid-callback is dangerous to you, then you implement shutdown protections against doing so.


>
>> Another option might be to optionally invoke a "new thread" handler; whenever a new thread is seen in the callback space, a JNA handler is called to figure out what to do with it (which might include setting the thread name, group, etc.). For example:
>>
>> interface CallbackThreadInitializer {
>> /* return some flags based on the incoming context, which probably includes the callback being called */
>> int initialize(context);
>> }
>>
>> Then your callbacks don't do any of this stuff. kind of like an uncaught exception handler... just throwin' it out there.
>>
>
> Interesting, and could get around the ugliness needed for
> attachAsDaemon. However, how would you envisage allowing the state to
> be dynamic in this case?

The initialize would indicate whether you want to keep the thread around and whether it should be daemon. The callback is provided so you have some idea of the native thread context. Then you can use the Thread object to indicate to JNA when you want the thread to be detached (Native.allowDetach(Thread)). The initializer could also provide some place to jam the thread name and thread group (requires the current thread detach and reattach, but that's not a big deal to do as a one-off. Throw in the right locks and checks to avoid extra overhead, and it smells better than doing stuff based on just the callback object (either externally or internally).

>
>>> Final thought, while I've got you considering recompiling the native
>>> code! :-) -- One thing I've added in to my hacked version of JNA when
>>> benchmarking this is naming the thread within the attach thread
>>> function. Naming the thread (ie. "JNA-Native"?), and possibly also
>>> putting all callback attachments in their own threadgroup, would be
>>> quite useful for profiling / debugging if this all gets in.
>>
>> Perhaps can be done with the thread initializer?
>
> Or perhaps I could just use Thread.setName() in the callback for now -
> for some reason I'd missed the fact that you can set this after thread
> creation! :-)

Yeah, I forgot about that too, or maybe found some instances where it didn't work.

Timothy Wall

unread,
Aug 11, 2011, 9:41:43 AM8/11/11
to jna-...@googlegroups.com
Found some interesting behavior on the OSX JVM.

Depending on what the main java thread is doing, the callbck thread mapping may use the same or different Thread objects.

In my tests, if the main thread sleeps the whole time it's waiting for callbacks, I get 10 different threads. If it only sleeps a little bit at a time, the VM seems to re-use the same Thread object.

Note that this is probably a VM-specific optimization that you couldn't really count on...

Neil C Smith

unread,
Aug 11, 2011, 9:54:02 AM8/11/11
to jna-...@googlegroups.com
Hi,

On 11 August 2011 03:38, Timothy Wall <twal...@java.net> wrote:
> I'm about to push some code so you can see better what I mean.
>

I'll reserve much further comment until I've had a chance to look and
play with it. I have a feeling we're saying mostly the same things in
different ways anyway! :-)


> I agree, but outside the thread (potentially before the thread is even started) all you have available to identify the future thread is the callback.    Even if you were to have JNA call a sort of Thread initializer, you'd still need the callback that was about to be called so you could identify the thread context.  It's not like you get some client data that says "this is the connection callback thread" or "this is the data feedback thread".  All you have is the callback that's about to be called.

I still meant this all happening within the callback context. Just
that the flags are thread-local and checked at callback exit - that
way you only have to change the flags in one place. Like I said
though, I might be misunderstanding your intention anyway.


> * or "at some point i'm going to unregister the callback, at which point I want to forget the thread" (tricky, since you can only detach from the callback)
>

I realise that in some cases the only way to deal with this is the
daemon option. However, I still think that's a hack to workaround
this problem, rather than what should be advised as the preferred
approach. Also, if you're not getting lots of regular callbacks then
you're probably not going to get much of a performance improvement
from remaining attached anyway, so could use the current system.


>
> Presumably if halting mid-callback is dangerous to you, then you implement shutdown protections against doing so.
>

Quite! But at the same time, you probably shouldn't be marked as a
daemon in this scenario either.

> The initializer could also provide some place to jam the thread name and thread group (requires the current thread detach and reattach, but that's not a big deal to do as a one-off.

Isn't that the same ugliness you disliked in my suggestion for dealing
with daemon threads? :-)

Neil C Smith

unread,
Aug 11, 2011, 10:08:07 AM8/11/11
to jna-...@googlegroups.com

Well, I'd count on the OSX JVM behaving differently! :-)

Is this breaking the semantics of Thread states? Pretty sure that
threads that have been marked as terminated are not meant to be able
to run again, which surely should apply whether they're native or not.
And if they're not marked as terminated and open to GC, is the OSX
JVM already monitoring for external thread termination, or is it just
a (small) memory leak???

Timothy Wall

unread,
Aug 11, 2011, 10:10:20 AM8/11/11
to jna-...@googlegroups.com
callback-branches branch is now available.

git checkout callback-branches to switch your local repo to it


Timothy Wall

unread,
Aug 11, 2011, 10:14:41 AM8/11/11
to jna-...@googlegroups.com
BTW, an overview of the branch diffs:

Native.setCallbackFlags (->CallbackReference.setCallbackFlags):
Pure java, jams flags into the callback's native data

callback.c, dispatch.h: add flags to the per-callback data struct to indicate desired behavior

testlib.c: simple threaded callback test, not complete

(feel free to add the windows thread implementation, not gotten to that just yet)

also feel free to add your implementation, we can compare side by side.

Timothy Wall

unread,
Aug 11, 2011, 10:18:05 AM8/11/11
to jna-...@googlegroups.com
I neglected to mention that all callbacks are called from the same native thread. Another detail is that the callbacks must be called in rapid succession (usleep(1000) vs usleep(1000000)) to get multiples, almost as if the VM doesn't have time to decide whether it should re-use the same thread.

Timothy Wall

unread,
Aug 11, 2011, 3:49:45 PM8/11/11
to jna-...@googlegroups.com
Check out the latest callback-threads. Added a CallbackThreadInitializer you can associate with one or more callbacks.

You can also call Native.setCallbackOptions() in your callback if you prefer. Try them both out, see what feels better.

Test in CallbacksTest is still just a stub test, but shows you how to use the CallbackThreadInitializer.

>
>> The initializer could also provide some place to jam the thread name and thread group (requires the current thread detach and reattach, but that's not a big deal to do as a one-off.
>
> Isn't that the same ugliness you disliked in my suggestion for dealing
> with daemon threads? :-)

The ugliness is not in un-mapping and re-mapping the thread so match as doing so after you're already in the context where you want the final mapping. If you set flags in the callback itself, you're not truly in that context until the next time through the callback. with the thread initializer, everything's set up the first time you enter the callback.


Neil C Smith

unread,
Aug 11, 2011, 5:09:36 PM8/11/11
to jna-...@googlegroups.com


On Aug 11, 2011 8:49 PM, "Timothy Wall" <twal...@java.net> wrote:
>
> Check out the latest callback-threads.  Added a CallbackThreadInitializer you can associate with one or more callbacks.
>
> You can also call Native.setCallbackOptions() in your callback if you prefer.  Try them both out, see what feels better.
>
> Test in CallbacksTest is still just a stub test, but shows you how to use the CallbackThreadInitializer.
>

Great! I won't be able to test this out until early next week now, but will check it out then and make an experimental fork of JNAJack to try using the API.

> >
> >> The initializer could also provide some place to jam the thread name and thread group (requires the current thread detach and reattach, but that's not a big deal to do as a one-off.
> >
> > Isn't that the same ugliness you disliked in my suggestion for dealing
> > with daemon threads? :-)
>
> The ugliness is not in un-mapping and re-mapping the thread so match as doing so after you're already in the context where you want the final mapping.  If you set flags in the callback itself, you're not truly in that context until the next time through the callback.  with the thread initializer, everything's set up the first time you enter the callback.
>
>

I understand where you're coming from with this now. My perspective had always been about controlling the thread state *between* callbacks, but I guess there are good reasons for setting some state before the first callback.

Neil C Smith

unread,
Aug 15, 2011, 2:22:04 PM8/15/11
to jna-...@googlegroups.com
I'm going to check out your code with JNAJack tomorrow. However,
having been thinking about this over the weekend I wondered about
coding something to test thread-local flags as opposed to
callback-local - see if I could actually implement what I was
suggesting earlier for a start, and I think it might be useful for
implementing manual-detach in a thread-safe way. So, having an hour
free and feeling like a challenge, I signed up on GitHub and made a
fork ...

If you're interested, it's up here - https://github.com/nsigma/jna
Bear in mind I've never really used JNI or C (or git for that matter),
so I've probably made some beginners mistake somewhere! It does seem
to work though, and existing code that doesn't use the new methods
seems to perform normally. It's about 20 lines of code altogether and
just deals with manual attach / detach (the commit is actually much
bigger because NetBeans adamantly wanted to rewrite your build file
and I couldn't be bothered fighting with it!)

Downside is that it uses the GCC only __thread attribute at the
moment, though it should be cross-platform. Not sure what your build
requirements are, particularly for Windows? There is an alternative
Microsoft compiler attribute, though it's Vista or above.

I'll let you know how I get on with using your proposed callbacks API
in "real-world" usage tomorrow.

Best wishes,

Neil

Neil C Smith

unread,
Aug 17, 2011, 9:06:38 AM8/17/11
to jna-...@googlegroups.com
Hi,

Found some time to play with the callback-threads branch and JNAJack.

CallbackThreadInitializer seems a nice, simple and useful API to work
with. I assume it only adds any overhead the first time it is called?
Daemon and noDetach seem to work as advertised, but neither the
thread name or thread group settings seemed to take affect for me - is
there a particular time they need to be set?

setCallbackOptions() seems less useful in practice at the moment,
though that's probably because there's currently nothing dynamic that
can be set. Should it be possible to have a callback marked as
noDetach switch between daemon and non-daemon? This doesn't work at
the moment, though probably shouldn't anyway?

Force detach is definitely needed. Restarting the Jack server when
the callback is marked noDetach currently leads to lots of dangling
old threads. Without being able to force detach, it also wouldn't be
possible to write a utility to use thread destructors to automatically
detach dying threads.

My personal ideal would be to keep your CallbackThreadInitializer, but
replace setCallbackOptions with my suggested thread-local noDetach /
forceDetach pair for dynamic usage, should it be possible to get this
to work on all platforms. I'm still wary that forceDetach as a
callback option would not be thread-safe in the admittedly small
number of cases where a callback is called in multiple threads.

One interesting side-effect of the thread-local approach is that you
can set these flags without a callback reference, which meant I was
able to test these options without recompiling JNAJack, unlike with
the callback options. Whether that's something that should be
encouraged (probably not!), it does mean that the user of a JNA based
library would be able to control these options outside of the library
itself.

Best wishes,

Neil

Timothy Wall

unread,
Aug 17, 2011, 10:09:27 AM8/17/11
to jna-...@googlegroups.com

On Aug 17, 2011, at 9:06 AM, Neil C Smith wrote:

> Hi,
>
> Found some time to play with the callback-threads branch and JNAJack.
>
> CallbackThreadInitializer seems a nice, simple and useful API to work
> with. I assume it only adds any overhead the first time it is called?
> Daemon and noDetach seem to work as advertised, but neither the
> thread name or thread group settings seemed to take affect for me - is
> there a particular time they need to be set?

no tests yet == probably doesn't work :) there are some issues with passing references around when switching threads; I've got a functioning test but the code path is a bit convoluted and just trying to iron it out a little.

Only has overhead when the thread is first attached *and* the callback about to be invoked has an associated initializer, otherwise it's just a bit test and then only if the thread is not already attached.

>
> setCallbackOptions() seems less useful in practice at the moment,
> though that's probably because there's currently nothing dynamic that
> can be set. Should it be possible to have a callback marked as
> noDetach switch between daemon and non-daemon? This doesn't work at
> the moment, though probably shouldn't anyway?

The CallbackThreadInitializer sort of supersedes the callback options; the options are really only needed internally to keep the communications overhead low.


>
> Force detach is definitely needed. Restarting the Jack server when
> the callback is marked noDetach currently leads to lots of dangling
> old threads. Without being able to force detach, it also wouldn't be
> possible to write a utility to use thread destructors to automatically
> detach dying threads.

I think ideally you'd just want to set a detach flag for a given thread, right? at the point you don't want it attached any longer, call CallbackThread.forceDetach(Thread) or some such, and the internal JNA stuff handles the housekeeping. If your callbacks run again, the thread gets detached, otherwise it doesn't (not much you can do in that case...).

>
> My personal ideal would be to keep your CallbackThreadInitializer, but
> replace setCallbackOptions with my suggested thread-local noDetach /
> forceDetach pair for dynamic usage, should it be possible to get this
> to work on all platforms. I'm still wary that forceDetach as a
> callback option would not be thread-safe in the admittedly small
> number of cases where a callback is called in multiple threads.

Have to think about this one a bit. You definitely want the detach tied to the thread, not the callback. might be a way to put some thread-local stuff in the thin java wrapper that ultimately calls the callback (though that might have issues with direct mode callbacks).

>
> One interesting side-effect of the thread-local approach is that you
> can set these flags without a callback reference, which meant I was
> able to test these options without recompiling JNAJack, unlike with
> the callback options. Whether that's something that should be
> encouraged (probably not!), it does mean that the user of a JNA based
> library would be able to control these options outside of the library
> itself.

I don't think it would even have to be thread-local; you could probably drop something onto the local callback invocation stack that gets tweaked by the forcedetach call. That would require that the force detach *only* be called from within the callback context, but it *could* be handled by JNA; a global "forceThreadDetach(Thread)" could queue a request that gets processed within the callback context.

Timothy Wall

unread,
Aug 17, 2011, 10:21:10 AM8/17/11
to jna-...@googlegroups.com

On Aug 17, 2011, at 9:06 AM, Neil C Smith wrote:

> setCallbackOptions() seems less useful in practice at the moment,
> though that's probably because there's currently nothing dynamic that
> can be set. Should it be possible to have a callback marked as
> noDetach switch between daemon and non-daemon? This doesn't work at
> the moment, though probably shouldn't anyway?

Note that you can only choose between daemon/non-daemon when the thread is first attached, so if you have "no detach" then you wouldn't be able to switch anyway until after you detach.

So I think what's missing is your forceDetach -- what would be a straightforward way of incorporating that into CallbackThreadInitializer (or not, if it makes no sense)?

Maybe add these to the CallbackThreadInitializer() =>

/** Called when a new callback thread is attached, probably called before the callback is called. */
void threadAttached(Thread t);
/** Force the given thread to be detached at the next available opportunity. */
void detach(Thread t);
/** Force all threads initialized with this initializer to be detached at the next available opportunity. */
void detachAll();

Trying to come up with the simplest, most coherent API for doing this:
1) properly set up callback threads' information (name, group, daemon)
2) optionally avoid detaching once attached
3) force detach (when?)

I know it's "simpler" from an API point of view in your situation to call either "don't detach" or "detach" from within the callback, but that doesn't have function #1, and doesn't feel like the right level of generality.

Neil C Smith

unread,
Aug 17, 2011, 10:53:22 AM8/17/11
to jna-...@googlegroups.com
On 17 August 2011 15:09, Timothy Wall <twal...@java.net> wrote:
> Only has overhead when the thread is first attached *and* the callback about to be invoked has an associated initializer, otherwise it's just a bit test and then only if the thread is not already attached.
>

That's how I thought - great!


>
> I think ideally you'd just want to set a detach flag for a given thread, right?  at the point you don't want it attached any longer, call CallbackThread.forceDetach(Thread) or some such, and the internal JNA stuff handles the housekeeping.  If your callbacks run again, the thread gets detached, otherwise it doesn't (not much you can do in that case...).
>

Think you're right here, it's only the force detach stuff that's
needed as a manual option - it would be possible to handle everything
else within the CallbackThreadInitializer, which would be called again
in case of detach.

> Have to think about this one a bit.  You definitely want the detach tied to the thread, not the callback.  might be a way to put some thread-local stuff in the thin java wrapper that ultimately calls the callback (though that might have issues with direct mode callbacks).
>

I'm a little wary of the overhead of a thread-local call in Java
considering it's going to have to happen every callback, isn't it?
The native versions __thread & declspec should be a lot faster - could
the Java version be a fallback to cover all bases? I'm just a bit
wary of fixing one bottleneck and adding another! :-)

>
> I don't think it would even have to be thread-local; you could probably drop something onto the local callback invocation stack that gets tweaked by the forcedetach call.  That would require that the force detach *only* be called from within the callback context, but it *could* be handled by JNA; a global "forceThreadDetach(Thread)" could queue a request that gets processed within the callback context.

Not quite the same unless you can also access the
CallbackThreadInitializer to force it to remain attached in the first
place. I'm not sure it's a good idea though, even if it does make it
possible to fix (or break!) 3rd party code.

Neil C Smith

unread,
Aug 17, 2011, 11:04:19 AM8/17/11
to jna-...@googlegroups.com

I'd definitely like to see CallbackThreadInitializer kept and like the
fact that you've added in the abilities of function#1 (when it all
works!). Having the detach(Thread t) & detachAll() methods in the CTI
looks neat, though would you have to make sure you passed the CTI into
all callbacks in which you might want to detach the thread?

If the bitcheck for an attached CTI was done on every callback, it
could also control whether any check for forced detach was done at
all. Then, in the absence of a CTI on the callback, the thread-local
stuff would never be checked, and existing code would have no extra
overhead?

Maybe rename this class CallbackThreadController or
CallbackThreadOptions? It's straying away from just initialization!

Timothy Wall

unread,
Aug 17, 2011, 11:32:55 AM8/17/11
to jna-...@googlegroups.com

On Aug 17, 2011, at 11:04 AM, Neil C Smith wrote:

> On 17 August 2011 15:21, Timothy Wall <twal...@java.net> wrote:
>>
>> Maybe add these to the CallbackThreadInitializer() =>
>>
>> /** Called when a new callback thread is attached, probably called before the callback is called. */
>> void threadAttached(Thread t);
>> /** Force the given thread to be detached at the next available opportunity. */
>> void detach(Thread t);
>> /** Force all threads initialized with this initializer to be detached at the next available opportunity. */
>> void detachAll();
>>
>> Trying to come up with the simplest, most coherent API for doing this:
>> 1) properly set up callback threads' information (name, group, daemon)
>> 2) optionally avoid detaching once attached
>> 3) force detach (when?)
>>
>> I know it's "simpler" from an API point of view in your situation to call either "don't detach" or "detach" from within the callback, but that doesn't have function #1, and doesn't feel like the right level of generality.
>
> I'd definitely like to see CallbackThreadInitializer kept and like the
> fact that you've added in the abilities of function#1 (when it all
> works!). Having the detach(Thread t) & detachAll() methods in the CTI
> looks neat, though would you have to make sure you passed the CTI into
> all callbacks in which you might want to detach the thread?
>

CTI can have many instances or a single one that manages your callback threads. Its initial association with a callback is *only* to indicate that that's what you want to use to handle new threads spotted with a given callback. After that, the thread and CTI is pretty much independent of the callback (for a given thread, at least until it's detached again).

So you could use the CTI itself to detach, or maybe a static method on CTI to force detach on the current thread. The only reason to have the detach stuff be member functions would be if there were some reason you'd need to override them; can't think of any offhand. Whatever code is calling detach would just as well be responsible for handling any callback cleanup (no reason to push that into the CTI).


> If the bitcheck for an attached CTI was done on every callback, it
> could also control whether any check for forced detach was done at
> all. Then, in the absence of a CTI on the callback, the thread-local
> stuff would never be checked, and existing code would have no extra
> overhead?

Once a thread is initialized, it's thread bookkeeping instead of callback bookkeeping. So if a callback thread gets tagged for detach (from within or outside of a callback), the JNA callback cleanup takes care of it.

>
> Maybe rename this class CallbackThreadController or
> CallbackThreadOptions? It's straying away from just initialization!

Right, maybe CallbackThreadManager...

Neil C Smith

unread,
Aug 17, 2011, 3:25:40 PM8/17/11
to jna-...@googlegroups.com
On 17 August 2011 16:32, Timothy Wall <twal...@java.net> wrote:
>
> CTI can have many instances or a single one that manages your callback threads.  Its initial association with a callback is *only* to indicate that that's what you want to use to handle new threads spotted with a given callback.  After that, the thread and CTI is pretty much independent of the callback (for a given thread, at least until it's detached again).
>
> So you could use the CTI itself to detach, or maybe a static method on CTI to force detach on the current thread.  The only reason to have the detach stuff be member functions would be if there were some reason you'd need to override them; can't think of any offhand.  Whatever code is calling detach would just as well be responsible for handling any callback cleanup (no reason to push that into the CTI).
>

I hadn't realised you'd considered them as static methods, so was
wondering why they were on the CTI. Makes sense now.

I also wonder whether the method should just be detach() not
detach(Thread t), and then only work with the current thread? Being
able to set from another thread seems initially useful, but I wonder
if it's setting up expectations which cannot be fulfilled - might stop
you getting bug reports about threads not detaching! :-) You'd also
need to be in the thread if it was to be a thread-local flag, so
allowing the state to be set from anywhere might incur additional
overhead?

>
>> If the bitcheck for an attached CTI was done on every callback, it
>> could also control whether any check for forced detach was done at
>> all.  Then, in the absence of a CTI on the callback, the thread-local
>> stuff would never be checked, and existing code would have no extra
>> overhead?
>
> Once a thread is initialized, it's thread bookkeeping instead of callback bookkeeping.  So if a callback thread gets tagged for detach (from within or outside of a callback), the JNA callback cleanup takes care of it.
>

This really only made sense when I thought you were suggesting methods
on individual CTI objects, and would probably only have a negligible
performance gain for a lot of added complexity. I'm all for KISS
principles!

Best wishes, Neil

Timothy Wall

unread,
Sep 9, 2011, 10:21:13 AM9/9/11
to jna-...@googlegroups.com
callback-threads branch has been updated.

added tests for thread config/detach variations, use Native.detach(boolean) from within the callback (may be used independently of CallbackThreadInitializer).

Kind of a hack, but I overloaded SetLastError/errno status to indicate the desired thread detach state to avoid having to rewrite equivalent TLS on a bunch of native platforms.

T.

Neil C Smith

unread,
Sep 29, 2011, 1:07:54 PM9/29/11
to jna-...@googlegroups.com
Hope my off-list message to apologize for the tardiness of my response
got through! :-)

On 9 September 2011 15:21, Timothy Wall <twal...@java.net> wrote:
> callback-threads branch has been updated.
>
> added tests for thread config/detach variations, use Native.detach(boolean) from within the callback (may be used independently of CallbackThreadInitializer).
>
> Kind of a hack, but I overloaded SetLastError/errno status to indicate the desired thread detach state to avoid having to rewrite equivalent TLS on a bunch of native platforms.
>
> T.
>

Just had a chance to have a quick look at this. Seems like a "good" hack!

Few questions -

* Is errno thread-local on all the platforms JNA targets? Pretty sure
it is on all the ones I'm interested in, but maybe this needs to fail
silently / throw an exception on some?
* Should setLastError(0) be called after the two switch cases
post-callback to reset the value? Just wondered if it might cause
issues if native libs check this value.
* I assume that the values of THREAD_ATTACH / THREAD_DETACH don't
conflict with any of the possible significant values for error number
anywhere?
* Should there be a note that a call to Native.detach() should be the
last thing you do in a callback? Or at least, after you've re-called
into any native code? Just thinking that native code might either
mess up the error number, or it might cause issues as mentioned above.
* And the $64million question - what's next? Is this going to make
its way into the master branch anytime soon???

Timothy Wall

unread,
Sep 29, 2011, 2:14:26 PM9/29/11
to jna-...@googlegroups.com

On Sep 29, 2011, at 1:07 PM, Neil C Smith wrote:

>
> Few questions -
>
> * Is errno thread-local on all the platforms JNA targets? Pretty sure
> it is on all the ones I'm interested in, but maybe this needs to fail
> silently / throw an exception on some?

errno has to be thread-local in order for the c library to function properly in a multi-threaded environment; since Java is already set up to be using a pthread-aware version of libc, this isn't normally an issue.

> * Should setLastError(0) be called after the two switch cases
> post-callback to reset the value? Just wondered if it might cause
> issues if native libs check this value.

Possibly; you also may be of luck if the callback is supposed to indicate error status via errno/SetLastError.

> * I assume that the values of THREAD_ATTACH / THREAD_DETACH don't
> conflict with any of the possible significant values for error number
> anywhere?

Since the callback is executing Java code, any errno values are moot and will have already been handled by the VM (modulo anything that might happen in the native callback processing code, which has already been vetted).


> * Should there be a note that a call to Native.detach() should be the
> last thing you do in a callback? Or at least, after you've re-called
> into any native code? Just thinking that native code might either
> mess up the error number, or it might cause issues as mentioned above.

That's true, it *should* be the very last thing called, since the VM or other native code might change its value. The tests call it just before return, so should regular clients.

> * And the $64million question - what's next? Is this going to make
> its way into the master branch anytime soon???

Given that everything is working satisfactorily, as soon as I get the bandwidth to re-do the native builds.

Neil C Smith

unread,
Dec 1, 2011, 12:11:18 PM12/1/11
to jna-...@googlegroups.com
Hi,

I noticed 3.4.0 had sneaked out recently! :-) Can I assume from this
line in changes - "Improved callback thread-mapping support; re-use,
rename, and group callback threads." - that all the work mentioned in
this thread is now included?

I've not had a chance to play yet, and won't for a few days - the
online JavaDocs still seem to point to 3.3.0 (despite the 3.4.0 in the
link).

Thanks and best wishes,

Timothy Wall

unread,
Dec 1, 2011, 1:45:27 PM12/1/11
to jna-...@googlegroups.com
yes, the callback thread stuff is all in there.

thanks for the tip on the javadoc, must have copied them from the wrong directory. they're fixed now.

Neil C Smith

unread,
Dec 2, 2011, 5:21:43 AM12/2/11
to jna-...@googlegroups.com
Hi,

On 1 December 2011 18:45, Timothy Wall <twal...@java.net> wrote:
> yes, the callback thread stuff is all in there.
>

Great! :-D

> thanks for the tip on the javadoc, must have copied them from the wrong directory.  they're fixed now.
>

The link on the front page
(http://twall.github.com/jna/3.4.0/javadoc/) still seems to point to
3.3.0.

Best wishes,

Timothy Wall

unread,
Dec 2, 2011, 7:34:03 AM12/2/11
to jna-...@googlegroups.com

On Dec 2, 2011, at 5:21 AM, Neil C Smith wrote:

>
> The link on the front page
> (http://twall.github.com/jna/3.4.0/javadoc/) still seems to point to
> 3.3.0.

flush your browser cache.

Neil C Smith

unread,
Dec 2, 2011, 7:44:35 AM12/2/11
to jna-...@googlegroups.com

Sorry for the noise! First thing I did was shift-refresh, which
didn't work. Clearing the cache completely worked though. Never had
that problem with shift-refresh before (and I do a lot of web dev!).
Wonder if it's to do with frames?

Thanks anyway,

Neil C Smith

unread,
Sep 20, 2012, 10:49:17 AM9/20/12
to jna-...@googlegroups.com
Hi,

Hope you don't mind me reopening an old thread, as mentioned in the
recent VLCJ thread. I've seen a few messages (on here and elsewhere)
with people having some issues with thread management and the
CallbackThreadInitializers. I have one issue in JNAJack where a
thread can get shutdown without me getting a callback (user shuts down
JACK server) so that there's no place to detach the thread from the
VM.

Earlier in this thread we'd talked about the possibility of using
thread-local destructors to manage automatic thread detachment, as is
advised in the Android JNI docs. I perfectly understand your decision
to use the error codes rather than TLS for the CTI feature, for
portability reasons. However, I wondered if it was possible to
revisit the idea of a utility for automatic thread management built on
top of this.

I'm presuming it would be fairly easy to map the pthreads TLS methods
and the destructor callback from JNA without any additional code in
jnidispatch? One issue we discussed was doing this on Windows,
because the TLS implementation doesn't allow for a destructor
callback. However, I recently came across the docs for Fiber Local
Storage - FlsAlloc does allow for a callback on thread exit [1]. The
docs seem to suggest that this is usable even without using
ConvertThreadToFiber. It's Vista+ but might offer a usable way to do
this - maybe some method to query whether automatic thread management
is supported prior to setting up CTI's in some cases?

Thoughts? Usable or dead in the water? :-)

Best wishes,

Neil

[1] http://msdn.microsoft.com/en-us/library/windows/desktop/ms682661%28v=vs.85%29.aspx


On 1 December 2011 18:45, Timothy Wall <twal...@java.net> wrote:
> yes, the callback thread stuff is all in there.
>
> thanks for the tip on the javadoc, must have copied them from the wrong directory. they're fixed now.
>


--
Neil C Smith
Artist : Technologist : Adviser
http://neilcsmith.net

Praxis LIVE - Open-source, graphical environment for rapid development
of intermedia performance tools, projections and interactive spaces -
http://code.google.com/p/praxis

OpenEye - specialist web solutions for the cultural, education,
charitable and local government sectors - http://openeye.info

Timothy Wall

unread,
Sep 20, 2012, 12:42:08 PM9/20/12
to jna-...@googlegroups.com
I thought you could get a thread exit callback by using WaitForSingleObject.

Haven't pursued it, but if you get a callback on the dying thread, that's all that
would be needed to clean up the thread mapping (would require native code, though).

I've been experimenting with pthreads on OSX, I can do the unmapping automatically by
digging in the guts of pthread_cleanup_push(), but every platform has a different
pthreads implementation.

Neil C Smith

unread,
Sep 20, 2012, 12:58:52 PM9/20/12
to jna-...@googlegroups.com
I looked at pthread_cleanup_push() during our earlier discussion, but
don't think it can achieve what we want (very easily). Pretty sure we
can just map pthread_key_create() [1] and pass in a callback to that,
then call pthread_setspecific() (key must be anything non-null for
callback to be called) in each attached thread. The callback just
needs to call Native.detach(true).

This was mentioned at some point earlier in this thread - it's along
the advice given in the JNI Tips for Android [2] - look for the
Threads section.

The problem was there didn't seem to be an equivalent with Windows,
but FlsAlloc would seem to possibly offer that.

I'm not 100%, but this should be doable without any native code
changes - I know how much you love those! :-)

Only thing might involve a hacked CallbackThreadInitializer - need to
hang the pthread_setspecific() and equivalent off of a method that's
only called at setup time - getName()?

Best wishes,

Neil

[1] http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_key_create.html
[2] http://developer.android.com/guide/practices/jni.html

Timothy Wall

unread,
Sep 20, 2012, 1:13:08 PM9/20/12
to jna-...@googlegroups.com
I just tried a simple test using the thread-local key destructor, that seems to do the trick; it's only a couple of lines of code, and certainly takes care of all pthreads platforms.

Just need a fix for windows and I can roll something into master.

Neil C Smith

unread,
Sep 20, 2012, 1:32:38 PM9/20/12
to jna-...@googlegroups.com

Wow, that was quick!

Fingers crossed for FlsAlloc. If not, Boost has some code that does this on Windows. Be interesting to know if it does anything that can be replicated.

N

Neil C Smith
Artist : Technologist : Adviser
http://neilcsmith.net

Timothy Wall

unread,
Sep 20, 2012, 2:07:05 PM9/20/12
to jna-...@googlegroups.com
actually, regular old TlsAlloc + DllMain seems to work, but is causing a different test to fail (callback calling Native.detach(true/false) before returning).

Timothy Wall

unread,
Sep 20, 2012, 3:03:35 PM9/20/12
to jna-...@googlegroups.com
try out the callback-thread-cleanup branch (requires native build).

I had to tweak some native bits for w32, but no interface changes.

Neil C Smith

unread,
Sep 20, 2012, 3:37:46 PM9/20/12
to jna-...@googlegroups.com
On 20 September 2012 20:03, Timothy Wall <twal...@java.net> wrote:
> try out the callback-thread-cleanup branch (requires native build).
>

OK. Do you have a Windows build of jnidispatch? I don't have a
(native) build env on Windows, try to use it as little as possible!
:-)

> I had to tweak some native bits for w32, but no interface changes.
>

Well, if TlsAlloc is working fine with that then great (and
potentially makes it XP compatible?). My thoughts with FlsAlloc was
that it might be possible to do this without changing any native code.

Best wishes,

Neil

Timothy Wall

unread,
Sep 20, 2012, 3:57:02 PM9/20/12
to jna-...@googlegroups.com


Built and tested on XP.
jnidispatch.dll
Reply all
Reply to author
Forward
0 new messages