ports: avoid adding port table entries and finalizers if possible
authorAndy Wingo <wingo@pobox.com>
Tue, 14 Feb 2012 13:01:52 +0000 (14:01 +0100)
committerAndy Wingo <wingo@pobox.com>
Tue, 14 Feb 2012 13:10:53 +0000 (14:10 +0100)
* libguile/ports.h (scm_t_port_type_flags, scm_t_ptob_descriptor): Add
  flags to ptob descriptors.

* libguile/ports.c (scm_set_port_flush): Set the SCM_PORT_TYPE_HAS_FLUSH
  flag here.
  (scm_c_make_port_with_encoding): Only add ports to the table if
  SCM_PORT_TYPE_HAS_FLUSH is set.  Only add finalizers to ports if there
  is a free function.
  (scm_close_port): Inline scm_i_remove_port here.  Only remove from the
  weak set if SCM_PORT_TYPE_HAS_FLUSH is set.
  (scm_set_port_revealed_x): Add a comment.

libguile/ports.c
libguile/ports.h

index 5fb3f59..c1da25e 100644 (file)
@@ -250,7 +250,9 @@ scm_set_port_close (scm_t_bits tc, int (*close) (SCM))
 void
 scm_set_port_flush (scm_t_bits tc, void (*flush) (SCM port))
 {
-   scm_c_port_type_ref (SCM_TC2PTOBNUM (tc))->flush = flush;
+  scm_t_ptob_descriptor *ptob = scm_c_port_type_ref (SCM_TC2PTOBNUM (tc));
+  ptob->flush = flush;
+  ptob->flags |= SCM_PORT_TYPE_HAS_FLUSH;
 }
 
 void
@@ -612,11 +614,11 @@ scm_c_make_port_with_encoding (scm_t_bits tag, unsigned long mode_bits,
   entry->ilseq_handler = handler;
   entry->iconv_descriptors = NULL;
 
-  scm_weak_set_add_x (scm_i_port_weak_set, ret);
+  if (SCM_PORT_DESCRIPTOR (ret)->flags & SCM_PORT_TYPE_HAS_FLUSH)
+    scm_weak_set_add_x (scm_i_port_weak_set, ret);
 
-  /* For each new port, register a finalizer so that it port type's free
-     function can be invoked eventually.  */
-  register_finalizer_for_port (ret);
+  if (SCM_PORT_DESCRIPTOR (ret)->free)
+    register_finalizer_for_port (ret);
 
   return ret;
 }
@@ -636,33 +638,6 @@ scm_new_port_table_entry (scm_t_bits tag)
   return scm_c_make_port (tag, 0, 0);
 }
 
-/* Remove a port from the table and destroy it.  */
-
-static void close_iconv_descriptors (scm_t_iconv_descriptors *id);
-
-static void
-scm_i_remove_port (SCM port)
-#define FUNC_NAME "scm_remove_port"
-{
-  scm_t_port *p;
-
-  p = SCM_PTAB_ENTRY (port);
-  scm_port_non_buffer (p);
-  SCM_SETPTAB_ENTRY (port, 0);
-  scm_weak_set_remove_x (scm_i_port_weak_set, port);
-
-  p->putback_buf = NULL;
-  p->putback_buf_size = 0;
-
-  if (p->iconv_descriptors)
-    {
-      close_iconv_descriptors (p->iconv_descriptors);
-      p->iconv_descriptors = NULL;
-    }
-}
-#undef FUNC_NAME
-
-
 \f
 
 /* Predicates.  */
@@ -727,6 +702,8 @@ SCM_DEFINE (scm_eof_object_p, "eof-object?", 1, 0, 0,
 
 /* Closing ports.  */
 
+static void close_iconv_descriptors (scm_t_iconv_descriptors *id);
+
 /* scm_close_port
  * Call the close operation on a port object. 
  * see also scm_close.
@@ -741,6 +718,7 @@ SCM_DEFINE (scm_close_port, "close-port", 1, 0, 0,
            "descriptors.")
 #define FUNC_NAME s_scm_close_port
 {
+  scm_t_port *p;
   int rv;
 
   port = SCM_COERCE_OUTPORT (port);
@@ -752,8 +730,26 @@ SCM_DEFINE (scm_close_port, "close-port", 1, 0, 0,
     rv = SCM_PORT_DESCRIPTOR (port)->close (port);
   else
     rv = 0;
-  scm_i_remove_port (port);
+
+  p = SCM_PTAB_ENTRY (port);
+
+  scm_port_non_buffer (p);
+  SCM_SETPTAB_ENTRY (port, 0);
+
+  if (SCM_PORT_DESCRIPTOR (port)->flags & SCM_PORT_TYPE_HAS_FLUSH)
+    scm_weak_set_remove_x (scm_i_port_weak_set, port);
+
+  p->putback_buf = NULL;
+  p->putback_buf_size = 0;
+
+  if (p->iconv_descriptors)
+    {
+      close_iconv_descriptors (p->iconv_descriptors);
+      p->iconv_descriptors = NULL;
+    }
+
   SCM_CLR_PORT_OPEN_FLAG (port);
+
   return scm_from_bool (rv >= 0);
 }
 #undef FUNC_NAME
@@ -1254,6 +1250,9 @@ SCM_DEFINE (scm_set_port_revealed_x, "set-port-revealed!", 2, 0, 0,
   int r;
   scm_i_pthread_mutex_t *lock;
   
+  /* FIXME: It doesn't make sense to manipulate revealed counts on ports
+     without a free function.  */
+
   port = SCM_COERCE_OUTPORT (port);
   SCM_VALIDATE_OPENPORT (1, port);
   r = scm_to_int (rcount);
index 899d0b3..b44ec66 100644 (file)
@@ -191,6 +191,10 @@ SCM_INTERNAL SCM scm_i_port_weak_set;
 
 \f
 
+typedef enum scm_t_port_type_flags {
+  SCM_PORT_TYPE_HAS_FLUSH = 1 << 0
+} scm_t_port_type_flags;
+
 /* port-type description.  */
 typedef struct scm_t_ptob_descriptor
 {
@@ -211,6 +215,7 @@ typedef struct scm_t_ptob_descriptor
   scm_t_off (*seek) (SCM port, scm_t_off OFFSET, int WHENCE);
   void (*truncate) (SCM port, scm_t_off length);
 
+  unsigned flags;
 } scm_t_ptob_descriptor;
 
 #define SCM_TC2PTOBNUM(x) (0x0ff & ((x) >> 8))