mirror of
git://git.gnupg.org/gnupg.git
synced 2024-06-07 23:27:48 +02:00
Simplify the management of the stream list in estream.c
This commit is contained in:
parent
682da55aa9
commit
892793888e
|
@ -1,3 +1,14 @@
|
||||||
|
2011-03-03 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* estream.c (struct estream_list): Rename to estream_list_s and
|
||||||
|
simplify. A double linked list is overkill for our purpose.
|
||||||
|
(do_list_add, do_list_remove): Adjust accordingly.
|
||||||
|
(_es_get_std_stream): Ditto.
|
||||||
|
(do_list_iterate, estream_iterator_t): Remove; it is used only at
|
||||||
|
one place.
|
||||||
|
(es_fflush): Replace iteration function. Also lock each stream
|
||||||
|
while flushing all streams.
|
||||||
|
|
||||||
2011-02-27 Werner Koch <wk@g10code.com>
|
2011-02-27 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* gettime.c (isotime2epoch): Factor check code out to ..
|
* gettime.c (isotime2epoch): Factor check code out to ..
|
||||||
|
|
138
common/estream.c
138
common/estream.c
|
@ -1,5 +1,5 @@
|
||||||
/* estream.c - Extended Stream I/O Library
|
/* estream.c - Extended Stream I/O Library
|
||||||
* Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010 g10 Code GmbH
|
* Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 g10 Code GmbH
|
||||||
*
|
*
|
||||||
* This file is part of Libestream.
|
* This file is part of Libestream.
|
||||||
*
|
*
|
||||||
|
@ -254,28 +254,26 @@ typedef struct estream_internal *estream_internal_t;
|
||||||
#define ESTREAM_UNLOCK(stream) ESTREAM_MUTEX_UNLOCK (stream->intern->lock)
|
#define ESTREAM_UNLOCK(stream) ESTREAM_MUTEX_UNLOCK (stream->intern->lock)
|
||||||
#define ESTREAM_TRYLOCK(stream) ESTREAM_MUTEX_TRYLOCK (stream->intern->lock)
|
#define ESTREAM_TRYLOCK(stream) ESTREAM_MUTEX_TRYLOCK (stream->intern->lock)
|
||||||
|
|
||||||
/* Stream list. */
|
/* A linked list to hold active stream objects. */
|
||||||
|
struct estream_list_s
|
||||||
typedef struct estream_list *estream_list_t;
|
|
||||||
|
|
||||||
struct estream_list
|
|
||||||
{
|
{
|
||||||
estream_t car;
|
struct estream_list_s *next;
|
||||||
estream_list_t cdr;
|
estream_t stream; /* Entry is not used if NULL. */
|
||||||
estream_list_t *prev_cdr;
|
|
||||||
};
|
};
|
||||||
|
typedef struct estream_list_s *estream_list_t;
|
||||||
static estream_list_t estream_list;
|
static estream_list_t estream_list;
|
||||||
static estream_mutex_t estream_list_lock;
|
|
||||||
|
|
||||||
#define ESTREAM_LIST_LOCK ESTREAM_MUTEX_LOCK (estream_list_lock)
|
|
||||||
#define ESTREAM_LIST_UNLOCK ESTREAM_MUTEX_UNLOCK (estream_list_lock)
|
|
||||||
|
|
||||||
/* File descriptors registered to be used as the standard file handles. */
|
/* File descriptors registered to be used as the standard file handles. */
|
||||||
static int custom_std_fds[3];
|
static int custom_std_fds[3];
|
||||||
static unsigned char custom_std_fds_valid[3];
|
static unsigned char custom_std_fds_valid[3];
|
||||||
|
|
||||||
|
/* A lock object for the estream list and the custom_std_fds array. */
|
||||||
|
static estream_mutex_t estream_list_lock;
|
||||||
|
#define ESTREAM_LIST_LOCK ESTREAM_MUTEX_LOCK (estream_list_lock)
|
||||||
|
#define ESTREAM_LIST_UNLOCK ESTREAM_MUTEX_UNLOCK (estream_list_lock)
|
||||||
|
|
||||||
|
|
||||||
|
/* Error code replacements. */
|
||||||
#ifndef EOPNOTSUPP
|
#ifndef EOPNOTSUPP
|
||||||
# define EOPNOTSUPP ENOSYS
|
# define EOPNOTSUPP ENOSYS
|
||||||
#endif
|
#endif
|
||||||
|
@ -372,75 +370,63 @@ map_w32_to_errno (DWORD w32_err)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Add STREAM to the list of registered stream objects. If
|
/* Add STREAM to the list of registered stream objects. If
|
||||||
WITH_LOCKED_LIST is true we assumed that the list of streams is
|
WITH_LOCKED_LIST is true it is assumed that the list of streams is
|
||||||
already locked. */
|
already locked. The implementation is straightforward: We first
|
||||||
|
look for an unused entry in the list and use that; if none is
|
||||||
|
available we put a new item at the head. We drawback of the
|
||||||
|
strategy never to shorten the list is that a one time allocation of
|
||||||
|
many streams will lead to scanning unused entries later. If that
|
||||||
|
turns out to be a problem, we may either free some items from the
|
||||||
|
list or append new entries at the end; or use a table. Returns 0
|
||||||
|
on success; on error or non-zero is returned and ERRNO set. */
|
||||||
static int
|
static int
|
||||||
do_list_add (estream_t stream, int with_locked_list)
|
do_list_add (estream_t stream, int with_locked_list)
|
||||||
{
|
{
|
||||||
estream_list_t list_obj;
|
estream_list_t item;
|
||||||
int ret;
|
|
||||||
|
|
||||||
list_obj = mem_alloc (sizeof (*list_obj));
|
if (!with_locked_list)
|
||||||
if (! list_obj)
|
ESTREAM_LIST_LOCK;
|
||||||
ret = -1;
|
|
||||||
else
|
for (item = estream_list; item && item->stream; item = item->next)
|
||||||
|
;
|
||||||
|
if (!item)
|
||||||
{
|
{
|
||||||
if (!with_locked_list)
|
item = mem_alloc (sizeof *item);
|
||||||
ESTREAM_LIST_LOCK;
|
if (item)
|
||||||
list_obj->car = stream;
|
{
|
||||||
list_obj->cdr = estream_list;
|
item->next = estream_list;
|
||||||
list_obj->prev_cdr = &estream_list;
|
estream_list = item;
|
||||||
if (estream_list)
|
}
|
||||||
estream_list->prev_cdr = &list_obj->cdr;
|
|
||||||
estream_list = list_obj;
|
|
||||||
if (!with_locked_list)
|
|
||||||
ESTREAM_LIST_UNLOCK;
|
|
||||||
ret = 0;
|
|
||||||
}
|
}
|
||||||
|
if (item)
|
||||||
|
item->stream = stream;
|
||||||
|
|
||||||
return ret;
|
if (!with_locked_list)
|
||||||
|
ESTREAM_LIST_UNLOCK;
|
||||||
|
|
||||||
|
return item? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove STREAM from the list of registered stream objects. */
|
/* Remove STREAM from the list of registered stream objects. */
|
||||||
static void
|
static void
|
||||||
do_list_remove (estream_t stream, int with_locked_list)
|
do_list_remove (estream_t stream, int with_locked_list)
|
||||||
{
|
{
|
||||||
estream_list_t list_obj;
|
estream_list_t item;
|
||||||
|
|
||||||
if (!with_locked_list)
|
if (!with_locked_list)
|
||||||
ESTREAM_LIST_LOCK;
|
ESTREAM_LIST_LOCK;
|
||||||
for (list_obj = estream_list; list_obj; list_obj = list_obj->cdr)
|
|
||||||
if (list_obj->car == stream)
|
for (item = estream_list; item; item = item->next)
|
||||||
|
if (item->stream == stream)
|
||||||
{
|
{
|
||||||
*list_obj->prev_cdr = list_obj->cdr;
|
item->stream = NULL;
|
||||||
if (list_obj->cdr)
|
break;
|
||||||
list_obj->cdr->prev_cdr = list_obj->prev_cdr;
|
|
||||||
mem_free (list_obj);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!with_locked_list)
|
if (!with_locked_list)
|
||||||
ESTREAM_LIST_UNLOCK;
|
ESTREAM_LIST_UNLOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Type of an stream-iterator-function. */
|
|
||||||
typedef int (*estream_iterator_t) (estream_t stream);
|
|
||||||
|
|
||||||
/* Iterate over list of registered streams, calling ITERATOR for each
|
|
||||||
of them. */
|
|
||||||
static int
|
|
||||||
do_list_iterate (estream_iterator_t iterator)
|
|
||||||
{
|
|
||||||
estream_list_t list_obj;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
ESTREAM_LIST_LOCK;
|
|
||||||
for (list_obj = estream_list; list_obj; list_obj = list_obj->cdr)
|
|
||||||
ret |= (*iterator) (list_obj->car);
|
|
||||||
ESTREAM_LIST_UNLOCK;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -487,6 +473,14 @@ do_deinit (void)
|
||||||
{
|
{
|
||||||
/* Flush all streams. */
|
/* Flush all streams. */
|
||||||
es_fflush (NULL);
|
es_fflush (NULL);
|
||||||
|
|
||||||
|
/* We should release the estream_list. However there is one
|
||||||
|
problem: That list is also used to search for the standard
|
||||||
|
estream file descriptors. If we would remove the entire list,
|
||||||
|
any use of es_foo in another atexit function may re-create the
|
||||||
|
list and the streams with possible undesirable effects. Given
|
||||||
|
that we don't close the stream either, it should not matter that
|
||||||
|
we keep the list and let the OS clean it up at process end. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2905,11 +2899,11 @@ _es_get_std_stream (int fd)
|
||||||
|
|
||||||
fd %= 3; /* We only allow 0, 1 or 2 but we don't want to return an error. */
|
fd %= 3; /* We only allow 0, 1 or 2 but we don't want to return an error. */
|
||||||
ESTREAM_LIST_LOCK;
|
ESTREAM_LIST_LOCK;
|
||||||
for (list_obj = estream_list; list_obj; list_obj = list_obj->cdr)
|
for (list_obj = estream_list; list_obj; list_obj = list_obj->next)
|
||||||
if (list_obj->car->intern->is_stdstream
|
if (list_obj->stream && list_obj->stream->intern->is_stdstream
|
||||||
&& list_obj->car->intern->stdstream_fd == fd)
|
&& list_obj->stream->intern->stdstream_fd == fd)
|
||||||
{
|
{
|
||||||
stream = list_obj->car;
|
stream = list_obj->stream;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!stream)
|
if (!stream)
|
||||||
|
@ -3241,8 +3235,20 @@ es_fflush (estream_t stream)
|
||||||
ESTREAM_UNLOCK (stream);
|
ESTREAM_UNLOCK (stream);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
err = do_list_iterate (do_fflush);
|
{
|
||||||
|
estream_list_t item;
|
||||||
|
|
||||||
|
err = 0;
|
||||||
|
ESTREAM_LIST_LOCK;
|
||||||
|
for (item = estream_list; item; item = item->next)
|
||||||
|
if (item->stream)
|
||||||
|
{
|
||||||
|
ESTREAM_LOCK (item->stream);
|
||||||
|
err |= do_fflush (item->stream);
|
||||||
|
ESTREAM_UNLOCK (item->stream);
|
||||||
|
}
|
||||||
|
ESTREAM_LIST_UNLOCK;
|
||||||
|
}
|
||||||
return err ? EOF : 0;
|
return err ? EOF : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user