Showing posts with label jna. Show all posts
Showing posts with label jna. Show all posts

Saturday, September 22, 2012

Thread termination/exit handlers

I'd been hunting for a while for a good solution to automatically call cleanup operations on exit from threads I didn't own.  Windows (XP onward) has a pretty straightforward solution if you're working with a DLL, but for pthreads on most other platforms, the solution is not as obvious.

Some folks have been using JNA to allow Java code to be invoked as callbacks from various streaming (video, sound) libraries.  If these callbacks come from threads instantiated from native code, the JVM has to (at least temporarily) map the thread into Java space for the duration of the callback.  If the callbacks are frequent, and always come in on the same native thread, we don't want to incur the mapping overhead on every invocation.  The solution, then is to avoid detaching the thread when the callback finishes.

Now we have a new problem.  When the native thread actually terminates, the JVM has no idea that the thread went away because it's only really got a placeholder Thread object, and hasn't hooked up all the plumbing it normally does to detect that the thread has gone away and clean up/GC the mapped Thread object.  Thus the need for a thread exit handler.  In some cases, you may not care about the minimal object overhead, for instance if you've just got a few native threads.  However, with a lot of threads coming and going (we can't force folks to thread-pool).

Windows


On Windows, if you have a DllMain function defined, you'll get notices when threads and processes attach/detach your DLL's code.  This works out nicely, we can make the VM detach the current thread when we get that message:

// Store thread-local information required to detach the thread
// (in my case, only a JVM reference was required)
// TlsSetValue is only set when we recognize that we need the 
// extra cleanup
static DWORD dwTlsIndex;
BOOL WINAPI DllMain(HINSTANCE hDLL, 
                    DWORD fdwReason, 
                    LPVOID lpvReserved) {
  switch (fdwReason) {
  case DLL_PROCESS_ATTACH:
    dwTlsIndex = TlsAlloc();
    if (dwTlsIndex == TLS_OUT_OF_INDEXES) {
      return FALSE;
    }
    break;
  case DLL_PROCESS_DETACH:
    TlsFree(dwTlsIndex);
    break;
  case DLL_THREAD_ATTACH:
    break;
  case DLL_THREAD_DETACH: {
    extern void detach_thread();
    detach_thread(TlsGetValue(dwTlsIndex));
    break;
  }
  default:
    break;
  }
  return TRUE;
}
 Easy enough.  Note that TlsSetValue is called elsewhere only when the callback decides it doesn't want to detach immediately (rather than every time a native thread attaches).  Callbacks normally detach on exit if they weren't attached to begin with.

POSIX Threads (pthreads)

The pthreads library is a different beast.  Searches for "thread termination handler" don't turn up much, except for the stack-based pthread_cancel_push/pop, which seems to do the right thing, but have to arrive in pairs.  It's actually in the pthreads implementation of thread-local storage that we find a way to attach a termination handler to a given thread.

When you define a given thread-local variable in pthreads (a "key" in pthreads lingo), you can provide a destructor function to be used to clean up the storage...on thread exit.  It was a little hard to find since it's not a thread termination handler per se, but rather a mechanism to clean up thread local storage.  I'd overlooked it several times because I wasn't looking for thread local storage solutions.


// Basic plumbing to create a unique key identifying
// specific thread-local storage
static pthread_key_t key;
static void make_key() {
  extern void detach_thread();
  pthread_key_create(&key, detach_thread);
}

    ...
    // This code gets called whenever we identify that
    // a thread needs detach-on-exit behavior
    static pthread_once_t key_once = PTHREAD_ONCE_INIT;
    pthread_once(&key_once, make_key);
    if (!jvm || pthread_getspecific(key) == NULL) {
      pthread_setspecific(key, jvm);
    }
    ...

Now detach_thread will be called (with the value of the thread-local storage as its single argument) when the thread exits.

And voilĂ , you have a POSIX thread termination handler.

Thursday, September 11, 2008

JNA: increasing performance with large Structures

If you're using very large structures and using them often, here's a tip that can boost performance by several orders of magnitude. Note that you should follow this tip *only* if you really need the performance boost; otherwise you may wind up obfuscating your code.

By default, when JNA makes a native call it will copy the full contents of a Java Structure to native memory prior to the call and read it all back after the call. If your Structure is very large, this can result in significant overhead reflecting all the fields of the Structure. The reflection dwarfs the actual native communication time.

If you're only reading or writing a single field, it's much faster (although somewhat less elegant) to use the readField(String) and writeField(String) methods to access the data, while disabling the normal read and write. Depending on the size of your structure, you may see two orders of magnitude or more improvement in the native function call time.

Here's an example of performing the same operation two different ways:


class Big extends Structure {
public int toNative;
public int fromNative;
// plus lots more fields
// the more, the bigger the difference in performance

}

class FastBig extends Big {
public void read() { }
public void write() { }
}

Big big = new Big();
big.toNative = 42;
lib.callMyNativeFunction(big);
System.out.println("Got " + big.fromNative);

Big fast = new FastBig();
fast.toNative = 42;
fast.writeField("toNative");
lib.callMyNativeFunction(fast);
System.out.println("Got " + fast.readField("fromNative"));


If you wrap a loop and time these, you'll see what kind of difference it makes. On a test structure with 25 "int" fields, the fast version reduces time by a factor of 10.

Trivia: some other "struct" implementations (e.g. Javolution) use objects for all fields and require an explicit "write" or "set" on each. This reduces data transfer and/or reflection overhead, at the expense of simplicity of assignment and initialization.

JNA:
s.field = 1;
call(s.field);

Javolution:
s.field.set(1);
call(s.field.get());

Thursday, September 04, 2008

JNA win64 port

JNA now supports 64-bit windows. The the build is a bit nonstandard, but it's automatic and reproducible. I was hoping to use mingw-64, but that project is not yet sufficient for JNA's purposes. Fortunately, the MS has a free 64-bit cross compiler which does work.

Thanks to the fine folks at Aquafold (actually mostly Niels G. the CTO) for making it possible.

Thanks also to T. Heller of python's ctypes for the initial glue bits.

Wednesday, September 12, 2007

Run your Java program as an NT service

Thomas Boerkel has contributed some mappings and code to the JNA project to facilitate access to Windows' user accounts, registry, and NT services. Included is an abstract class which is capable of installing, uninstalling, and running itself as an NT service. What sets this little gem apart from most available wrappers is that you don't need a Windows executable stub; the complete Windows service API is available to your Java program, including all system events and callbacks.

You can browse the source here. A NetBeans project is included.

I was working on an abstract service class as well but Thomas beat me to completion. Great work, Thomas!

Update: Make sure your classpath and classes are accessible by the local system account, or the service won't be able to start. To see if this is the issue, you can temporarily change the service to start using your user identity; if it works, then the problem is that the local system account doesn't have access.

Wednesday, June 27, 2007

Improved Window Shaping

Thanks to contributions from Olivier Chafik and Chris Deckers, the overhead for setting a window shape mask has been reduced by about two orders of magnitude. In this case, the balloon tip windows no longer have such a noticeable delay before showing.

Linux users should also have fewer issues with this version; some of the library setup previously required is now taken care of automatically by the JNA library.



Saturday, May 12, 2007

Easier Alpha Masks

The per-pixel alpha masking in this post has been codified into a simple API.

WindowUtils.setWindowTransparent(Window w, boolean transparent);

This effectively gives the window a transparent background. The alpha levels of the window's contents are preserved.

The demo is similar to the previous one but adds a few standard components to the mix.



UPDATE If you have a linux system and this for some reason doesn't work, please post a comment to that effect, or post a message to users@jna.dev.java.net so we can ensure this works reliably across all linux systems (64-bit is in the works).

Wednesday, April 18, 2007

Alpha-mask Transparency for a Window

Finally got per-pixel alpha mask working on w32. The included image isn't the greatest for showing an antialiased edge (it does have one), but if you have something with a drop shadow lying about, just drop it on the demo window and that'll be used instead.

Update This demo works on Windows, OSX and Linux (Linux requires JRE1.5+).



Update Here's another image to drop on the demo window, which better demonstrates the alpha blending, in case you don't have any handy


I've got some working X11 code, too, but I need to figure out a decent API to make it happen. OSX lets you just set the window background pixel transparent and then everything you paint in the window is automatically composited with whatever alpha mask you paint with. That could probably work with Swing as well, but you have to magically drop anything with a default background. OSX does this by checking for a magic UIResource color; anything painted with that color is fully transparent.

Update Source is available on BRANCH_V2 from JNA.

I realize I may be an utter dolt, but I find it really hard to follow Microsoft APIs. I've worked with Qt, X11/Xt, and Mac, each of which has its peculiarities of architecture, but those have a consistency (might I say design) that spans more than two or three functions.

Friday, April 13, 2007

Java Transparent Windows (X11 update)





Update: If your X11 setup supports it (XFCE, metacity + xcompmgr, compiz, etc), the JNA shaped window demo now has window transparency.

Thanks to Romain Guy for some initial testing and VMWare for making experimental linux installations easier.

Update: BTW, the linux setup I used was ubuntu (after installing xubuntu packages to get xfce; should have started with xubuntu). Note that the transparency is similar to that on OS X and w32, i.e. a single alpha level for the entire window. Next up is to apply a per-pixel alpha mask, if I can scrounge up some samples of how to do it on each platform.

I added some features to JNA to facilitate working with the X11 visual lookups (it returns an array of structures), so a few more files got changed than just the examples jar. If you want the latest and greatest, you'll need to check out from CVS and do 'ant examples-jar'.

Monday, April 02, 2007

Speech Bubble Update (with Drop Shadow)


I added a drop shadow to the speech bubble. You don't need it on OSX (OSX provides one automatically), and I don't have compiz or similar compositing window manager installed on linux at the moment (although if anyone is willing to submit/test the corresponding code, I'm happy to include it).

Nothing fancy, just black with 50% alpha. The shadow mask is just the original mask, sheared, scaled, and offset. The drop shadow would probably look nicer with a blurred edge, but that likely requires a variable alpha setting for the window (although you might be able to fake it by varying the edge color). Applying per-pixel alpha masks prior to Windows Vista seems to be non-trivial (this example uses a single alpha value for the entire window).

The JNA function definitions are trivial:


int GetWindowLongA(Pointer hWnd, int nIndex);
int SetWindowLongA(Pointer hWnd, int nIndex, int dwNewLong);
boolean SetLayeredWindowAttributes(Pointer hwnd, int crKey,
byte bAlpha, int dwFlags);


As is the actual usage:


Pointer hWnd = getHWnd(w);
User32 user = User32.INSTANCE;
int flags = user.GetWindowLongA(hWnd, User32.GWL_EXSTYLE) | User32.WS_EX_LAYERED;
user.SetWindowLongA(hWnd, User32.GWL_EXSTYLE, flags);
user.SetLayeredWindowAttributes(hWnd, 0, (byte)(255*alpha), User32.LWA_ALPHA);


The only real trick is that DirectDraw must be disabled in order to get the transparency effect and avoid leaving behind painting artifacts.

java -Dsun.java2d.noddraw=true ...

NOTE: thanks to l2fprod for the hint and the original round, transparent clock!

Update: Demo is now available from the JNA homepage.

Wednesday, March 28, 2007

Give your application a speech bubble

As a result of an argument about the best way to present meta-information about complex application objects presented to the user, I had to come up with some concrete alternatives.

The problem is that for a given item in the application (in this case an SVN-based revision control client that aggregates and presents large amounts of meta-information about the repository), there may exist information that just doesn't fit in the display. You want to provide the user with a route to the desired information with as few inputs as possible.

Tooltips is one alternative, but aren't always appropriate. While you can set (globally) the delay before appearance and the time before dismissal, dismissing them is implicit. In my application, I need the meta information to be displayed or hidden explicitly, so that rules out tooltips (at least without substantial modification of the tooltip manager).

A dedicated "inspector" window is another alternative, but kind of heavyweight. We definitely don't want a component that can be activated, since that introduces focus issues. I also didn't want to make it appear to the user that there was a generic "container" that kept resizing and moving, as if it were a tool palette that couldn't decide on its purpose. At a minimum the window has to be undecorated and pretty much behave like a tooltip.

What I really wanted was something in between the two. A simple Popup with a unique appearance which could be shown or hidden at will. Apple introduced something like this as Balloon Help years ago, although I think the main problem was that they didn't get the trigger quite right. One reason a lot of expert users don't like tooltips (or balloon help) is that they show up when you don't expect it and you have to wave the mouse to make them go away (usually causing another one to be triggered).

Google maps does a nice job with their balloon tips. The trigger is obvious, and the tip itself provides a close button (and now I notice a maximize button as well).

So I started out with Popups via PopupFactory and wound up with another demonstration of non-rectangular clipping, brought to you by the JNA project. The API is pretty simple:


Component myComponent;
Component myBubble;
Point where; // location relative to myComponent
final Popup popup = BalloonManager.getBalloon(myComponent, myBubble, where.x, where.y);
popup.show();
// Hide the popup on mouse clicks
myBubble.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
popup.hide();
}
});


The balloon is a simple rounded rectangle with a triangle stuck to the bottom, with the corresponding Area used as the window mask.

I originally tried using PopupFactory directly, but it doesn't provide enough control over the intermediate components (the ancestors of the content that you don't really see; there's a pesky medium-weight popup that uses java.awt.Panel, which can't be easily masked). This implementation uses a window for any popup, regardless of whether its fully contained within the parent component.

Drop shadows would be nice (maybe someone wants to contribute some compositing code?).




Tuesday, February 27, 2007

Non-rectangular Windows Update




Updated to include support for OSX and linux.

While OSX doesn't actually use any native code to do the window mask, JNA support is there if it needed to. Source (and per-platform binaries) is available at http://jna.dev.java.net.

Update
Transparent version of the demo is available here.

Friday, February 23, 2007

Non-rectangular Windows

I've been meaning to play around with shaped windows for a while, but didn't relish the thought of walking through the tedium of JNI configurations and builds. Doing it on one platform is bad enough, but on several? No thanks.

So I thought I'd write a little scriptable shared library access stub once and be done with JNI entirely. Well, turns out it's already been done. Several times.

JNative
NLink
JNA

JNative has some interesting features not found in the others, but actually using it is only slightly better than JNI. NLink is currently w32-only, and has a bit of a COM bent. JNA fit most closely with my objectives, already had implementations for w32 and solaris, and was already platform-agnostic. So I took a couple days to hack in some more features (mostly to get an understanding of the codebase), and here is what I got. The following code is what it takes to make a frame take an arbitrary shape.

User32 user32 = User32.INSTANCE;
GDI32 gdi32 = GDI32.INSTANCE;
JFrame frame = new JFrame(getName());
Pointer p = gdi32.CreateRoundRectRgn(0, -150, 300, 300, 300, 300);
int hWnd = user32.FindWindowA(null, getName());
user32.SetWindowRgn(hWnd, p, true);

Looking up the appropriate w32 calls probably took the most time. How are the w32 libraries defined? How is this for trivial:

public interface User32 extends StdCallLibarary {
User32 INSTANCE = (User32)Native.loadLibary("user32", User32.class);
int FindWindowA(String winClass, String title);
void setWindowRgn(int hWnd, Pointer p, boolean redraw);
}
public interface GDI32 extends StdCallLibrary {
GDI32 INSTANCE = (GDI32)Native.loadLibrary("gdi32", GDI32.class);
Pointer CreateRoundRectRgn(int left, int top, int right, int bottom, int w, int h);
}

Now, somebody's probably going to point me to how SWT has had this functionality for years (does it?), but this is nicely abstracted and based on a very small number of classes. I'll be updating the code at jna.dev.java.net (or maybe opening a new location if I can't get the existing project moved to subversion), but for now, check out the demo by clicking on everyone's favorite orange launch button.




Permissions required, because this runs some custom native code.

Oh, BTW, this is windows-only for the moment. I'll do X11 next and anyone's free to send me some code snippets for setting window masks on other platforms. I could also use some help porting to PPC and other platforms (a very small amount of native ASM to push arguments to the stack, not too hard).