Skip to content

Commit

Permalink
Prune draw queue before sending to frontend
Browse files Browse the repository at this point in the history
If the draw queue fills up with lots (i.e. twice the number of max rows)
of insert/delete line commands we can remove draw commands from the
beginning of the draw queue.  This reduces the possibility of the draw
queue overflowing.
  • Loading branch information
b4winckler committed Jan 10, 2009
1 parent e706fca commit 02592cf
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 2 deletions.
2 changes: 2 additions & 0 deletions src/MacVim/MMBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
BOOL waitForAck;
int initialWindowLayout;
BOOL flushDisabled;
unsigned numWholeLineChanges;
unsigned offsetForDrawDataPrune;
}

+ (MMBackend *)sharedInstance;
Expand Down
46 changes: 44 additions & 2 deletions src/MacVim/MMBackend.m
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ - (NSComparisonResult)serverNameCompare:(NSString *)string;


@interface MMBackend (Private)
- (void)clearDrawData;
- (void)didChangeWholeLine;
- (void)waitForDialogReturn;
- (void)insertVimStateMessage;
- (void)processInputQueue;
Expand Down Expand Up @@ -364,7 +366,7 @@ - (void)clearAll
// Any draw commands in queue are effectively obsolete since this clearAll
// will negate any effect they have, therefore we may as well clear the
// draw queue.
[drawData setLength:0];
[self clearDrawData];

[drawData appendBytes:&type length:sizeof(int)];
}
Expand Down Expand Up @@ -396,6 +398,9 @@ - (void)deleteLinesFromRow:(int)row count:(int)count
[drawData appendBytes:&bottom length:sizeof(int)];
[drawData appendBytes:&left length:sizeof(int)];
[drawData appendBytes:&right length:sizeof(int)];

if (left == 0 && right == gui.num_cols-1)
[self didChangeWholeLine];
}

- (void)drawString:(char*)s length:(int)len row:(int)row column:(int)col
Expand Down Expand Up @@ -431,6 +436,9 @@ - (void)insertLinesFromRow:(int)row count:(int)count
[drawData appendBytes:&bottom length:sizeof(int)];
[drawData appendBytes:&left length:sizeof(int)];
[drawData appendBytes:&right length:sizeof(int)];

if (left == 0 && right == gui.num_cols-1)
[self didChangeWholeLine];
}

- (void)drawCursorAtRow:(int)row column:(int)col shape:(int)shape
Expand Down Expand Up @@ -491,7 +499,7 @@ - (void)flushQueue:(BOOL)force
[drawData appendBytes:&gui.col length:sizeof(gui.col)];

[self queueMessage:BatchDrawMsgID data:[drawData copy]];
[drawData setLength:0];
[self clearDrawData];
}

if ([outputQueue count] > 0) {
Expand Down Expand Up @@ -1466,6 +1474,40 @@ - (oneway void)acknowledgeConnection

@implementation MMBackend (Private)

- (void)clearDrawData
{
[drawData setLength:0];
numWholeLineChanges = offsetForDrawDataPrune = 0;
}

- (void)didChangeWholeLine
{
// It may happen that draw queue is filled up with lots of changes that
// affect a whole row. If the number of such changes equals twice the
// number of visible rows then we can prune some commands off the queue.
//
// NOTE: If we don't perform this pruning the draw queue may grow
// indefinitely if Vim were to repeatedly send draw commands without ever
// waiting for new input (that's when the draw queue is flushed). The one
// instance I know where this can happen is when a command is executed in
// the shell (think ":grep" with thousands of matches).

++numWholeLineChanges;
if (numWholeLineChanges == gui.num_rows) {
// Remember the offset to prune up to.
offsetForDrawDataPrune = [drawData length];
} else if (numWholeLineChanges == 2*gui.num_rows) {
// Delete all the unnecessary draw commands.
NSMutableData *d = [[NSMutableData alloc]
initWithBytes:[drawData bytes] + offsetForDrawDataPrune
length:[drawData length] - offsetForDrawDataPrune];
offsetForDrawDataPrune = [d length];
numWholeLineChanges -= gui.num_rows;
[drawData release];
drawData = d;
}
}

- (void)waitForDialogReturn
{
// Keep processing the run loop until a dialog returns. To avoid getting
Expand Down

0 comments on commit 02592cf

Please sign in to comment.