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)
 {


Reply via email to