Ejemplo n.º 1
0
GC
gc_cache_lookup (struct gc_cache *cache, XGCValues *gcv, unsigned long mask)
{
  struct gc_cache_cell *cell, *next, *prev;
  struct gcv_and_mask gcvm;

  if ((!!cache->head) != (!!cache->tail)) abort ();
  if (cache->head && (cache->head->prev || cache->tail->next)) abort ();

  gcvm.mask = mask;
  gcvm.gcv = *gcv;	/* this copies... */

#ifdef GCCACHE_HASH

  if (gethash (&gcvm, cache->table, (void *) &cell))

#else /* !GCCACHE_HASH */

  cell = cache->tail;	/* start at the end (most recently used) */
  while (cell)
    {
      if (gc_cache_eql (&gcvm, &cell->gcvm))
	break;
      else
	cell = cell->prev;
    }

  if (cell)

#endif /* !GCCACHE_HASH */

    {
      /* Found a cell.  Move this cell to the end of the list, so that it
	 will be less likely to be collected than a cell that was accessed
	 less recently.
       */
      if (cell == cache->tail)
	return cell->gc;

      next = cell->next;
      prev = cell->prev;
      if (prev) prev->next = next;
      if (next) next->prev = prev;
      if (cache->head == cell) cache->head = next;
      cell->next = 0;
      cell->prev = cache->tail;
      cache->tail->next = cell;
      cache->tail = cell;
      if (cache->head == cell) abort ();
      if (cell->next) abort ();
      if (cache->head->prev) abort ();
      if (cache->tail->next) abort ();
      return cell->gc;
    }

  /* else, cache miss. */

  if (cache->size == GC_CACHE_SIZE)
    /* Reuse the first cell on the list (least-recently-used.)
       Remove it from the list, and unhash it from the table.
     */
    {
      cell = cache->head;
      cache->head = cell->next;
      cache->head->prev = 0;
      if (cache->tail == cell) cache->tail = 0; /* only one */
      BLOCK_INPUT;
      XFreeGC (cache->dpy, cell->gc);
      cache->delete_count++;
      UNBLOCK_INPUT;
#ifdef GCCACHE_HASH
      remhash (&cell->gcvm, cache->table);
#endif
    }
  else if (cache->size > GC_CACHE_SIZE)
    abort ();
  else
    {
      /* Allocate a new cell (don't put it in the list or table yet.)
       */
      cell = (struct gc_cache_cell *) xmalloc (sizeof (struct gc_cache_cell));
      cache->size++;
    }

  /* Now we've got a cell (new or reused).  Fill it in. */
  memcpy (&cell->gcvm.gcv, gcv, sizeof (XGCValues));
  cell->gcvm.mask = mask;

  /* Put the cell on the end of the list. */
  cell->next = 0;
  cell->prev = cache->tail;
  if (cache->tail) cache->tail->next = cell;
  cache->tail = cell;
  if (! cache->head) cache->head = cell;

  cache->create_count++;
#ifdef GCCACHE_HASH
  /* Hash it in the table */
  puthash (&cell->gcvm, cell, cache->table);
#endif

  /* Now make and return the GC. */
  BLOCK_INPUT;
  cell->gc = XCreateGC (cache->dpy, cache->window, mask, gcv);
  UNBLOCK_INPUT;

  /* debug */
  if (cell->gc != gc_cache_lookup (cache, gcv, mask)) abort ();

  return cell->gc;
}
Ejemplo n.º 2
0
GC gc_cache_lookup(struct gc_cache *cache, XGCValues * gcv, unsigned long mask)
{
	struct gc_cache_cell *cell = NULL, *next = NULL, *prev = NULL;
	struct gcv_and_mask gcvm;

	if (cache == NULL)
		abort();
	else if ((!!cache->head) != (!!cache->tail))
		abort();
	else if (cache->head && cache->tail && (cache->head->prev || cache->tail->next))
		abort();
	else {
		gcvm.mask = mask;
		gcvm.gcv = *gcv;	/* this copies... */

#ifdef GCCACHE_HASH

		if (gethash(&gcvm, cache->table,
			    (const void **)((void*)&cell)))
#else				/* !GCCACHE_HASH */

		/* start at the end (most recently used) */
		cell = cache->tail;
		while (cell) {
			if (gc_cache_eql(&gcvm, &cell->gcvm))
				break;
			else
				cell = cell->prev;
		}

		/* #### This whole file needs some serious overhauling. */
		if (!(mask | GCTile) && cell->gc->values.tile)
			cell = NULL;
		else if (!(mask | GCStipple) && cell->gc->values.stipple)
			cell = NULL;
#endif				/* !GCCACHE_HASH */

		{
			/* Found a cell.  Move this cell to the end of
			   the list, so that it will be less likely to
			   be collected than a cell that was accessed
			   less recently.
			*/

			if (!cell) {
				abort();
				return NULL;
			} else {
				if (cell == cache->tail)
					return cell->gc;
				next = cell->next;
				prev = cell->prev;
				if (prev)
					prev->next = next;
				if (next)
					next->prev = prev;
				if (cache->head == cell)
					cache->head = next;
				cell->next = NULL;
				cell->prev = cache->tail;
				if (cache->tail)
					cache->tail->next = cell;
				else
					abort();
				cache->tail = cell;
				if (cache->head == cell)
					abort();
				else if (cell->next)
					abort();
				else if (cache->head != NULL && cache->head->prev)
					abort();
				else if (cache->tail != NULL && cache->tail->next)
					abort();
				return cell->gc;
			}
		}

		/* else, cache miss. */
		if (cache == NULL)
			abort();
		else if (cache->size == GC_CACHE_SIZE)
			/* Reuse the first cell on the list
			   (least-recently-used).  Remove it from the
			   list, and unhash it from the table.
			*/
		{
			cell = cache->head;
			if (cache->head != NULL) {
				cache->head = cell->next;
				cache->head->prev = 0;
			}
			if (cache->tail == cell)
				cache->tail = 0;	/* only one */
			XFreeGC(cache->dpy, cell->gc);
			cache->delete_count++;
#ifdef GCCACHE_HASH
			remhash(&cell->gcvm, cache->table);
#endif
		} else if (cache->size > GC_CACHE_SIZE)
			abort();
		else {
			/* Allocate a new cell (don't put it in the
			   list or table yet). */
			cell = xnew(struct gc_cache_cell);
			cache->size++;
		}
		if (cell != NULL) {
			/* Now we've got a cell (new or reused).  Fill
			   it in. */
			memcpy(&cell->gcvm.gcv, gcv, sizeof(XGCValues));
			cell->gcvm.mask = mask;

			/* Put the cell on the end of the list. */
			cell->next = 0;
			cell->prev = cache->tail;
			if (cache->tail)
				cache->tail->next = cell;
			cache->tail = cell;
			if (!cache->head)
				cache->head = cell;
			cache->create_count++;
#ifdef GCCACHE_HASH
			/* Hash it in the table */
			puthash(&cell->gcvm, cell, cache->table);
#endif
			/* Now make and return the GC. */
			cell->gc = XCreateGC(cache->dpy, cache->window,
					     mask, gcv);
			/* debug */
			assert(cell->gc == gc_cache_lookup(cache, gcv, mask));
			return cell->gc;
		}
	}
	return NULL; /* No cell determined */
}