[Nickle] nickle: Branch 'master' - 3 commits

Bart Massey bart at po8.org
Tue Oct 2 11:43:50 PDT 2007


It should be easy to add finalizer support to your
mark-sweep GC, and then just close the file in the finalizer
when it becomes unreferenced.  This would be the traditional
solution, I think.  Am I missing something?

	Bart

In message <20071002085403.791D3114203 at keithp.com> you wrote:
> --===============1547860296==
> 
>  builtin-toplevel.c |    1 
>  ctype.5c           |   20 ++++++++-----
>  file.c             |   79 +++++++++++++++++++++++++++++------------------------
>  value.h            |    1 
>  4 files changed, 57 insertions(+), 44 deletions(-)
> 
> New commits:
> commit 2278b93b7e760f1153847a0b3c36d07684f72e0c
> Author: Keith Packard <keithp at koto.keithp.com>
> Date:   Tue Oct 2 01:53:02 2007 -0700
> 
>     Manage file buffer chains with explicit malloc/free.
>     
>     Buffer chains must have life equal to the file they belong to; an
>     unreferenced file may still have buffered data, so the buffers cannot be
>     reclaimed. The nickle GC does not have a separate pass that checks to see
>     which objects can be freed, rather it assumes that such objects are
>     self-contained.
>     
>     Hence, anything hanging off of an object which can refuse to
>     be reclaimed must not have been allocated from the nickle GC system. Yes,
>     this is a significant limitation to this allocator.
>     
>     Someday I'll figure out a good general fix for this problem, right now we'll
>     stop segfaults when applications drop file references without closing them.
> 
> diff --git a/file.c b/file.c
> index 77356b1..933b544 100644
> --- a/file.c
> +++ b/file.c
> @@ -472,6 +472,30 @@ ProcessInterrupt ()
>      }
>  }
>  
> +static FileChainPtr
> +FileChainAlloc (FileChainPtr next, int size)
> +{
> +    FileChainPtr	ret;
> +
> +    ret = malloc (sizeof (FileChain) + size);
> +    ret->next = next;
> +    ret->size = size;
> +    ret->used = 0;
> +    ret->ptr = 0;
> +    return ret;
> +}
> +
> +static void
> +FileChainFree (FileChainPtr ic)
> +{
> +    while (ic)
> +    {
> +	FileChainPtr next = ic->next;
> +	free (ic);
> +	ic = next;
> +    }
> +}
> +
>  int
>  FileInit (void)
>  {
> @@ -521,8 +545,6 @@ FileMark (void *object)
>  
>      FileFlush ((Value) file, False);
>      MemReference (file->next);
> -    MemReference (file->input);
> -    MemReference (file->output);
>  }
>  
>  void
> @@ -538,10 +560,14 @@ FileFree (void *object)
>  {
>      File    *file = object;
>  
> -    if (file->fd == -1)
> -	return 1;
> -    if (FileClose ((Value) file) != FileBlocked)
> +    if (file->fd == -1 || FileClose ((Value) file) != FileBlocked)
> +    {
> +	FileChainFree (file->input);
> +	file->input = NULL;
> +	FileChainFree (file->output);
> +	file->output = NULL;
>  	return 1;
> +    }
>      return 0;
>  }
>  
> @@ -613,30 +639,6 @@ FileResetFd (int fd)
>  #endif
>  }
>  
> -static void
> -FileChainMark (void *object)
> -{
> -    FileChainPtr	chain = object;
> -
> -    MemReference (chain->next);
> -}
> -
> -DataType    FileChainType = { FileChainMark, 0, "FileChainType" };
> -
> -static FileChainPtr
> -NewFileChain (FileChainPtr next, int size)
> -{
> -    ENTER ();
> -    FileChainPtr	ret;
> -
> -    ret = MemAllocate (&FileChainType, sizeof (FileChain) + size);
> -    ret->next = next;
> -    ret->size = size;
> -    ret->used = 0;
> -    ret->ptr = 0;
> -    RETURN (ret);
> -}
> -
>  Value
>  FileCreate (int fd, int flags)
>  {
> @@ -893,7 +895,7 @@ FileStringRead (char *string, int len)
>  
>      file = NewFile (-1);
>      file->file.flags |= FileString|FileReadable;
> -    file->file.input = NewFileChain (0, len);
> +    file->file.input = FileChainAlloc (0, len);
>      memcpy (FileBuffer (file->file.input), string, len);
>      file->file.input->used = len;
>      RETURN (file);
> @@ -1009,7 +1011,7 @@ FileInput (Value file)
>  	    EXIT ();
>  	    return FileEOF;
>  	}
> -	file->file.input = NewFileChain (0, FileBufferSize);
> +	file->file.input = FileChainAlloc (NULL, FileBufferSize);
>      }
>      ic = file->file.input;
>      for (;;)
> @@ -1022,7 +1024,12 @@ FileInput (Value file)
>  	else
>  	{
>  	    if (ic->next)
> -		ic = ic->next;
> +	    {
> +		file->file.input = ic->next;
> +		ic->next = NULL;
> +		FileChainFree (ic);
> +		ic = file->file.input;
> +	    }
>  	    else if (file->file.flags & FileString)
>  	    {
>  		file->file.flags |= FileEnd;
> @@ -1084,7 +1091,7 @@ FileUnput (Value file, unsigned char c)
>      ic = file->file.input;
>      if (!ic || ic->ptr == 0)
>      {
> -	ic = file->file.input = NewFileChain (file->file.input, FileBufferSize);
> +	ic = file->file.input = FileChainAlloc (file->file.input, FileBufferSize);
>  	ic->ptr = ic->used = ic->size;
>      }
>      FileBuffer(ic)[--ic->ptr] = c;
> @@ -1175,6 +1182,8 @@ FileFlush (Value file, Bool block)
>  		    ic->used = ic->ptr = 0;
>  		    break;
>  		}
> +		else
> +		    FileChainFree (ic);
>  		*prev = 0;
>  	    }
>  	}
> @@ -1214,7 +1223,7 @@ FileOutput (Value file, char c)
>      }
>      ic = file->file.output;
>      if (!ic)
> -	ic = file->file.output = NewFileChain (0, FileBufferSize);
> +	ic = file->file.output = FileChainAlloc (0, FileBufferSize);
>      if (ic->used == ic->size)
>      {
>  	if (FileFlush (file, False) == FileError)
> @@ -1224,7 +1233,7 @@ FileOutput (Value file, char c)
>  	}
>  	ic = file->file.output;
>  	if (ic->used == ic->size)
> -	    ic = file->file.output = NewFileChain (file->file.output, FileBufferSize);
> +	    ic = file->file.output = FileChainAlloc (file->file.output, FileBufferSize);
>      }
>      ic = file->file.output;
>      FileBuffer(ic)[ic->used++] = c;
> diff --git a/value.h b/value.h
> index c941011..e94428f 100644
> --- a/value.h
> +++ b/value.h
> @@ -625,7 +625,6 @@ typedef struct _array {
>  #define ArrayValueSet(a,i,v) (BoxValueSet(ArrayValueBox(a,i),ArrayValueElt(a,i), v))
>  
>  typedef struct _io_chain {
> -    DataType		*data;
>      struct _io_chain	*next;
>      int			size;
>      int			used;
> commit 8e3690cea5da54d83e6fd6d26c073c1c4d8ae403
> Author: Keith Packard <keithp at koto.keithp.com>
> Date:   Tue Oct 2 01:16:05 2007 -0700
> 
>     Extend Ctype namespace to latin-1.
>     
>     This should be extended to all of unicode, but that's a huge amount of data.
> 
> diff --git a/ctype.5c b/ctype.5c
> index 88dd1df..a595452 100644
> --- a/ctype.5c
> +++ b/ctype.5c
> @@ -16,8 +16,8 @@ namespace Ctype {
>  	return ch >= 0 && ch <= 127;
>      }
>      
> -    /* The characteristic vector of sets of ASCII chars. */
> -    public typedef bool[128] charset;
> +    /* The characteristic vector of sets of Latin-1 chars. */
> +    public typedef bool[256] charset;
>  
>      public charset make_charset(bool(int) cfun) 
>  	/*
> @@ -25,7 +25,7 @@ namespace Ctype {
>  	 */
>      {
>  	charset result;
> -	for (int i = 0; i < 128; i++)
> +	for (int i = 0; i < dim(result); i++)
>  	    result[i] = cfun(i);
>  	return result;
>      }
> @@ -35,7 +35,7 @@ namespace Ctype {
>  	 * Test whether a particular char is in a charset. 
>  	 */
>      {
> -	return isascii(ch) && v[ch];
> +	return ch >= 0 && ch < dim(v) && v[ch];
>      }
>  
>  
> @@ -51,7 +51,8 @@ namespace Ctype {
>  	 */
>      {
>  	static bool cfun(int ch) {
> -	    return ch >= 'A' && ch <= 'Z';
> +	    return (ch >= 'A' && ch <= 'Z' ||
> +		    ch >= 'À' && ch <= 'Þ');
>  	}
>  	static charset v = make_charset(cfun);
>  	return member(v, ch);
> @@ -63,7 +64,8 @@ namespace Ctype {
>  	 */
>      {
>  	static bool cfun(int ch) {
> -	    return ch >= 'a' && ch <= 'z';
> +	    return (ch >= 'a' && ch <= 'z' ||
> +		    ch >= 'à' && ch <= 'þ');
>  	}
>  	static charset v = make_charset(cfun);
>  	return member(v, ch);
> @@ -107,7 +109,8 @@ namespace Ctype {
>  	 */	
>      {
>  	static bool cfun(int ch) {
> -	    return ch > ' ' && ch < 127;
> +	    return (ch > ' ' && ch < 127 ||
> +		    ch >= 'À' && ch <= 'þ');
>  	}
>  	static charset v = make_charset(cfun);
>  	return member(v, ch);
> @@ -119,7 +122,8 @@ namespace Ctype {
>  	 */	
>      {
>  	static bool cfun(int ch) {
> -	    return ch >= ' ' && ch < 127;
> +	    return (ch >= ' ' && ch < 127 ||
> +		    ch >= 'À' && ch <= 'þ');
>  	}
>  	static charset v = make_charset(cfun);
>  	return member(v, ch);
> commit 52c9ae4e5c476f6b202b49de3840c7ffdd0e02d8
> Author: Keith Packard <keithp at koto.keithp.com>
> Date:   Tue Oct 2 01:15:16 2007 -0700
> 
>     Flush file output on exit call.
>     
>     Use of the built-in exit function should flush all file I/O, just as if the
>     program terminated by returning to the top level at EOF.
> 
> diff --git a/builtin-toplevel.c b/builtin-toplevel.c
> index 36f854c..6ef745b 100644
> --- a/builtin-toplevel.c
> +++ b/builtin-toplevel.c
> @@ -422,6 +422,7 @@ do_exit (Value av)
>      if (aborting)
>  	RETURN (Void);
>      IoFini ();
> +    FileFini ();
>      exit (code);
>      RETURN (Void);
>  }
> 
> --===============1547860296==
> Content-Type: text/plain; charset="us-ascii"
> MIME-Version: 1.0
> Content-Transfer-Encoding: 7bit
> Content-Disposition: inline
> 
> _______________________________________________
> Nickle mailing list
> Nickle at nickle.org
> http://nickle.org/mailman/listinfo/nickle
> 
> --===============1547860296==--


More information about the Nickle mailing list