9front - general discussion about 9front
 help / color / mirror / Atom feed
From: ori@eigenstate.org
To: 9front@9front.org
Subject: Re: [9front] [PATCH] acme: limit reads of the event file to one read.
Date: Sat, 12 Jun 2021 10:10:13 -0400	[thread overview]
Message-ID: <9CB57FC9074A1CEF5875C545BC8E762D@eigenstate.org> (raw)
In-Reply-To: <AD2DBCBD646D70FB0853D9EE79CD08A1@biobuf.link>

Definitely makes it easier to write acme clients,
I'm in favor.

Style nitpicks:

	if(foo) {, if (foo) {

should be:

	if(foo){

It's also worth asking if we should unfuck the message
format, which would be an incompatible change.

1. Always return exactly one message set, rather than
   splitting across reads
2. Counting the message size in bytes, so you can
   read and copy the required amount, rather than
   trying to figure out the byte count from the
   rune count
3. Maybe do something about the difficult-to-interpret
   continuation messages; eg, flatten them into one
   event, and put the required information into the one
   event.

I'd be ok with it, but I'm not a heavy acme user, and
I don't know how many acme users use external tools
that'd need to be fixed up.

Also, we've been more or less treating plan9port as
acme upstream, not sure if we'd want to diverge.

Quoth james palmer <james@biobuf.link>:
> this patch limits acme to one message per read of the event file.
> this makes writing clients easier because events can be read into a
> sufficiently large buffer and parsed instead of read one byte at a time.
> 
> git/import-able patch follows.
> 
> - james
> 
>  From 189797ed9098d5f6cc06cda299f1941dc07dee08
> From: james palmer <foura@biobuf.link>
> Date: Fri, 11 Jun 2021 19:41:38 +0000
> Subject: [PATCH] acme: limit reads of the events file to one event for easier parsing.
> 
> ---
> diff 3ec67240f59d1e68b8d7fcb30fa17fe87f317bff 189797ed9098d5f6cc06cda299f1941dc07dee08
> --- a/sys/src/cmd/acme/dat.h	Mon Jun  7 10:13:51 2021
> +++ b/sys/src/cmd/acme/dat.h	Fri Jun 11 20:41:38 2021
> @@ -44,6 +44,7 @@
>  typedef	struct	Fid Fid;
>  typedef	struct	File File;
>  typedef	struct	Elog Elog;
> +typedef struct	Event Event;
>  typedef	struct	Mntdir Mntdir;
>  typedef	struct	Range Range;
>  typedef	struct	Rangeset Rangeset;
> @@ -256,8 +257,8 @@
>  	int		rdselfd;
>  	Column	*col;
>  	Xfid		*eventx;
> -	char		*events;
> -	int		nevents;
> +	Event	*evhead;
> +	Event	*evtail;
>  	int		owner;
>  	int		maxlines;
>  	Dirlist	**dlp;
> @@ -278,6 +279,14 @@
>  	int		tagexpand;
>  	int		taglines;
>  	Rectangle	tagtop;
> +	int deleted;
> +};
> +
> +struct Event {
> +	char *buf;
> +	int sz;
> +	int offset;
> +	Event *next;
>  };
>  
>  void	wininit(Window*, Window*, Rectangle);
> --- a/sys/src/cmd/acme/wind.c	Mon Jun  7 10:13:51 2021
> +++ b/sys/src/cmd/acme/wind.c	Fri Jun 11 20:41:38 2021
> @@ -22,6 +22,9 @@
>  	Rune *rp;
>  	int nc, i;
>  
> +	w->deleted = 0;
> +	w->evhead = nil;
> +	w->evtail = nil;
>  	w->tag.w = w;
>  	w->taglines = 1;
>  	w->tagexpand = TRUE;
> @@ -311,6 +314,7 @@
>  winclose(Window *w)
>  {
>  	int i;
> +	Event *cur, *next;
>  
>  	if(decref(w) == 0){
>  		xfidlog(w, "del");
> @@ -322,7 +326,15 @@
>  		for(i=0; i<w->nincl; i++)
>  			free(w->incl[i]);
>  		free(w->incl);
> -		free(w->events);
> +		
> +		cur = w->evhead;
> +		while(cur) {
> +			next = cur->next;
> +			free(cur);
> +			free(cur->buf);
> +			cur = next;
> +		}
> +		
>  		free(w);
>  	}
>  }
> @@ -331,12 +343,21 @@
>  windelete(Window *w)
>  {
>  	Xfid *x;
> +	Event *cur, *next;
>  
>  	x = w->eventx;
>  	if(x){
> -		w->nevents = 0;
> -		free(w->events);
> -		w->events = nil;
> +		cur = w->evhead;
> +		while(cur) {
> +			next = cur->next;
> +			free(cur->buf);
> +			free(cur);
> +			cur = next;
> +		}
> +		
> +		w->deleted = 1;
> +		w->evhead = nil;
> +		w->evtail = nil;
>  		w->eventx = nil;
>  		sendp(x->c, nil);	/* wake him up */
>  	}
> @@ -669,26 +690,42 @@
>  void
>  winevent(Window *w, char *fmt, ...)
>  {
> -	int n;
> -	char *b;
>  	Xfid *x;
> +	char *buf;
>  	va_list arg;
> +	Event *ev;
>  
>  	if(w->nopen[QWevent] == 0)
>  		return;
>  	if(w->owner == 0)
> -		error("no window owner");
> +		error("no window owner");	
> +		
> +	ev = emalloc(sizeof(Event));
> +	ev->next = nil;
> +
>  	va_start(arg, fmt);
> -	b = vsmprint(fmt, arg);
> +	buf = vsmprint(fmt, arg);
>  	va_end(arg);
> -	if(b == nil)
> +	
> +	if(buf == nil)
>  		error("vsmprint failed");
> -	n = strlen(b);
> -	w->events = erealloc(w->events, w->nevents+1+n);
> -	w->events[w->nevents++] = w->owner;
> -	memmove(w->events+w->nevents, b, n);
> -	free(b);
> -	w->nevents += n;
> +		
> +	ev->buf = smprint("%c%s", w->owner, buf);
> +	if(!ev->buf)
> +		error("smprint failed");
> +	free(buf);
> +	
> +	ev->offset = 0;
> +	ev->sz = strlen(ev->buf);
> +	
> +	if(w->evhead) {
> +		w->evtail->next = ev;
> +		w->evtail = ev;
> +	} else {
> +		w->evhead = ev;
> +		w->evtail = ev;
> +	}
> +	
>  	x = w->eventx;
>  	if(x){
>  		w->eventx = nil;
> --- a/sys/src/cmd/acme/xfid.c	Mon Jun  7 10:13:51 2021
> +++ b/sys/src/cmd/acme/xfid.c	Fri Jun 11 20:41:38 2021
> @@ -991,34 +991,45 @@
>  xfideventread(Xfid *x, Window *w)
>  {
>  	Fcall fc;
> -	char *b;
> -	int i, n;
> +	Event *ev;
> +	int bufsz;
> +	char *buf;
>  
> -	i = 0;
>  	x->flushed = FALSE;
> -	while(w->nevents == 0){
> -		if(i){
> -			if(!x->flushed)
> -				respond(x, &fc, "window shut down");
> +	while(!w->evhead){
> +		if(w->deleted) {
> +			respond(x, &fc, "window shut down");
>  			return;
>  		}
> +		
>  		w->eventx = x;
>  		winunlock(w);
>  		recvp(x->c);
>  		winlock(w, 'F');
> -		i++;
>  	}
> -
> -	n = w->nevents;
> -	if(n > x->count)
> -		n = x->count;
> -	fc.count = n;
> -	fc.data = w->events;
> +	
> +	ev = w->evhead;
> +	bufsz = ev->sz - ev->offset < x->count
> +		? ev->sz - ev->offset : x->count;

there's a 'min()' in util.c

> +	buf = emalloc(bufsz);
> +	
> +	memcpy(buf, ev->buf+ev->offset, bufsz);
> +	ev->offset += bufsz;
> +	
> +	if(ev->offset == bufsz) {
> +		w->evhead = ev->next;
> +		free(ev->buf);
> +		free(ev);
> +		
> +		if(!w->evhead)
> +			w->evtail = nil;
> +	}
> +		
> +	
> +	fc.count = bufsz;
> +	fc.data = buf;
>  	respond(x, &fc, nil);
> -	b = w->events;
> -	w->events = estrdup(w->events+n);
> -	free(b);
> -	w->nevents -= n;
> +	free(buf);
>  }
>  
>  void
> 


      parent reply	other threads:[~2021-06-14 20:04 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-11 20:00 james palmer
2021-06-12 11:43 ` james palmer
2021-06-12 14:22   ` james palmer
2021-06-12 14:10 ` ori [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9CB57FC9074A1CEF5875C545BC8E762D@eigenstate.org \
    --to=ori@eigenstate.org \
    --cc=9front@9front.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).