mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-02 02:10:19 +02:00
Remove weak set usage in ports.c
* libguile/ephemerons.h: * libguile/ephemerons.c (scm_c_ephemeron_load, scm_c_ephemeron_push): New routines. * libguile/ioext.c (scm_fdes_to_ports): Rework in terms of scm_c_port_for_each. * libguile/ports-internal.h (struct scm_t_port): Add pointer to entry on weak ports list, so that we can cancel it easily. * libguile/ports.c (release_port): Mark weak ports list entry as dead. (all_ports_needing_close, for_each_port_needing_close): Rework as ephemeron chain. (scm_c_make_port_with_encoding, close_port, scm_c_port_for_each): Adapt API. (scm_init_ports): No more weak set.
This commit is contained in:
parent
2a6f6ec354
commit
dbc384a6ba
6 changed files with 67 additions and 51 deletions
|
@ -126,6 +126,18 @@ scm_c_ephemeron_next (struct gc_ephemeron *e)
|
|||
return gc_ephemeron_chain_next (e);
|
||||
}
|
||||
|
||||
struct gc_ephemeron*
|
||||
scm_c_ephemeron_load (struct gc_ephemeron **loc)
|
||||
{
|
||||
return gc_ephemeron_chain_head (loc);
|
||||
}
|
||||
|
||||
void
|
||||
scm_c_ephemeron_push (struct gc_ephemeron **loc, struct gc_ephemeron *e)
|
||||
{
|
||||
gc_ephemeron_chain_push (loc, e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -39,6 +39,10 @@ SCM_INTERNAL int scm_i_print_ephemeron (SCM exp, SCM port,
|
|||
SCM_INTERNAL struct gc_ephemeron* scm_to_ephemeron (SCM e);
|
||||
SCM_INTERNAL SCM scm_from_ephemeron (struct gc_ephemeron *e);
|
||||
|
||||
SCM_INTERNAL struct gc_ephemeron* scm_c_ephemeron_load (struct gc_ephemeron **loc);
|
||||
SCM_INTERNAL void scm_c_ephemeron_push (struct gc_ephemeron **loc,
|
||||
struct gc_ephemeron *e);
|
||||
|
||||
SCM_INTERNAL struct scm_ephemeron_table* scm_c_make_ephemeron_table (size_t count);
|
||||
SCM_INTERNAL size_t scm_c_ephemeron_table_length (struct scm_ephemeron_table *et);
|
||||
SCM_INTERNAL struct gc_ephemeron*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright 1995-2001,2003,2006,2011,2014,2018
|
||||
/* Copyright 1995-2001,2003,2006,2011,2014,2018,2025
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Guile.
|
||||
|
@ -282,15 +282,19 @@ SCM_DEFINE (scm_primitive_move_to_fdes, "primitive-move->fdes", 2, 0, 0,
|
|||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
static SCM
|
||||
get_matching_port (void *closure, SCM port, SCM result)
|
||||
struct scm_fdes_to_ports_data
|
||||
{
|
||||
int fd = * (int *) closure;
|
||||
|
||||
if (SCM_OPFPORTP (port) && SCM_FSTREAM (port)->fdes == fd)
|
||||
result = scm_cons (port, result);
|
||||
SCM ports;
|
||||
int fd;
|
||||
};
|
||||
|
||||
return result;
|
||||
static void
|
||||
collect_matching_ports (void *closure, SCM port)
|
||||
{
|
||||
struct scm_fdes_to_ports_data *data = closure;
|
||||
|
||||
if (SCM_OPFPORTP (port) && SCM_FSTREAM (port)->fdes == data->fd)
|
||||
data->ports = scm_cons (port, data->ports);
|
||||
}
|
||||
|
||||
/* Return a list of ports using a given file descriptor. */
|
||||
|
@ -301,13 +305,13 @@ SCM_DEFINE (scm_fdes_to_ports, "fdes->ports", 1, 0, 0,
|
|||
"counts.")
|
||||
#define FUNC_NAME s_scm_fdes_to_ports
|
||||
{
|
||||
SCM result = SCM_EOL;
|
||||
int int_fd = scm_to_int (fd);
|
||||
struct scm_fdes_to_ports_data data;
|
||||
data.ports = SCM_EOL;
|
||||
data.fd = scm_to_int (fd);
|
||||
|
||||
result = scm_c_weak_set_fold (get_matching_port,
|
||||
(void*) &int_fd, result,
|
||||
scm_i_port_weak_set);
|
||||
return result;
|
||||
scm_c_port_for_each (collect_matching_ports, &data);
|
||||
|
||||
return data.ports;
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* ports-internal.h - internal-only declarations for ports.
|
||||
|
||||
Copyright 2013,2018
|
||||
Copyright 2013,2018,2025
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Guile.
|
||||
|
@ -27,6 +27,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "libguile/bytevectors.h"
|
||||
#include "libguile/ephemerons.h"
|
||||
#include "libguile/list.h"
|
||||
#include "libguile/pairs.h"
|
||||
#include "libguile/ports.h"
|
||||
|
@ -361,6 +362,12 @@ struct scm_t_port
|
|||
iconv_t input_cd; /* with iconv_lock */
|
||||
iconv_t output_cd; /* with iconv_lock */
|
||||
|
||||
/* If the port needs to be closed when it becomes unreachable, it is
|
||||
put on a global ephemeron chain, so that we can explicitly flush
|
||||
all ports. If the port is later closed manually, we can mark that
|
||||
chain link as dead, and it will be collected on the next GC. */
|
||||
struct gc_ephemeron *close_handle;
|
||||
|
||||
/* Port properties. */
|
||||
SCM alist;
|
||||
};
|
||||
|
|
|
@ -159,6 +159,13 @@ release_port (SCM port)
|
|||
if (cur > 1)
|
||||
return;
|
||||
|
||||
struct gc_ephemeron *e = pt->close_handle;
|
||||
if (e)
|
||||
{
|
||||
pt->close_handle = NULL;
|
||||
scm_c_ephemeron_mark_dead_x (e);
|
||||
}
|
||||
|
||||
/* FIXME: `catch' around the close call? It could throw an exception,
|
||||
and in that case we'd leak the iconv descriptors, if any. */
|
||||
if (SCM_PORT_TYPE (port)->close)
|
||||
|
@ -701,11 +708,24 @@ SCM_DEFINE (scm_port_mode, "port-mode", 1, 0, 0,
|
|||
|
||||
|
||||
|
||||
/* The port table --- a weak set of all ports.
|
||||
/* The port list --- a weak list of all ports.
|
||||
|
||||
We need a global registry of ports to flush them all at exit, and to
|
||||
get all the ports matching a file descriptor. */
|
||||
SCM scm_i_port_weak_set;
|
||||
static struct gc_ephemeron *all_ports_needing_close = NULL;
|
||||
|
||||
static void
|
||||
for_each_port_needing_close (void (*proc)(void *data, SCM p), void *data)
|
||||
{
|
||||
for (struct gc_ephemeron *e = scm_c_ephemeron_load (&all_ports_needing_close);
|
||||
e;
|
||||
e = scm_c_ephemeron_next (e))
|
||||
{
|
||||
SCM port = scm_c_ephemeron_key (e);
|
||||
if (!scm_is_false (port))
|
||||
proc (data, port);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -798,7 +818,8 @@ scm_c_make_port_with_encoding (scm_t_port_type *ptob, unsigned long mode_bits,
|
|||
if (SCM_PORT_TYPE (ret)->flags & SCM_PORT_TYPE_NEEDS_CLOSE_ON_GC)
|
||||
{
|
||||
scm_i_add_port_finalizer (SCM_I_CURRENT_THREAD, ret);
|
||||
scm_weak_set_add_x (scm_i_port_weak_set, ret);
|
||||
pt->close_handle = scm_c_make_ephemeron (ret, SCM_BOOL_T);
|
||||
scm_c_ephemeron_push (&all_ports_needing_close, pt->close_handle);
|
||||
}
|
||||
|
||||
initialize_port_buffers (ret);
|
||||
|
@ -901,9 +922,6 @@ close_port (SCM port, int explicit)
|
|||
|
||||
SCM_CLR_PORT_OPEN_FLAG (port);
|
||||
|
||||
if (SCM_PORT_TYPE (port)->flags & SCM_PORT_TYPE_NEEDS_CLOSE_ON_GC)
|
||||
scm_weak_set_remove_x (scm_i_port_weak_set, port);
|
||||
|
||||
release_port (port);
|
||||
|
||||
return SCM_BOOL_T;
|
||||
|
@ -4059,32 +4077,10 @@ scm_port_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
|
|||
|
||||
/* Iterating over all ports. */
|
||||
|
||||
struct for_each_data
|
||||
{
|
||||
void (*proc) (void *data, SCM p);
|
||||
void *data;
|
||||
};
|
||||
|
||||
static SCM
|
||||
for_each_trampoline (void *data, SCM port, SCM result)
|
||||
{
|
||||
struct for_each_data *d = data;
|
||||
|
||||
d->proc (d->data, port);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
scm_c_port_for_each (void (*proc)(void *data, SCM p), void *data)
|
||||
{
|
||||
struct for_each_data d;
|
||||
|
||||
d.proc = proc;
|
||||
d.data = data;
|
||||
|
||||
scm_c_weak_set_fold (for_each_trampoline, &d, SCM_EOL,
|
||||
scm_i_port_weak_set);
|
||||
for_each_port_needing_close (proc, data);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -4230,8 +4226,6 @@ scm_init_ports (void)
|
|||
scm_void_port_type = scm_make_port_type ("void", void_port_read,
|
||||
void_port_write);
|
||||
|
||||
scm_i_port_weak_set = scm_c_make_weak_set (31);
|
||||
|
||||
cur_inport_fluid = scm_make_fluid ();
|
||||
cur_outport_fluid = scm_make_fluid ();
|
||||
cur_errport_fluid = scm_make_fluid ();
|
||||
|
|
|
@ -27,11 +27,6 @@
|
|||
#include "libguile/print.h"
|
||||
#include "libguile/strings.h"
|
||||
|
||||
|
||||
|
||||
SCM_INTERNAL SCM scm_i_port_weak_set;
|
||||
|
||||
|
||||
|
||||
|
||||
#define SCM_EOF_OBJECT_P(x) (scm_is_eq ((x), SCM_EOF_VAL))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue