|
Packit |
1e8aac |
/*
|
|
Packit |
1e8aac |
* Copyright (C) 2004 Owen Taylor
|
|
Packit |
1e8aac |
*
|
|
Packit |
1e8aac |
* Authors:
|
|
Packit |
1e8aac |
* Owen Taylor <otaylor@redhat.com>
|
|
Packit |
1e8aac |
*
|
|
Packit |
1e8aac |
* Modified by the Glade developers
|
|
Packit |
1e8aac |
*
|
|
Packit |
1e8aac |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
1e8aac |
* it under the terms of the GNU General Public License as
|
|
Packit |
1e8aac |
* published by the Free Software Foundation; either version 2 of the
|
|
Packit |
1e8aac |
* License, or (at your option) any later version.
|
|
Packit |
1e8aac |
*
|
|
Packit |
1e8aac |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
1e8aac |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
1e8aac |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
1e8aac |
* GNU General Public License for more details.
|
|
Packit |
1e8aac |
*
|
|
Packit |
1e8aac |
* You should have received a copy of the GNU General Public License
|
|
Packit |
1e8aac |
* along with this program; if not, write to the Free Software
|
|
Packit |
1e8aac |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
Packit |
1e8aac |
*
|
|
Packit |
1e8aac |
*/
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
#include "config.h"
|
|
Packit |
1e8aac |
#include "glade-id-allocator.h"
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
#include <glib.h>
|
|
Packit |
1e8aac |
#include <string.h>
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
#define INITIAL_WORDS 4
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
struct _GladeIDAllocator
|
|
Packit |
1e8aac |
{
|
|
Packit |
1e8aac |
guint n_words;
|
|
Packit |
1e8aac |
guint32 *data;
|
|
Packit |
1e8aac |
};
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
/**
|
|
Packit |
1e8aac |
* glade_id_allocator_new:
|
|
Packit |
1e8aac |
*
|
|
Packit |
1e8aac |
* Returns: a new #GladeIDAllocator
|
|
Packit |
1e8aac |
*/
|
|
Packit |
1e8aac |
GladeIDAllocator *
|
|
Packit |
1e8aac |
glade_id_allocator_new (void)
|
|
Packit |
1e8aac |
{
|
|
Packit |
1e8aac |
GladeIDAllocator *allocator = g_slice_new (GladeIDAllocator);
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
allocator->n_words = INITIAL_WORDS;
|
|
Packit |
1e8aac |
allocator->data = g_new (guint32, INITIAL_WORDS);
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
memset (allocator->data, 0xff, INITIAL_WORDS * sizeof (guint32));
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
return allocator;
|
|
Packit |
1e8aac |
}
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
/**
|
|
Packit |
1e8aac |
* glade_id_allocator_destroy:
|
|
Packit |
1e8aac |
* @allocator: a #GladeIDAllocator
|
|
Packit |
1e8aac |
*
|
|
Packit |
1e8aac |
* Frees @allocator and its associated memory
|
|
Packit |
1e8aac |
*/
|
|
Packit |
1e8aac |
void
|
|
Packit |
1e8aac |
glade_id_allocator_destroy (GladeIDAllocator *allocator)
|
|
Packit |
1e8aac |
{
|
|
Packit |
1e8aac |
g_return_if_fail (allocator != NULL);
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
g_free (allocator->data);
|
|
Packit |
1e8aac |
g_slice_free (GladeIDAllocator, allocator);
|
|
Packit |
1e8aac |
}
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
static inline gint
|
|
Packit |
1e8aac |
first_set_bit (guint32 word)
|
|
Packit |
1e8aac |
{
|
|
Packit |
1e8aac |
static const char table[16] = {
|
|
Packit |
1e8aac |
4, 0, 1, 0,
|
|
Packit |
1e8aac |
2, 0, 1, 0,
|
|
Packit |
1e8aac |
3, 0, 1, 0,
|
|
Packit |
1e8aac |
2, 0, 1, 0
|
|
Packit |
1e8aac |
};
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
gint result = 0;
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
if ((word & 0xffff) == 0)
|
|
Packit |
1e8aac |
{
|
|
Packit |
1e8aac |
word >>= 16;
|
|
Packit |
1e8aac |
result += 16;
|
|
Packit |
1e8aac |
}
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
if ((word & 0xff) == 0)
|
|
Packit |
1e8aac |
{
|
|
Packit |
1e8aac |
word >>= 8;
|
|
Packit |
1e8aac |
result += 8;
|
|
Packit |
1e8aac |
}
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
if ((word & 0xf) == 0)
|
|
Packit |
1e8aac |
{
|
|
Packit |
1e8aac |
word >>= 4;
|
|
Packit |
1e8aac |
result += 4;
|
|
Packit |
1e8aac |
}
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
return result + table[word & 0xf];
|
|
Packit |
1e8aac |
}
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
/**
|
|
Packit |
1e8aac |
* glade_id_allocator_alloc:
|
|
Packit |
1e8aac |
* @allocator: a #GladeIDAllocator
|
|
Packit |
1e8aac |
*
|
|
Packit |
1e8aac |
* TODO: write me
|
|
Packit |
1e8aac |
* Returns:
|
|
Packit |
1e8aac |
*/
|
|
Packit |
1e8aac |
guint
|
|
Packit |
1e8aac |
glade_id_allocator_allocate (GladeIDAllocator *allocator)
|
|
Packit |
1e8aac |
{
|
|
Packit |
1e8aac |
guint i;
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
g_return_val_if_fail (allocator != NULL, 0);
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
for (i = 0; i < allocator->n_words; i++)
|
|
Packit |
1e8aac |
{
|
|
Packit |
1e8aac |
if (allocator->data[i] != 0)
|
|
Packit |
1e8aac |
{
|
|
Packit |
1e8aac |
gint free_bit = first_set_bit (allocator->data[i]);
|
|
Packit |
1e8aac |
allocator->data[i] &= ~(1 << free_bit);
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
return 32 * i + free_bit + 1;
|
|
Packit |
1e8aac |
}
|
|
Packit |
1e8aac |
}
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
{
|
|
Packit |
1e8aac |
guint n_words = allocator->n_words;
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
allocator->data = g_renew (guint32, allocator->data, n_words * 2);
|
|
Packit |
1e8aac |
memset (&allocator->data[n_words], 0xff, n_words * sizeof (guint32));
|
|
Packit |
1e8aac |
allocator->n_words = n_words * 2;
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
allocator->data[n_words] = 0xffffffff - 1;
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
return 32 * n_words + 1;
|
|
Packit |
1e8aac |
}
|
|
Packit |
1e8aac |
}
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
/**
|
|
Packit |
1e8aac |
* glade_id_allocator_release:
|
|
Packit |
1e8aac |
* @allocator:
|
|
Packit |
1e8aac |
* @id:
|
|
Packit |
1e8aac |
*
|
|
Packit |
1e8aac |
* TODO: write me
|
|
Packit |
1e8aac |
*/
|
|
Packit |
1e8aac |
void
|
|
Packit |
1e8aac |
glade_id_allocator_release (GladeIDAllocator *allocator, guint id)
|
|
Packit |
1e8aac |
{
|
|
Packit |
1e8aac |
guint word_idx;
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
g_return_if_fail (allocator != NULL);
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
/* Allocated ids start with 1 */
|
|
Packit |
1e8aac |
if (id > 0)
|
|
Packit |
1e8aac |
{
|
|
Packit |
1e8aac |
id = id - 1;
|
|
Packit |
1e8aac |
word_idx = id >> 5;
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
/* Tollerate releasing ids that were never allocated with the allocator
|
|
Packit |
1e8aac |
* or are out of range... when we load Glade files with huge numbers it happens
|
|
Packit |
1e8aac |
* that loaded unallocated ids are out of range
|
|
Packit |
1e8aac |
*/
|
|
Packit |
1e8aac |
if (word_idx < allocator->n_words)
|
|
Packit |
1e8aac |
allocator->data[word_idx] |= 1 << (id & 31);
|
|
Packit |
1e8aac |
}
|
|
Packit |
1e8aac |
}
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
#ifdef GLADE_ID_ALLOCATOR_TEST
|
|
Packit |
1e8aac |
int
|
|
Packit |
1e8aac |
main (int argc, char **argv)
|
|
Packit |
1e8aac |
{
|
|
Packit |
1e8aac |
GladeIDAllocator *allocator = glade_id_allocator_new ();
|
|
Packit |
1e8aac |
guint i;
|
|
Packit |
1e8aac |
guint iter;
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
for (i = 0; i < 1000; i++)
|
|
Packit |
1e8aac |
{
|
|
Packit |
1e8aac |
guint id = glade_id_allocator_allocate (allocator);
|
|
Packit |
1e8aac |
g_assert (id == i);
|
|
Packit |
1e8aac |
}
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
for (i = 0; i < 1000; i++)
|
|
Packit |
1e8aac |
glade_id_allocator_release (allocator, i);
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
for (iter = 0; iter < 10000; iter++)
|
|
Packit |
1e8aac |
{
|
|
Packit |
1e8aac |
for (i = 0; i < 1000; i++)
|
|
Packit |
1e8aac |
glade_id_allocator_alloc (allocator);
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
for (i = 0; i < 1000; i++)
|
|
Packit |
1e8aac |
glade_id_allocator_release (allocator, i);
|
|
Packit |
1e8aac |
}
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
glade_id_allocator_destroy (allocator);
|
|
Packit |
1e8aac |
|
|
Packit |
1e8aac |
return 0;
|
|
Packit |
1e8aac |
}
|
|
Packit |
1e8aac |
#endif
|