aboutsummaryrefslogtreecommitdiffstats
path: root/src/buffer.c
diff options
context:
space:
mode:
authorDmitry Antipov2012-07-20 20:05:47 +0400
committerDmitry Antipov2012-07-20 20:05:47 +0400
commit9928463dcdb0164477785e83406602065de79ef8 (patch)
tree14d6b28885b7e333733ff4eb62275e6e425f81b3 /src/buffer.c
parentf8643a6b9e35af22b69a84f83df5d9410de82f16 (diff)
downloademacs-9928463dcdb0164477785e83406602065de79ef8.tar.gz
emacs-9928463dcdb0164477785e83406602065de79ef8.zip
Add indirection counting to speed up Fkill_buffer.
* buffer.h (struct buffer): New member. * buffer.c (Fget_buffer_create): Set indirection counter to 0. (Fmake_indirect_buffer): Set indirection counter to -1, increment base buffer indirection counter. (compact_buffer): If ENABLE_CHECKING, verify indirection counters. (Fkill_buffer): Adjust indirection counters as needed, don't walk through buffer list if indirection counter is 0.
Diffstat (limited to 'src/buffer.c')
-rw-r--r--src/buffer.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/src/buffer.c b/src/buffer.c
index b722ff135dd..5f9f6a79b67 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -329,7 +329,9 @@ even if it is dead. The return value is never nil. */)
329 329
330 /* An ordinary buffer uses its own struct buffer_text. */ 330 /* An ordinary buffer uses its own struct buffer_text. */
331 b->text = &b->own_text; 331 b->text = &b->own_text;
332 b->base_buffer = 0; 332 b->base_buffer = NULL;
333 /* No one shares the text with us now. */
334 b->indirections = 0;
333 335
334 BUF_GAP_SIZE (b) = 20; 336 BUF_GAP_SIZE (b) = 20;
335 BLOCK_INPUT; 337 BLOCK_INPUT;
@@ -568,12 +570,18 @@ CLONE nil means the indirect buffer's state is reset to default values. */)
568 570
569 b = allocate_buffer (); 571 b = allocate_buffer ();
570 572
573 /* No double indirection - if base buffer is indirect,
574 new buffer becomes an indirect to base's base. */
571 b->base_buffer = (XBUFFER (base_buffer)->base_buffer 575 b->base_buffer = (XBUFFER (base_buffer)->base_buffer
572 ? XBUFFER (base_buffer)->base_buffer 576 ? XBUFFER (base_buffer)->base_buffer
573 : XBUFFER (base_buffer)); 577 : XBUFFER (base_buffer));
574 578
575 /* Use the base buffer's text object. */ 579 /* Use the base buffer's text object. */
576 b->text = b->base_buffer->text; 580 b->text = b->base_buffer->text;
581 /* We have no own text. */
582 b->indirections = -1;
583 /* Notify base buffer that we share the text now. */
584 b->base_buffer->indirections++;
577 585
578 b->pt = b->base_buffer->pt; 586 b->pt = b->base_buffer->pt;
579 b->begv = b->base_buffer->begv; 587 b->begv = b->base_buffer->begv;
@@ -1439,6 +1447,15 @@ No argument or nil as argument means do this for the current buffer. */)
1439int 1447int
1440compact_buffer (struct buffer *buffer) 1448compact_buffer (struct buffer *buffer)
1441{ 1449{
1450 /* Verify indirection counters. */
1451 if (buffer->base_buffer)
1452 {
1453 eassert (buffer->indirections == -1);
1454 eassert (buffer->base_buffer->indirections > 0);
1455 }
1456 else
1457 eassert (buffer->indirections >= 0);
1458
1442 /* Skip dead buffers, indirect buffers and buffers 1459 /* Skip dead buffers, indirect buffers and buffers
1443 which aren't changed since last compaction. */ 1460 which aren't changed since last compaction. */
1444 if (!NILP (buffer->BUFFER_INTERNAL_FIELD (name)) 1461 if (!NILP (buffer->BUFFER_INTERNAL_FIELD (name))
@@ -1555,10 +1572,19 @@ cleaning up all windows currently displaying the buffer to be killed. */)
1555 if (EQ (buffer, XWINDOW (minibuf_window)->buffer)) 1572 if (EQ (buffer, XWINDOW (minibuf_window)->buffer))
1556 return Qnil; 1573 return Qnil;
1557 1574
1558 /* When we kill a base buffer, kill all its indirect buffers. 1575 /* Notify our base buffer that we don't share the text anymore. */
1576 if (b->base_buffer)
1577 {
1578 eassert (b->indirections == -1);
1579 b->base_buffer->indirections--;
1580 eassert (b->base_buffer->indirections >= 0);
1581 }
1582
1583 /* When we kill an ordinary buffer which shares it's buffer text
1584 with indirect buffer(s), we must kill indirect buffer(s) too.
1559 We do it at this stage so nothing terrible happens if they 1585 We do it at this stage so nothing terrible happens if they
1560 ask questions or their hooks get errors. */ 1586 ask questions or their hooks get errors. */
1561 if (! b->base_buffer) 1587 if (!b->base_buffer && b->indirections > 0)
1562 { 1588 {
1563 struct buffer *other; 1589 struct buffer *other;
1564 1590