예제 #1
0
파일: ghash.c 프로젝트: RRZE-HPC/likwid
void
g_hash_table_foreach (GHashTable *hash_table,
                      GHFunc      func,
                      gpointer    user_data)
{
  gint i;

  for (i = 0; i < hash_table->size; i++)
    {
      guint node_hash = hash_table->hashes[i];
      gpointer node_key = hash_table->keys[i];
      gpointer node_value = hash_table->values[i];

      if (HASH_IS_REAL (node_hash))
        (* func) (node_key, node_value, user_data);

    }
}
예제 #2
0
static bool
hev_hash_table_remove_internal (HevHashTable *self, const void *key, bool notify)
{
	unsigned int node_index;
	unsigned int node_hash;

	if (!self)
	  return false;

	node_index = hev_hash_table_lookup_node (self, key, &node_hash);

	if (!HASH_IS_REAL (self->hashes[node_index]))
	  return false;

	hev_hash_table_remove_node (self, node_index, notify);
	hev_hash_table_maybe_resize (self);

	return true;
}
예제 #3
0
bool
hev_hash_table_lookup_extended (HevHashTable *self, const void *lookup_key, void **orig_key, void **value)
{
	unsigned int node_index;
	unsigned int node_hash;

	if (!self)
	  return false;

	node_index = hev_hash_table_lookup_node (self, lookup_key, &node_hash);

	if (!HASH_IS_REAL (self->hashes[node_index]))
	  return false;

	if (orig_key)
	  *orig_key = self->keys[node_index];
	if (value)
	  *value = self->values[node_index];

	return true;
}
예제 #4
0
/**
 * g_hash_table_find:
 * @hash_table: a #GHashTable.
 * @predicate:  function to test the key/value pairs for a certain property.
 * @user_data:  user data to pass to the function.
 *
 * Calls the given function for key/value pairs in the #GHashTable until
 * @predicate returns %TRUE.  The function is passed the key and value of
 * each pair, and the given @user_data parameter. The hash table may not
 * be modified while iterating over it (you can't add/remove items).
 *
 * Note, that hash tables are really only optimized for forward lookups,
 * i.e. g_hash_table_lookup().
 * So code that frequently issues g_hash_table_find() or
 * g_hash_table_foreach() (e.g. in the order of once per every entry in a
 * hash table) should probably be reworked to use additional or different
 * data structures for reverse lookups (keep in mind that an O(n) find/foreach
 * operation issued for all n values in a hash table ends up needing O(n*n)
 * operations).
 *
 * Return value: The value of the first key/value pair is returned,
 *     for which @predicate evaluates to %TRUE. If no pair with the
 *     requested property is found, %NULL is returned.
 *
 * Since: 2.4
 **/
gpointer
g_hash_table_find (GHashTable *hash_table,
                   GHRFunc     predicate,
                   gpointer    user_data)
{
  gint i;
#ifndef G_DISABLE_ASSERT
  gint version;
#endif
  gboolean match;

  g_return_val_if_fail (hash_table != NULL, NULL);
  g_return_val_if_fail (predicate != NULL, NULL);

#ifndef G_DISABLE_ASSERT
  version = hash_table->version;
#endif

  match = FALSE;

  for (i = 0; i < hash_table->size; i++)
    {
      guint node_hash = hash_table->hashes[i];
      gpointer node_key = hash_table->keys[i];
      gpointer node_value = hash_table->values[i];

      if (HASH_IS_REAL (node_hash))
        match = predicate (node_key, node_value, user_data);

#ifndef G_DISABLE_ASSERT
      g_return_val_if_fail (version == hash_table->version, NULL);
#endif

      if (match)
        return node_value;
    }

  return NULL;
}
예제 #5
0
/*
 * g_hash_table_foreach_remove_or_steal:
 * @hash_table: our #GHashTable
 * @func: the user's callback function
 * @user_data: data for @func
 * @notify: %TRUE if the destroy notify handlers are to be called
 *
 * Implements the common logic for g_hash_table_foreach_remove() and
 * g_hash_table_foreach_steal().
 *
 * Iterates over every node in the table, calling @func with the key
 * and value of the node (and @user_data).  If @func returns %TRUE the
 * node is removed from the table.
 *
 * If @notify is true then the destroy notify handlers will be called
 * for each removed node.
 */
static guint
g_hash_table_foreach_remove_or_steal (GHashTable *hash_table,
                                      GHRFunc     func,
                                      gpointer    user_data,
                                      gboolean    notify)
{
  guint deleted = 0;
  gint i;
#ifndef G_DISABLE_ASSERT
  gint version = hash_table->version;
#endif

  for (i = 0; i < hash_table->size; i++)
    {
      guint node_hash = hash_table->hashes[i];
      gpointer node_key = hash_table->keys[i];
      gpointer node_value = hash_table->values[i];

      if (HASH_IS_REAL (node_hash) &&
          (* func) (node_key, node_value, user_data))
        {
          g_hash_table_remove_node (hash_table, i, notify);
          deleted++;
        }

#ifndef G_DISABLE_ASSERT
      g_return_val_if_fail (version == hash_table->version, 0);
#endif
    }

  g_hash_table_maybe_resize (hash_table);

#ifndef G_DISABLE_ASSERT
  if (deleted > 0)
    hash_table->version++;
#endif

  return deleted;
}
예제 #6
0
static unsigned int
hev_hash_table_foreach_remove_or_steal (HevHashTable *self,
			HevHTRFunc func, void *user_data, bool notify)
{
	unsigned int deleted = 0;
	int i;

	for (i=0; i<self->size; i++) {
		unsigned int node_hash = self->hashes[i];
		void *node_key = self->keys[i];
		void *node_value = self->values[i];

		if (HASH_IS_REAL (node_hash) &&
				(* func) (node_key, node_value, user_data)) {
			hev_hash_table_remove_node (self, i, notify);
			deleted++;
		}
	}

	hev_hash_table_maybe_resize (self);

	return deleted;
}
예제 #7
0
/**
 * Fetch next entry from iterator.
 *
 * @param hxi	the hash table iterator
 * @param vp	where value is written, if non-NULL
 *
 * @return TRUE if a new entry exists, FALSE otherwise.
 */
bool
hikset_iter_next(hikset_iter_t *hxi, void **vp)
{
	const hikset_t *hx;

	hikset_iter_check(hxi);

	hx = hxi->hx;

	while (hxi->pos < hx->kset.size && !HASH_IS_REAL(hx->kset.hashes[hxi->pos]))
		hxi->pos++;

	if (hxi->pos >= hx->kset.size)
		return FALSE;

	if (vp != NULL) {
		void *kptr = deconstify_pointer(hx->kset.keys[hxi->pos]);
		*vp = ptr_add_offset(kptr, -hx->offset);
	}

	hxi->pos++;
	return TRUE;
}
예제 #8
0
/**
 * Traverse table, invoking callback for each entry.
 *
 * @param hx	the hash table
 * @param fn	callback to invoke
 * @param data	additional callback parameter
 */
void
hikset_foreach(const hikset_t *hx, data_fn_t fn, void *data)
{
	unsigned *hp, *end;
	size_t i, n;

	hikset_check(hx);

	end = &hx->kset.hashes[hx->kset.size];
	hash_refcnt_inc(HASH(hx));		/* Prevent any key relocation */

	for (i = n = 0, hp = hx->kset.hashes; hp != end; i++, hp++) {
		if (HASH_IS_REAL(*hp)) {
			void *kptr = deconstify_pointer(hx->kset.keys[i]);
			(*fn)(ptr_add_offset(kptr, -hx->offset), data);
			n++;
		}
	}

	g_assert(n == hx->kset.items);

	hash_refcnt_dec(HASH(hx));
}
예제 #9
0
static void
hev_hash_table_remove_all_nodes (HevHashTable *self, bool notify)
{
	int i = -1;
	void *key = NULL, *value = NULL;

	self->nnodes = 0;
	self->noccupied = 0;

	if (!notify || ((NULL == self->key_destroy_notify) &&
			(NULL == self->value_destroy_notify))) {
		memset (self->hashes, 0, self->size * sizeof (unsigned int));
		memset (self->keys, 0, self->size * sizeof (void *));
		memset (self->values, 0, self->size * sizeof (void *));

		return ;
	}

	for (i=0; i<self->size; i++) {
		if (HASH_IS_REAL (self->hashes[i])) {
			key = self->keys[i];
			value = self->values[i];

			self->hashes[i] = UNUSED_HASH_VALUE;
			self->keys[i] = NULL;
			self->values[i] = NULL;

			if (NULL != self->key_destroy_notify)
			  self->key_destroy_notify (key);

			if (NULL != self->value_destroy_notify)
			  self->value_destroy_notify (value);
		} else if (HASH_IS_TOMBSTONE (self->hashes[i])) {
			self->hashes[i] = UNUSED_HASH_VALUE;
		}
	}
}
예제 #10
0
/**
 * Traverse table, invoking callback for each entry and removing it when
 * the callback function returns TRUE.
 *
 * @param hx	the hash table
 * @param fn	callback to invoke
 * @param data	additional callback parameter
 *
 * @return the number of entries removed from the hash table.
 */
size_t
hikset_foreach_remove(hikset_t *hx, data_rm_fn_t fn, void *data)
{
	unsigned *hp, *end;
	size_t i, n, nr;

	hikset_check(hx);

	end = &hx->kset.hashes[hx->kset.size];
	hash_refcnt_inc(HASH(hx));		/* Prevent any key relocation */

	for (i = n = nr = 0, hp = hx->kset.hashes; hp != end; i++, hp++) {
		if (HASH_IS_REAL(*hp)) {
			void *kptr = deconstify_pointer(hx->kset.keys[i]);
			bool r = (*fn)(ptr_add_offset(kptr, -hx->offset), data);
			n++;
			if (r) {
				nr++;
				hash_keyset_erect_tombstone(&hx->kset, i);
				hx->stamp++;
			}
		}
	}

	g_assert(n == hx->kset.items);
	g_assert(nr <= hx->kset.items);

	hash_refcnt_dec(HASH(hx));

	hx->kset.items -= nr;

	if (nr != 0)
		hash_resize_as_needed(HASH(hx));

	return nr;
}
예제 #11
0
/*
 * g_hash_table_remove_internal:
 * @hash_table: our #GHashTable
 * @key: the key to remove
 * @notify: %TRUE if the destroy notify handlers are to be called
 * Return value: %TRUE if a node was found and removed, else %FALSE
 *
 * Implements the common logic for the g_hash_table_remove() and
 * g_hash_table_steal() functions.
 *
 * Do a lookup of @key and remove it if it is found, calling the
 * destroy notify handlers only if @notify is %TRUE.
 */
static gboolean
g_hash_table_remove_internal (GHashTable    *hash_table,
                              gconstpointer  key,
                              gboolean       notify)
{
  guint node_index;
  guint node_hash;

  g_return_val_if_fail (hash_table != NULL, FALSE);

  node_index = g_hash_table_lookup_node (hash_table, key, &node_hash);

  if (!HASH_IS_REAL (hash_table->hashes[node_index]))
    return FALSE;

  g_hash_table_remove_node (hash_table, node_index, notify);
  g_hash_table_maybe_resize (hash_table);

#ifndef G_DISABLE_ASSERT
  hash_table->version++;
#endif

  return TRUE;
}
예제 #12
0
/**
 * g_hash_table_lookup_extended:
 * @hash_table: a #GHashTable
 * @lookup_key: the key to look up
 * @orig_key: return location for the original key, or %NULL
 * @value: return location for the value associated with the key, or %NULL
 *
 * Looks up a key in the #GHashTable, returning the original key and the
 * associated value and a #gboolean which is %TRUE if the key was found. This
 * is useful if you need to free the memory allocated for the original key,
 * for example before calling g_hash_table_remove().
 *
 * You can actually pass %NULL for @lookup_key to test
 * whether the %NULL key exists, provided the hash and equal functions
 * of @hash_table are %NULL-safe.
 *
 * Return value: %TRUE if the key was found in the #GHashTable.
 **/
gboolean
g_hash_table_lookup_extended (GHashTable    *hash_table,
                              gconstpointer  lookup_key,
                              gpointer      *orig_key,
                              gpointer      *value)
{
  guint node_index;
  guint node_hash;

  g_return_val_if_fail (hash_table != NULL, FALSE);

  node_index = g_hash_table_lookup_node (hash_table, lookup_key, &node_hash);

  if (!HASH_IS_REAL (hash_table->hashes[node_index]))
    return FALSE;

  if (orig_key)
    *orig_key = hash_table->keys[node_index];

  if (value)
    *value = hash_table->values[node_index];

  return TRUE;
}
예제 #13
0
파일: ghash.c 프로젝트: RRZE-HPC/likwid
static gboolean
g_hash_table_insert_node (GHashTable *hash_table,
                          guint       node_index,
                          guint       key_hash,
                          gpointer    new_key,
                          gpointer    new_value,
                          gboolean    keep_new_key,
                          gboolean    reusing_key)
{
  gboolean already_exists;
  guint old_hash;
  gpointer key_to_free = NULL;
  gpointer value_to_free = NULL;

  old_hash = hash_table->hashes[node_index];
  already_exists = HASH_IS_REAL (old_hash);

  if (already_exists)
    {
      value_to_free = hash_table->values[node_index];

      if (keep_new_key)
        {
          key_to_free = hash_table->keys[node_index];
          hash_table->keys[node_index] = new_key;
        }
      else
        key_to_free = new_key;
    }
  else
    {
      hash_table->hashes[node_index] = key_hash;
      hash_table->keys[node_index] = new_key;
    }

  if (G_UNLIKELY (hash_table->keys == hash_table->values && hash_table->keys[node_index] != new_value))
    hash_table->values = g_memdup (hash_table->keys, sizeof (gpointer) * hash_table->size);

  hash_table->values[node_index] = new_value;

  if (!already_exists)
    {
      hash_table->nnodes++;

      if (HASH_IS_UNUSED (old_hash))
        {
          hash_table->noccupied++;
          g_hash_table_maybe_resize (hash_table);
        }

    }

  if (already_exists)
    {
      if (hash_table->key_destroy_func && !reusing_key)
        (* hash_table->key_destroy_func) (key_to_free);
      if (hash_table->value_destroy_func)
        (* hash_table->value_destroy_func) (value_to_free);
    }

  return !already_exists;
}
예제 #14
0
static bool
hev_hash_table_insert_node (HevHashTable *self, unsigned int node_index,
			unsigned int key_hash, void *new_key, void *new_value,
			bool keep_new_key, bool reusing_key)
{
	bool already_exists;
	unsigned int old_hash;
	void *key_to_free = NULL;
	void *value_to_free = NULL;

	old_hash = self->hashes[node_index];
	already_exists = HASH_IS_REAL (old_hash);

	/* Proceed in three steps.  First, deal with the key because it is the
	* most complicated.  Then consider if we need to split the table in
	* two (because writing the value will result in the set invariant
	* becoming broken).  Then deal with the value.
	*
	* There are three cases for the key:
	*
	*  - entry already exists in table, reusing key:
	*    free the just-passed-in new_key and use the existing value
	*
	*  - entry already exists in table, not reusing key:
	*    free the entry in the table, use the new key
	*
	*  - entry not already in table:
	*    use the new key, free nothing
	*
	* We update the hash at the same time...
	*/
	if (already_exists) {
		/* Note: we must record the old value before writing the new key
		* because we might change the value in the event that the two
		* arrays are shared.
		*/
		value_to_free = self->values[node_index];

		if (keep_new_key) {
			key_to_free = self->keys[node_index];
			self->keys[node_index] = new_key;
		} else {
			key_to_free = new_key;
		}
	} else {
		self->hashes[node_index] = key_hash;
		self->keys[node_index] = new_key;
	}

	/* Step two: check if the value that we are about to write to the
	* table is the same as the key in the same position.  If it's not,
	* split the table.
	*/
	if (self->keys == self->values && self->keys[node_index] != new_value)
	  self->values = memdup (self->keys, sizeof (void *) * self->size);

	/* Step 3: Actually do the write */
	self->values[node_index] = new_value;

	/* Now, the bookkeeping... */
	if (!already_exists) {
		self->nnodes++;

		if (HASH_IS_UNUSED (old_hash)) {
		/* We replaced an empty node, and not a tombstone */
			self->noccupied++;
			hev_hash_table_maybe_resize (self);
		}
	}

	if (already_exists) {
		if (self->key_destroy_notify && !reusing_key)
		  (* self->key_destroy_notify) (key_to_free);
		if (self->value_destroy_notify)
		  (* self->value_destroy_notify) (value_to_free);
	}

	return !already_exists;
}