Author: mturk Date: Tue Jun 28 14:26:29 2011 New Revision: 1140637 URL: http://svn.apache.org/viewvc?rev=1140637&view=rev Log: Make Descriptor reference counted. Invoke close/free only when there are no more references
Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Descriptor.java commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LocalDescriptor.java commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/SocketDescriptor.java commons/sandbox/runtime/trunk/src/main/native/include/acr/descriptor.h commons/sandbox/runtime/trunk/src/main/native/os/unix/inetsock.c commons/sandbox/runtime/trunk/src/main/native/os/unix/usock.c commons/sandbox/runtime/trunk/src/main/native/os/win32/pollset.c commons/sandbox/runtime/trunk/src/main/native/shared/descriptor.c Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Descriptor.java URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Descriptor.java?rev=1140637&r1=1140636&r2=1140637&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Descriptor.java (original) +++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Descriptor.java Tue Jun 28 14:26:29 2011 @@ -37,10 +37,17 @@ import org.apache.commons.runtime.util.U public abstract class Descriptor implements Device, Syncable { + private static native void retain0(long fd); + private static native void release0(long fd); + private static native boolean unique0(long fd); + /** Operating system descriptor. */ - protected long fd; - + protected long fd; + /** + * Closed flag. + */ + protected volatile boolean closed; /** * Creates a new object. */ @@ -118,7 +125,7 @@ public abstract class Descriptor impleme { // true if both int is negative or zero // Descriptor is always assured to be above the stderr (#3) - if (fd == 0L) + if (closed || fd == 0L) return false; else return true; @@ -131,7 +138,7 @@ public abstract class Descriptor impleme */ public final boolean closed() { - if (fd == 0L) + if (closed || fd == 0L) return true; else return false; @@ -147,6 +154,50 @@ public abstract class Descriptor impleme } /** + * Increase retention. + * <p> + * This method increments the operating system descriptor's + * reference counter. + * </p> + * @return operating system descriptor with increased + * retention counter. + */ + public final long retain() + { + if (fd != 0L) + retain0(fd); + return fd; + } + + /** + * True if retention counter equals one. + * @param fd operating system descriptor. + */ + public static boolean unique(final long fd) + throws InvalidDescriptorException + { + if (fd == 0L) + throw new InvalidDescriptorException(); + return unique0(fd); + } + + /** + * Decrease retention by decrementing the reference counter. + * User of this method will usually invalidate the operating + * system descriptor instead using {@code close()} method. + * + * @param fd operating system descriptor. + * @return {@code true} if the object can be released. + */ + public static void release(final long fd) + throws InvalidDescriptorException + { + if (fd == 0L) + throw new InvalidDescriptorException(); + release0(fd); + } + + /** * Compares this {@code Descriptor} to the specified object. * * @param other a {@code Descriptor} @@ -171,6 +222,26 @@ public abstract class Descriptor impleme } /** + * Called by the garbage collector when the object is destroyed. + * The class will free internal resources allocated by the + * Operating system only if there are no additional references + * to this object. + * @see Object#finalize() + * @throws Throwable the {@code Exception} raised by this method. + */ + @Override + protected final void finalize() + throws Throwable + { + try { + close(); + } + finally { + fd = 0L; + } + } + + /** * Returns a string representation of the Descriptor. * The returned string is hexadecimal representation of the underlying * descriptor for the {@code pointer} type descriptors and integer for Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LocalDescriptor.java URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LocalDescriptor.java?rev=1140637&r1=1140636&r2=1140637&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LocalDescriptor.java (original) +++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LocalDescriptor.java Tue Jun 28 14:26:29 2011 @@ -51,6 +51,7 @@ final class LocalDescriptor extends Desc public LocalDescriptor(long fd) { this.fd = fd; + closed = false; } public void create(SocketType type) @@ -63,6 +64,7 @@ final class LocalDescriptor extends Desc throws IOException { this.fd = socket0(type.valueOf(), block); + closed = false; } public boolean isBlocking() @@ -90,6 +92,7 @@ final class LocalDescriptor extends Desc { // Closing an empty socket is not an error if (valid()) { + closed = true; int rc = close0(fd); fd = 0L; if (rc != 0) @@ -116,26 +119,4 @@ final class LocalDescriptor extends Desc throw new ClosedDescriptorException(); } - /** - * Called by the garbage collector when the object is destroyed. - * The class will free internal resources allocated by the Operating system. - * @see Object#finalize() - * @throws Throwable the {@code Exception} raised by this method. - */ - @Override - protected final void finalize() - throws Throwable - { - if (valid()) { - try { - close(); - } catch (Exception e) { - // Ignore exceptions during close - } - finally { - fd = 0L; - } - } - } - } Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/SocketDescriptor.java URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/SocketDescriptor.java?rev=1140637&r1=1140636&r2=1140637&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/SocketDescriptor.java (original) +++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/SocketDescriptor.java Tue Jun 28 14:26:29 2011 @@ -48,12 +48,14 @@ final class SocketDescriptor extends Des public SocketDescriptor(long fd) { this.fd = fd; + closed = false; } public void create(SocketType type) throws IOException { this.fd = socket0(type.valueOf()); + closed = false; } public boolean isBlocking() @@ -81,6 +83,7 @@ final class SocketDescriptor extends Des { // Closing an empty socket is not an error if (valid()) { + closed = true; int rc = close0(fd); fd = 0L; if (rc != 0) @@ -107,27 +110,4 @@ final class SocketDescriptor extends Des throw new ClosedDescriptorException(); } - /** - * Called by the garbage collector when the object is destroyed. - * The class will free internal resources allocated by the Operating system. - * @see Object#finalize() - * @throws Throwable the {@code Exception} raised by this method. - */ - @Override - protected final void finalize() - throws Throwable - { - if (valid()) { - try { - close(); - } catch (Exception e) { - // Ignore exceptions during close - } - finally { - fd = 0L; - } - } - } - - } Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr/descriptor.h URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr/descriptor.h?rev=1140637&r1=1140636&r2=1140637&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/include/acr/descriptor.h (original) +++ commons/sandbox/runtime/trunk/src/main/native/include/acr/descriptor.h Tue Jun 28 14:26:29 2011 @@ -21,8 +21,8 @@ typedef struct acr_fd_t acr_fd_t; struct acr_fd_t { - int type; /**< Descriptor type */ - int size; /**< Allocated descriptor size */ + int type; /**< Descriptor type */ + volatile acr_atomic32_t refs; /**< Reference counter */ union { jlong nh; void *p; Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/inetsock.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/inetsock.c?rev=1140637&r1=1140636&r2=1140637&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/unix/inetsock.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/unix/inetsock.c Tue Jun 28 14:26:29 2011 @@ -21,21 +21,23 @@ #include "acr/unsafe.h" #include "acr/port.h" #include "arch_opts.h" +#include "arch_sync.h" #include <poll.h> #include <sys/un.h> ACR_NET_EXPORT(jint, SocketDescriptor, close0)(JNI_STDARGS, jlong fp) { + int rc = 0; acr_fd_t *fd = J2P(fp, acr_fd_t *); if (fd == 0) return ACR_EBADF; - if (r_close(fd->u.s) == -1) - return ACR_GET_OS_ERROR(); - else { + if (AcrAtomic32Dec(&fd->refs) == 0) { + if (r_close(fd->u.s) == -1) + rc = ACR_GET_OS_ERROR(); AcrFree(fd); - return 0; } + return rc; } ACR_NET_EXPORT(jint, SocketDescriptor, sendz0)(JNI_STDARGS, jlong fp) Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/usock.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/usock.c?rev=1140637&r1=1140636&r2=1140637&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/unix/usock.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/unix/usock.c Tue Jun 28 14:26:29 2011 @@ -24,6 +24,7 @@ #include "acr/unsafe.h" #include "acr/port.h" #include "arch_opts.h" +#include "arch_sync.h" #include <poll.h> #include <sys/un.h> @@ -34,16 +35,17 @@ ACR_NET_EXPORT(jint, LocalDescriptor, close0)(JNI_STDARGS, jlong fp) { + int rc = 0; acr_fd_t *fd = J2P(fp, acr_fd_t *); if (fd == 0) return ACR_EBADF; - if (r_close(fd->u.s) == -1) - return ACR_GET_OS_ERROR(); - else { + if (AcrAtomic32Dec(&fd->refs) == 0) { + if (r_close(fd->u.s) == -1) + rc = ACR_GET_OS_ERROR(); AcrFree(fd); - return 0; } + return rc; } ACR_NET_EXPORT(jint, LocalDescriptor, sendz0)(JNI_STDARGS, jlong fp) @@ -107,7 +109,8 @@ ACR_NET_EXPORT(jlong, LocalDescriptor, s r_close(sd); return 0; } - sp->u.s = sd; + sp->refs = 1; + sp->u.s = sd; return P2J(sp); } @@ -260,6 +263,7 @@ ACR_NET_EXPORT(jlong, LocalServerEndpoin r_close(sd); return 0; } - sp->u.s = sd; + sp->refs = 1; + sp->u.s = sd; return P2J(sp); } Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/pollset.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/pollset.c?rev=1140637&r1=1140636&r2=1140637&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/pollset.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/pollset.c Tue Jun 28 14:26:29 2011 @@ -101,10 +101,8 @@ static int wwait(acr_pollset_t *ps) LeaveCriticalSection(&ps->mutex); ws = WaitForSingleObject(ps->wakeup, INFINITE); EnterCriticalSection(&ps->mutex); - if (AcrAtomic32Dec(&ps->waiters) <= 0) { + if (AcrAtomic32Dec(&ps->waiters) == 0) ResetEvent(ps->wakeup); - AcrAtomic32Set(&ps->waiters, 0); - } if (ws == WAIT_FAILED) return GetLastError(); else Modified: commons/sandbox/runtime/trunk/src/main/native/shared/descriptor.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/shared/descriptor.c?rev=1140637&r1=1140636&r2=1140637&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/shared/descriptor.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/shared/descriptor.c Tue Jun 28 14:26:29 2011 @@ -23,6 +23,7 @@ #include "acr/clazz.h" #include "acr/memory.h" #include "acr/unsafe.h" +#include "arch_sync.h" J_DECLARE_CLAZZ = { INVALID_FIELD_OFFSET, @@ -50,6 +51,24 @@ ACR_IO_EXPORT(void, Descriptor, init0)(J _clazzn.u = 1; } +ACR_IO_EXPORT(void, Descriptor, retain0)(JNI_STDARGS, jlong fp) +{ + acr_fd_t *fd = J2P(fp, acr_fd_t *); + AcrAtomic32Inc(&fd->refs); +} + +ACR_IO_EXPORT(void, Descriptor, release0)(JNI_STDARGS, jlong fp) +{ + acr_fd_t *fd = J2P(fp, acr_fd_t *); + AcrAtomic32Dec(&fd->refs); +} + +ACR_IO_EXPORT(jboolean, Descriptor, unique0)(JNI_STDARGS, jlong fp) +{ + acr_fd_t *fd = J2P(fp, acr_fd_t *); + return AcrAtomic32Equ(&fd->refs, 1); +} + acr_fd_t * AcrGetDescriptorFp(JNI_STDARGS) {