diff options
author | Andy Wingo <wingo@pobox.com> | 2012-02-14 14:01:52 +0100 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2012-02-14 14:10:53 +0100 |
commit | 03a2eeb0cc032f48f8b789a04a41f37a6459d879 (patch) | |
tree | dbba31f2ce93bcc3071f30a964c92e7bc9fe50d8 | |
parent | 6c98257f2ead0855f218369ea7f9a823cdb9727e (diff) | |
download | guile-03a2eeb0cc032f48f8b789a04a41f37a6459d879.tar.gz |
ports: avoid adding port table entries and finalizers if possible
* 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.
-rw-r--r-- | libguile/ports.c | 65 | ||||
-rw-r--r-- | libguile/ports.h | 5 |
2 files changed, 37 insertions, 33 deletions
diff --git a/libguile/ports.c b/libguile/ports.c index 5fb3f59b0..c1da25e9a 100644 --- a/libguile/ports.c +++ b/libguile/ports.c @@ -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 - - /* 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); diff --git a/libguile/ports.h b/libguile/ports.h index 899d0b33b..b44ec66a9 100644 --- a/libguile/ports.h +++ b/libguile/ports.h @@ -191,6 +191,10 @@ SCM_INTERNAL SCM scm_i_port_weak_set; +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)) |