/* hazardpointer.c generated by valac 0.56.3, the Vala compiler
 * generated from hazardpointer.vala, do not modify */

/* hazardpointer.vala
 *
 * Copyright (C) 2011  Maciej Piechotka
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.

 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 *
 * Author:
 * 	Maciej Piechotka <uzytkownik2@gmail.com>
 */

#include "gee.h"
#include <glib.h>
#include <glib-object.h>
#include <free.h>
#include <string.h>

typedef struct _GeeHazardPointerNode GeeHazardPointerNode;
typedef struct _GeeHazardPointerFreeNode GeeHazardPointerFreeNode;
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _g_thread_unref0(var) ((var == NULL) ? NULL : (var = (g_thread_unref (var), NULL)))
#define _gee_hazard_pointer_context_free0(var) ((var == NULL) ? NULL : (var = (gee_hazard_pointer_context_free (var), NULL)))
typedef struct _Block10Data Block10Data;
#define _gee_hazard_pointer_free0(var) ((var == NULL) ? NULL : (var = (gee_hazard_pointer_free (var), NULL)))
#define _gee_hazard_pointer_free_node_free0(var) ((var == NULL) ? NULL : (var = (gee_hazard_pointer_free_node_free (var), NULL)))
#define _g_free0(var) ((var == NULL) ? NULL : (var = (g_free (var), NULL)))
#define _gee_hazard_pointer_node_free0(var) ((var == NULL) ? NULL : (var = (gee_hazard_pointer_node_free (var), NULL)))
#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);

struct _Block10Data {
	int _ref_count_;
	GeeCollection* to_free;
};

struct _GeeHazardPointerFreeNode {
	void* pointer;
	GDestroyNotify destroy_notify;
};

struct _GeeHazardPointerNode {
	GeeHazardPointerNode* _next;
	gint _active;
	void* _hazard;
};

VALA_EXTERN gint gee_hazard_pointer__default_policy;
VALA_EXTERN gint gee_hazard_pointer__thread_exit_policy;
VALA_EXTERN GStaticMutex gee_hazard_pointer__queue_mutex;
VALA_EXTERN GeeQueue* gee_hazard_pointer__queue;
VALA_EXTERN GeeArrayList* gee_hazard_pointer__global_to_free;
VALA_EXTERN gint gee_hazard_pointer_release_policy;
VALA_EXTERN GeeHazardPointerNode* gee_hazard_pointer__head;
GeeHazardPointerNode* gee_hazard_pointer__head = NULL;
gint gee_hazard_pointer__default_policy = (gint) GEE_HAZARD_POINTER_POLICY_TRY_FREE;
gint gee_hazard_pointer__thread_exit_policy = (gint) GEE_HAZARD_POINTER_POLICY_RELEASE;
gint gee_hazard_pointer_release_policy = 0;
GeeQueue* gee_hazard_pointer__queue = NULL;
GStaticMutex gee_hazard_pointer__queue_mutex = G_STATIC_MUTEX_INIT;
GeeArrayList* gee_hazard_pointer__global_to_free = NULL;
static guint gee_hazard_pointer_context_THRESHOLD;
VALA_EXTERN GStaticPrivate gee_hazard_pointer_context__current_context;
GStaticPrivate gee_hazard_pointer_context__current_context = G_STATIC_PRIVATE_INIT;
VALA_EXTERN GStaticPrivate gee_hazard_pointer_context__root_context;
GStaticPrivate gee_hazard_pointer_context__root_context = G_STATIC_PRIVATE_INIT;
static guint gee_hazard_pointer_context_THRESHOLD = (guint) 10;

static void gee_hazard_pointer_instance_init (GeeHazardPointer * self);
 G_GNUC_INTERNAL void gee_hazard_pointer_node_free (GeeHazardPointerNode * self);
 G_GNUC_INTERNAL void gee_hazard_pointer_node_release (GeeHazardPointerNode* self);
 G_GNUC_INTERNAL void gee_hazard_pointer_free_node_free (GeeHazardPointerFreeNode * self);
 G_GNUC_INTERNAL gboolean gee_hazard_pointer_policy_perform (GeeHazardPointerPolicy self,
                                            GeeArrayList** to_free);
 G_GNUC_INTERNAL gboolean gee_hazard_pointer_try_free (GeeArrayList* to_free);
 G_GNUC_INTERNAL void gee_hazard_pointer_release_policy_ensure_start (void);
static void gee_hazard_pointer_release_policy_start (GeeHazardPointerReleasePolicy _self_);
static gboolean ___lambda54_ (void);
static inline void gee_hazard_pointer_release_policy_pull_from_queue (GeeCollection* to_free,
                                                        gboolean do_lock);
static gpointer ____lambda54__gthread_func (gpointer self);
static gboolean ___lambda56_ (void);
static void gee_hazard_pointer_release_policy_swap (GType t_type,
                                             GBoxedCopyFunc t_dup_func,
                                             GDestroyNotify t_destroy_func,
                                             gpointer* a,
                                             gpointer* b);
static gboolean ____lambda56__gsource_func (gpointer self);
static Block10Data* block10_data_ref (Block10Data* _data10_);
static void block10_data_unref (void * _userdata_);
static gboolean ___lambda55_ (Block10Data* _data10_,
                       GeeArrayList* x);
static gboolean ____lambda55__gee_forall_func (gpointer g,
                                        gpointer self);
 G_GNUC_INTERNAL GeeHazardPointerNode* gee_hazard_pointer_acquire (void);
 G_GNUC_INTERNAL void gee_hazard_pointer_node_set (GeeHazardPointerNode* self,
                                  void* ptr);
 G_GNUC_INTERNAL GeeHazardPointer* gee_hazard_pointer_new_from_node (GeeHazardPointerNode* node);
 G_GNUC_INTERNAL GeeHazardPointerContext* gee_hazard_pointer_context_get_current_context (void);
 G_GNUC_INTERNAL void gee_hazard_pointer_context_release_ptr (GeeHazardPointerContext* self,
                                             void* ptr,
                                             GDestroyNotify notify);
 G_GNUC_INTERNAL void* gee_hazard_pointer_node_get (GeeHazardPointerNode* self,
                                   gboolean safe);
 G_GNUC_INTERNAL GeeHazardPointerNode* gee_hazard_pointer_get_head (void);
 G_GNUC_INTERNAL GeeHazardPointerNode* gee_hazard_pointer_node_get_next (GeeHazardPointerNode* self);
 G_GNUC_INTERNAL gboolean gee_hazard_pointer_node_activate (GeeHazardPointerNode* self);
 G_GNUC_INTERNAL GeeHazardPointerNode* gee_hazard_pointer_node_new (void);
 G_GNUC_INTERNAL void gee_hazard_pointer_node_set_next (GeeHazardPointerNode* self,
                                       GeeHazardPointerNode* next);
static void gee_hazard_pointer_context_instance_init (GeeHazardPointerContext * self);
static GeeHazardPointerPolicy* _gee_hazard_pointer_policy_dup (GeeHazardPointerPolicy* self);
 G_GNUC_INTERNAL GeeHazardPointerFreeNode* gee_hazard_pointer_free_node_new (void);
static void gee_hazard_pointer_free_node_instance_init (GeeHazardPointerFreeNode * self);
static void gee_hazard_pointer_node_instance_init (GeeHazardPointerNode * self);
 G_GNUC_INTERNAL gboolean gee_hazard_pointer_node_is_active (GeeHazardPointerNode* self);

/**
 * Policy determines what happens on exit from Context.
 */
/**
 * Checks if the policy is concrete or if it depends on global variables.
 *
 * @return ``true`` if this policy does not depend on global variables
 */
gboolean
gee_hazard_pointer_policy_is_concrete (GeeHazardPointerPolicy self)
{
	gboolean result;
	switch (self) {
		case GEE_HAZARD_POINTER_POLICY_DEFAULT:
		case GEE_HAZARD_POINTER_POLICY_THREAD_EXIT:
		{
			result = FALSE;
			return result;
		}
		case GEE_HAZARD_POINTER_POLICY_TRY_FREE:
		case GEE_HAZARD_POINTER_POLICY_FREE:
		case GEE_HAZARD_POINTER_POLICY_TRY_RELEASE:
		case GEE_HAZARD_POINTER_POLICY_RELEASE:
		{
			result = TRUE;
			return result;
		}
		default:
		{
			g_assert_not_reached ();
		}
	}
}

/**
 * Checks if policy blocks or is lock-free.
 * Please note that it works on a concrete policy only.
 *
 * @return ``true`` if the policy may block the thread.
 */
gboolean
gee_hazard_pointer_policy_is_blocking (GeeHazardPointerPolicy self)
{
	gboolean result;
	_vala_return_val_if_fail (gee_hazard_pointer_policy_is_concrete (self), "this.is_concrete ()", FALSE);
	switch (self) {
		case GEE_HAZARD_POINTER_POLICY_TRY_FREE:
		case GEE_HAZARD_POINTER_POLICY_TRY_RELEASE:
		{
			result = FALSE;
			return result;
		}
		case GEE_HAZARD_POINTER_POLICY_FREE:
		case GEE_HAZARD_POINTER_POLICY_RELEASE:
		{
			result = TRUE;
			return result;
		}
		default:
		{
			g_assert_not_reached ();
		}
	}
}

/**
 * Checks if policy guarantees freeing all elements.
 * Please note that it works on a concrete policy only.
 *
 * @return ``true`` if the policy guarantees freeing all elements.
 */
gboolean
gee_hazard_pointer_policy_is_safe (GeeHazardPointerPolicy self)
{
	gboolean result;
	_vala_return_val_if_fail (gee_hazard_pointer_policy_is_concrete (self), "this.is_concrete ()", FALSE);
	switch (self) {
		case GEE_HAZARD_POINTER_POLICY_TRY_FREE:
		case GEE_HAZARD_POINTER_POLICY_TRY_RELEASE:
		{
			result = FALSE;
			return result;
		}
		case GEE_HAZARD_POINTER_POLICY_FREE:
		case GEE_HAZARD_POINTER_POLICY_RELEASE:
		{
			result = TRUE;
			return result;
		}
		default:
		{
			g_assert_not_reached ();
		}
	}
}

/**
 * Finds concrete policy which corresponds to given policy.
 *
 * @return Policy that corresponds to given policy at given time in given thread.
 */
GeeHazardPointerPolicy
gee_hazard_pointer_policy_to_concrete (GeeHazardPointerPolicy self)
{
	GeeHazardPointerPolicy result;
	switch (self) {
		case GEE_HAZARD_POINTER_POLICY_TRY_FREE:
		case GEE_HAZARD_POINTER_POLICY_FREE:
		case GEE_HAZARD_POINTER_POLICY_TRY_RELEASE:
		case GEE_HAZARD_POINTER_POLICY_RELEASE:
		{
			result = self;
			_vala_warn_if_fail (gee_hazard_pointer_policy_is_concrete (result), "result.is_concrete ()");
			return result;
		}
		case GEE_HAZARD_POINTER_POLICY_DEFAULT:
		{
			gint _tmp0_;
			_tmp0_ = g_atomic_int_get ((volatile gint *) (&gee_hazard_pointer__default_policy));
			result = (GeeHazardPointerPolicy) _tmp0_;
			_vala_warn_if_fail (gee_hazard_pointer_policy_is_concrete (result), "result.is_concrete ()");
			return result;
		}
		case GEE_HAZARD_POINTER_POLICY_THREAD_EXIT:
		{
			gint _tmp1_;
			_tmp1_ = g_atomic_int_get ((volatile gint *) (&gee_hazard_pointer__thread_exit_policy));
			result = (GeeHazardPointerPolicy) _tmp1_;
			_vala_warn_if_fail (gee_hazard_pointer_policy_is_concrete (result), "result.is_concrete ()");
			return result;
		}
		default:
		{
			g_assert_not_reached ();
		}
	}
}

/**
 * Runs the policy.
 * @param to_free List containing elements to free.
 * @return Non-empty list of not freed elements or ``null`` if all elements have been disposed.
 */
 G_GNUC_INTERNAL gboolean
gee_hazard_pointer_policy_perform (GeeHazardPointerPolicy self,
                                   GeeArrayList** to_free)
{
	gboolean result;
	g_return_val_if_fail (*to_free != NULL, FALSE);
	switch (gee_hazard_pointer_policy_to_concrete (self)) {
		case GEE_HAZARD_POINTER_POLICY_TRY_FREE:
		{
			result = gee_hazard_pointer_try_free (*to_free);
			return result;
		}
		case GEE_HAZARD_POINTER_POLICY_FREE:
		{
			while (TRUE) {
				if (!gee_hazard_pointer_try_free (*to_free)) {
					break;
				}
				g_thread_yield ();
			}
			break;
		}
		case GEE_HAZARD_POINTER_POLICY_TRY_RELEASE:
		{
			gee_hazard_pointer_release_policy_ensure_start ();
			if (g_static_mutex_trylock (&gee_hazard_pointer__queue_mutex)) {
				GeeQueue* _tmp0_;
				GeeArrayList* _tmp1_;
				GeeArrayList* _tmp2_;
				_tmp0_ = gee_hazard_pointer__queue;
				_tmp1_ = *to_free;
				*to_free = NULL;
				_tmp2_ = _tmp1_;
				gee_queue_offer (_tmp0_, _tmp2_);
				_g_object_unref0 (_tmp2_);
				g_static_mutex_unlock (&gee_hazard_pointer__queue_mutex);
				result = TRUE;
				return result;
			} else {
				result = FALSE;
				return result;
			}
		}
		case GEE_HAZARD_POINTER_POLICY_RELEASE:
		{
			GeeQueue* _tmp3_;
			GeeArrayList* _tmp4_;
			GeeArrayList* _tmp5_;
			gee_hazard_pointer_release_policy_ensure_start ();
			g_static_mutex_lock (&gee_hazard_pointer__queue_mutex);
			_tmp3_ = gee_hazard_pointer__queue;
			_tmp4_ = *to_free;
			*to_free = NULL;
			_tmp5_ = _tmp4_;
			gee_queue_offer (_tmp3_, _tmp5_);
			_g_object_unref0 (_tmp5_);
			g_static_mutex_unlock (&gee_hazard_pointer__queue_mutex);
			result = TRUE;
			return result;
		}
		default:
		{
			g_assert_not_reached ();
		}
	}
	result = FALSE;
	return result;
}

static GType
gee_hazard_pointer_policy_get_type_once (void)
{
	static const GEnumValue values[] = {{GEE_HAZARD_POINTER_POLICY_DEFAULT, "GEE_HAZARD_POINTER_POLICY_DEFAULT", "default"}, {GEE_HAZARD_POINTER_POLICY_THREAD_EXIT, "GEE_HAZARD_POINTER_POLICY_THREAD_EXIT", "thread-exit"}, {GEE_HAZARD_POINTER_POLICY_TRY_FREE, "GEE_HAZARD_POINTER_POLICY_TRY_FREE", "try-free"}, {GEE_HAZARD_POINTER_POLICY_FREE, "GEE_HAZARD_POINTER_POLICY_FREE", "free"}, {GEE_HAZARD_POINTER_POLICY_TRY_RELEASE, "GEE_HAZARD_POINTER_POLICY_TRY_RELEASE", "try-release"}, {GEE_HAZARD_POINTER_POLICY_RELEASE, "GEE_HAZARD_POINTER_POLICY_RELEASE", "release"}, {0, NULL, NULL}};
	GType gee_hazard_pointer_policy_type_id;
	gee_hazard_pointer_policy_type_id = g_enum_register_static ("GeeHazardPointerPolicy", values);
	return gee_hazard_pointer_policy_type_id;
}

GType
gee_hazard_pointer_policy_get_type (void)
{
	static volatile gsize gee_hazard_pointer_policy_type_id__once = 0;
	if (g_once_init_enter (&gee_hazard_pointer_policy_type_id__once)) {
		GType gee_hazard_pointer_policy_type_id;
		gee_hazard_pointer_policy_type_id = gee_hazard_pointer_policy_get_type_once ();
		g_once_init_leave (&gee_hazard_pointer_policy_type_id__once, gee_hazard_pointer_policy_type_id);
	}
	return gee_hazard_pointer_policy_type_id__once;
}

/**
 * Release policy determines what happens with object freed by Policy.TRY_RELEASE
 * and Policy.RELEASE.
 */
static gboolean
___lambda54_ (void)
{
	GeeHazardPointerContext* ctx = NULL;
	GeeHazardPointerPolicy _tmp0_;
	GeeHazardPointerContext* _tmp1_;
	_tmp0_ = GEE_HAZARD_POINTER_POLICY_TRY_FREE;
	_tmp1_ = gee_hazard_pointer_context_new (&_tmp0_);
	ctx = _tmp1_;
	while (TRUE) {
		GeeHazardPointerContext* _tmp2_;
		GeeArrayList* _tmp3_;
		GeeHazardPointerContext* _tmp4_;
		GeeArrayList* _tmp5_;
		gboolean _tmp6_;
		gboolean _tmp7_;
		GeeHazardPointerContext* _tmp8_;
		GeeHazardPointerContext* _tmp9_;
		GeeArrayList* _tmp10_;
		gboolean _tmp11_;
		gboolean _tmp12_;
		g_thread_yield ();
		_tmp2_ = ctx;
		_tmp3_ = _tmp2_->_to_free;
		_tmp4_ = ctx;
		_tmp5_ = _tmp4_->_to_free;
		_tmp6_ = gee_collection_get_is_empty ((GeeCollection*) _tmp5_);
		_tmp7_ = _tmp6_;
		gee_hazard_pointer_release_policy_pull_from_queue ((GeeCollection*) _tmp3_, _tmp7_);
		_tmp8_ = ctx;
		gee_hazard_pointer_context_try_free (_tmp8_);
		_tmp9_ = ctx;
		_tmp10_ = _tmp9_->_to_free;
		_tmp11_ = gee_collection_get_is_empty ((GeeCollection*) _tmp10_);
		_tmp12_ = _tmp11_;
		if (_tmp12_) {
			g_usleep ((gulong) 100000);
		}
	}
}

static gpointer
____lambda54__gthread_func (gpointer self)
{
	gpointer result;
	result = (gpointer) ((gintptr) ___lambda54_ ());
	return result;
}

static gboolean
___lambda56_ (void)
{
	GeeHazardPointerContext* ctx = NULL;
	GeeHazardPointerPolicy _tmp0_;
	GeeHazardPointerContext* _tmp1_;
	GeeArrayList* _tmp2_;
	gboolean result;
	_tmp0_ = GEE_HAZARD_POINTER_POLICY_TRY_FREE;
	_tmp1_ = gee_hazard_pointer_context_new (&_tmp0_);
	ctx = _tmp1_;
	gee_hazard_pointer_release_policy_swap (GEE_TYPE_ARRAY_LIST, (GBoxedCopyFunc) g_object_ref, (GDestroyNotify) g_object_unref, &gee_hazard_pointer__global_to_free, &ctx->_to_free);
	_tmp2_ = ctx->_to_free;
	gee_hazard_pointer_release_policy_pull_from_queue ((GeeCollection*) _tmp2_, FALSE);
	gee_hazard_pointer_context_try_free (ctx);
	gee_hazard_pointer_release_policy_swap (GEE_TYPE_ARRAY_LIST, (GBoxedCopyFunc) g_object_ref, (GDestroyNotify) g_object_unref, &gee_hazard_pointer__global_to_free, &ctx->_to_free);
	result = TRUE;
	_gee_hazard_pointer_context_free0 (ctx);
	return result;
}

static gboolean
____lambda56__gsource_func (gpointer self)
{
	gboolean result;
	result = ___lambda56_ ();
	return result;
}

static void
gee_hazard_pointer_release_policy_start (GeeHazardPointerReleasePolicy _self_)
{
	switch (_self_) {
		case GEE_HAZARD_POINTER_RELEASE_POLICY_HELPER_THREAD:
		{
			GThread* _tmp0_;
			GThread* _tmp1_;
			_tmp0_ = g_thread_new ("<<libgee hazard pointer>>", ____lambda54__gthread_func, NULL);
			_tmp1_ = _tmp0_;
			_g_thread_unref0 (_tmp1_);
			break;
		}
		case GEE_HAZARD_POINTER_RELEASE_POLICY_MAIN_LOOP:
		{
			GeeArrayList* _tmp2_;
			_tmp2_ = gee_array_list_new (G_TYPE_POINTER, NULL, NULL, NULL, NULL, NULL);
			_g_object_unref0 (gee_hazard_pointer__global_to_free);
			gee_hazard_pointer__global_to_free = _tmp2_;
			g_idle_add_full (G_PRIORITY_LOW, ____lambda56__gsource_func, NULL, NULL);
			break;
		}
		default:
		{
			g_assert_not_reached ();
		}
	}
}

static void
gee_hazard_pointer_release_policy_swap (GType t_type,
                                        GBoxedCopyFunc t_dup_func,
                                        GDestroyNotify t_destroy_func,
                                        gpointer* a,
                                        gpointer* b)
{
	gpointer tmp = NULL;
	gpointer _tmp0_;
	gpointer _tmp1_;
	gpointer _tmp2_;
	_tmp0_ = *a;
	*a = NULL;
	tmp = _tmp0_;
	_tmp1_ = *b;
	*b = NULL;
	(((*a) == NULL) || (t_destroy_func == NULL)) ? NULL : (*a = (t_destroy_func (*a), NULL));
	*a = _tmp1_;
	_tmp2_ = tmp;
	tmp = NULL;
	(((*b) == NULL) || (t_destroy_func == NULL)) ? NULL : (*b = (t_destroy_func (*b), NULL));
	*b = _tmp2_;
	((tmp == NULL) || (t_destroy_func == NULL)) ? NULL : (tmp = (t_destroy_func (tmp), NULL));
}

/**
 * Ensures that helper methods are started.
 */
 G_GNUC_INTERNAL inline void
gee_hazard_pointer_release_policy_ensure_start (void)
{
	gint policy = 0;
	gint _tmp0_;
	_tmp0_ = g_atomic_int_get ((volatile gint *) (&gee_hazard_pointer_release_policy));
	policy = _tmp0_;
	if ((policy & (1 << ((sizeof (gint) * 8) - 1))) != 0) {
		return;
	}
	if (g_static_mutex_trylock (&gee_hazard_pointer__queue_mutex)) {
		gint _tmp1_;
		_tmp1_ = g_atomic_int_get ((volatile gint *) (&gee_hazard_pointer_release_policy));
		policy = _tmp1_;
		if ((policy & (1 << ((sizeof (gint) * 8) - 1))) == 0) {
			GeeLinkedList* _tmp2_;
			gint _tmp3_;
			_tmp2_ = gee_linked_list_new (GEE_TYPE_ARRAY_LIST, (GBoxedCopyFunc) g_object_ref, (GDestroyNotify) g_object_unref, NULL, NULL, NULL);
			_g_object_unref0 (gee_hazard_pointer__queue);
			gee_hazard_pointer__queue = (GeeQueue*) _tmp2_;
			_tmp3_ = g_atomic_int_add ((volatile gint *) (&gee_hazard_pointer_release_policy), (gint) (1 << ((sizeof (gint) * 8) - 1)));
			policy = _tmp3_;
			gee_hazard_pointer_release_policy_start ((GeeHazardPointerReleasePolicy) policy);
		}
		g_static_mutex_unlock (&gee_hazard_pointer__queue_mutex);
	}
}

static gpointer
_g_object_ref0 (gpointer self)
{
	return self ? g_object_ref (self) : NULL;
}

static Block10Data*
block10_data_ref (Block10Data* _data10_)
{
	g_atomic_int_inc (&_data10_->_ref_count_);
	return _data10_;
}

static void
block10_data_unref (void * _userdata_)
{
	Block10Data* _data10_;
	_data10_ = (Block10Data*) _userdata_;
	if (g_atomic_int_dec_and_test (&_data10_->_ref_count_)) {
		_g_object_unref0 (_data10_->to_free);
		g_slice_free (Block10Data, _data10_);
	}
}

static gboolean
___lambda55_ (Block10Data* _data10_,
              GeeArrayList* x)
{
	gboolean result;
	g_return_val_if_fail (x != NULL, FALSE);
	gee_collection_add_all (_data10_->to_free, (GeeCollection*) x);
	result = TRUE;
	_g_object_unref0 (x);
	return result;
}

static gboolean
____lambda55__gee_forall_func (gpointer g,
                               gpointer self)
{
	gboolean result;
	result = ___lambda55_ (self, (GeeArrayList*) g);
	return result;
}

static inline void
gee_hazard_pointer_release_policy_pull_from_queue (GeeCollection* to_free,
                                                   gboolean do_lock)
{
	Block10Data* _data10_;
	GeeCollection* _tmp0_;
	gboolean locked = FALSE;
	g_return_if_fail (to_free != NULL);
	_data10_ = g_slice_new0 (Block10Data);
	_data10_->_ref_count_ = 1;
	_tmp0_ = _g_object_ref0 (to_free);
	_g_object_unref0 (_data10_->to_free);
	_data10_->to_free = _tmp0_;
	locked = do_lock;
	if (do_lock) {
		g_static_mutex_lock (&gee_hazard_pointer__queue_mutex);
	} else {
		locked = g_static_mutex_trylock (&gee_hazard_pointer__queue_mutex);
	}
	if (locked) {
		GeeCollection* temp = NULL;
		GeeArrayList* _tmp1_;
		GeeQueue* _tmp2_;
		GeeCollection* _tmp3_;
		GeeCollection* _tmp4_;
		_tmp1_ = gee_array_list_new (GEE_TYPE_ARRAY_LIST, (GBoxedCopyFunc) g_object_ref, (GDestroyNotify) g_object_unref, NULL, NULL, NULL);
		temp = (GeeCollection*) _tmp1_;
		_tmp2_ = gee_hazard_pointer__queue;
		_tmp3_ = temp;
		gee_queue_drain (_tmp2_, _tmp3_, -1);
		g_static_mutex_unlock (&gee_hazard_pointer__queue_mutex);
		_tmp4_ = temp;
		gee_traversable_foreach ((GeeTraversable*) _tmp4_, ____lambda55__gee_forall_func, _data10_);
		_g_object_unref0 (temp);
	}
	block10_data_unref (_data10_);
	_data10_ = NULL;
}

static GType
gee_hazard_pointer_release_policy_get_type_once (void)
{
	static const GEnumValue values[] = {{GEE_HAZARD_POINTER_RELEASE_POLICY_HELPER_THREAD, "GEE_HAZARD_POINTER_RELEASE_POLICY_HELPER_THREAD", "helper-thread"}, {GEE_HAZARD_POINTER_RELEASE_POLICY_MAIN_LOOP, "GEE_HAZARD_POINTER_RELEASE_POLICY_MAIN_LOOP", "main-loop"}, {0, NULL, NULL}};
	GType gee_hazard_pointer_release_policy_type_id;
	gee_hazard_pointer_release_policy_type_id = g_enum_register_static ("GeeHazardPointerReleasePolicy", values);
	return gee_hazard_pointer_release_policy_type_id;
}

GType
gee_hazard_pointer_release_policy_get_type (void)
{
	static volatile gsize gee_hazard_pointer_release_policy_type_id__once = 0;
	if (g_once_init_enter (&gee_hazard_pointer_release_policy_type_id__once)) {
		GType gee_hazard_pointer_release_policy_type_id;
		gee_hazard_pointer_release_policy_type_id = gee_hazard_pointer_release_policy_get_type_once ();
		g_once_init_leave (&gee_hazard_pointer_release_policy_type_id__once, gee_hazard_pointer_release_policy_type_id);
	}
	return gee_hazard_pointer_release_policy_type_id__once;
}

/**
 * Creates a hazard pointer for a pointer.
 *
 * @param ptr Protected pointer
 */
GeeHazardPointer*
gee_hazard_pointer_new (gconstpointer* ptr)
{
	GeeHazardPointer* self;
	GeeHazardPointerNode* _tmp0_;
	GeeHazardPointerNode* _tmp1_;
	self = g_slice_new0 (GeeHazardPointer);
	gee_hazard_pointer_instance_init (self);
	_tmp0_ = gee_hazard_pointer_acquire ();
	self->_node = _tmp0_;
	_tmp1_ = self->_node;
	gee_hazard_pointer_node_set (_tmp1_, (void*) ptr);
	return self;
}

/**
 * Create a hazard pointer from Node.
 */
 G_GNUC_INTERNAL GeeHazardPointer*
gee_hazard_pointer_new_from_node (GeeHazardPointerNode* node)
{
	GeeHazardPointer* self;
	g_return_val_if_fail (node != NULL, NULL);
	self = g_slice_new0 (GeeHazardPointer);
	gee_hazard_pointer_instance_init (self);
	self->_node = node;
	return self;
}

/**
 * Gets hazard pointer from atomic pointer safely.
 *
 * @param aptr Atomic pointer.
 * @param mask Mask of bits.
 * @param mask_out Result of mask.
 * @return Hazard pointer containing the element.
 */
GeeHazardPointer*
gee_hazard_pointer_get_hazard_pointer (GType g_type,
                                       GBoxedCopyFunc g_dup_func,
                                       GDestroyNotify g_destroy_func,
                                       gconstpointer** aptr,
                                       gsize mask,
                                       gsize* mask_out)
{
	gsize _vala_mask_out = 0UL;
	GeeHazardPointerNode* node = NULL;
	GeeHazardPointerNode* _tmp0_;
	void* rptr = NULL;
	void* ptr = NULL;
	void* _tmp9_;
	GeeHazardPointer* result;
	_tmp0_ = gee_hazard_pointer_acquire ();
	node = _tmp0_;
	rptr = NULL;
	ptr = NULL;
	_vala_mask_out = (gsize) 0;
	{
		gboolean _tmp1_ = FALSE;
		_tmp1_ = TRUE;
		while (TRUE) {
			void* _tmp4_;
			void* _tmp5_;
			void* _tmp6_;
			GeeHazardPointerNode* _tmp7_;
			void* _tmp8_;
			if (!_tmp1_) {
				void* _tmp2_;
				void* _tmp3_;
				_tmp2_ = rptr;
				_tmp3_ = g_atomic_pointer_get ((volatile gpointer *) ((void**) aptr));
				if (!(_tmp2_ != _tmp3_)) {
					break;
				}
			}
			_tmp1_ = FALSE;
			_tmp4_ = g_atomic_pointer_get ((volatile gpointer *) ((void**) aptr));
			rptr = _tmp4_;
			_tmp5_ = rptr;
			ptr = (void*) (((gsize) _tmp5_) & (~mask));
			_tmp6_ = rptr;
			_vala_mask_out = ((gsize) _tmp6_) & mask;
			_tmp7_ = node;
			_tmp8_ = ptr;
			gee_hazard_pointer_node_set (_tmp7_, _tmp8_);
		}
	}
	_tmp9_ = ptr;
	if (_tmp9_ != NULL) {
		GeeHazardPointerNode* _tmp10_;
		GeeHazardPointer* _tmp11_;
		_tmp10_ = node;
		_tmp11_ = gee_hazard_pointer_new_from_node (_tmp10_);
		result = _tmp11_;
		if (mask_out) {
			*mask_out = _vala_mask_out;
		}
		return result;
	} else {
		GeeHazardPointerNode* _tmp12_;
		_tmp12_ = node;
		gee_hazard_pointer_node_release (_tmp12_);
		result = NULL;
		if (mask_out) {
			*mask_out = _vala_mask_out;
		}
		return result;
	}
}

/**
 * Copy an object from atomic pointer.
 *
 * @param aptr Atomic pointer.
 * @param mask Mask of flags.
 * @param mask_out Result of mask.
 * @return A copy of object from atomic pointer.
 */
gpointer
gee_hazard_pointer_get_pointer (GType g_type,
                                GBoxedCopyFunc g_dup_func,
                                GDestroyNotify g_destroy_func,
                                gconstpointer** aptr,
                                gsize mask,
                                gsize* mask_out)
{
	gsize _vala_mask_out = 0UL;
	GeeHazardPointerNode* node = NULL;
	GeeHazardPointerNode* _tmp0_;
	void* rptr = NULL;
	void* ptr = NULL;
	gpointer res = NULL;
	void* _tmp9_;
	gpointer _tmp10_;
	GeeHazardPointerNode* _tmp11_;
	gpointer result;
	_tmp0_ = gee_hazard_pointer_acquire ();
	node = _tmp0_;
	rptr = NULL;
	ptr = NULL;
	_vala_mask_out = (gsize) 0;
	{
		gboolean _tmp1_ = FALSE;
		_tmp1_ = TRUE;
		while (TRUE) {
			void* _tmp4_;
			void* _tmp5_;
			void* _tmp6_;
			GeeHazardPointerNode* _tmp7_;
			void* _tmp8_;
			if (!_tmp1_) {
				void* _tmp2_;
				void* _tmp3_;
				_tmp2_ = rptr;
				_tmp3_ = g_atomic_pointer_get ((volatile gpointer *) ((void**) aptr));
				if (!(_tmp2_ != _tmp3_)) {
					break;
				}
			}
			_tmp1_ = FALSE;
			_tmp4_ = g_atomic_pointer_get ((volatile gpointer *) ((void**) aptr));
			rptr = _tmp4_;
			_tmp5_ = rptr;
			ptr = (void*) (((gsize) _tmp5_) & (~mask));
			_tmp6_ = rptr;
			_vala_mask_out = ((gsize) _tmp6_) & mask;
			_tmp7_ = node;
			_tmp8_ = ptr;
			gee_hazard_pointer_node_set (_tmp7_, _tmp8_);
		}
	}
	_tmp9_ = ptr;
	_tmp10_ = ((((gconstpointer*) _tmp9_) != NULL) && (g_dup_func != NULL)) ? g_dup_func ((gpointer) ((gconstpointer*) _tmp9_)) : ((gpointer) ((gconstpointer*) _tmp9_));
	res = _tmp10_;
	_tmp11_ = node;
	gee_hazard_pointer_node_release (_tmp11_);
	result = res;
	if (mask_out) {
		*mask_out = _vala_mask_out;
	}
	return result;
}

/**
 * Exchange objects safely.
 *
 * @param aptr Atomic pointer.
 * @param new_ptr New value
 * @param mask Mask of flags.
 * @param new_mask New mask.
 * @param old_mask Previous mask mask.
 * @return Hazard pointer containing old value.
 */
GeeHazardPointer*
gee_hazard_pointer_exchange_hazard_pointer (GType g_type,
                                            GBoxedCopyFunc g_dup_func,
                                            GDestroyNotify g_destroy_func,
                                            gconstpointer** aptr,
                                            gpointer new_ptr,
                                            gsize mask,
                                            gsize new_mask,
                                            gsize* old_mask)
{
	gsize _vala_old_mask = 0UL;
	GeeHazardPointerNode* new_node = NULL;
	void* new_rptr = NULL;
	gpointer _tmp2_;
	GeeHazardPointerNode* node = NULL;
	GeeHazardPointerNode* _tmp3_;
	void* rptr = NULL;
	void* ptr = NULL;
	GeeHazardPointerNode* _tmp12_;
	void* _tmp14_;
	GeeHazardPointer* result;
	new_node = NULL;
	if (new_ptr != NULL) {
		GeeHazardPointerNode* _tmp0_;
		GeeHazardPointerNode* _tmp1_;
		_tmp0_ = gee_hazard_pointer_acquire ();
		new_node = _tmp0_;
		_tmp1_ = new_node;
		gee_hazard_pointer_node_set (_tmp1_, new_ptr);
	}
	_vala_old_mask = (gsize) 0;
	_tmp2_ = new_ptr;
	new_ptr = NULL;
	new_rptr = (void*) (((gsize) _tmp2_) | (mask & new_mask));
	_tmp3_ = gee_hazard_pointer_acquire ();
	node = _tmp3_;
	rptr = NULL;
	ptr = NULL;
	{
		gboolean _tmp4_ = FALSE;
		_tmp4_ = TRUE;
		while (TRUE) {
			void* _tmp7_;
			void* _tmp8_;
			void* _tmp9_;
			GeeHazardPointerNode* _tmp10_;
			void* _tmp11_;
			if (!_tmp4_) {
				void* _tmp5_;
				void* _tmp6_;
				_tmp5_ = rptr;
				_tmp6_ = new_rptr;
				if (!(!g_atomic_pointer_compare_and_exchange ((volatile gpointer *) ((void**) aptr), _tmp5_, _tmp6_))) {
					break;
				}
			}
			_tmp4_ = FALSE;
			_tmp7_ = g_atomic_pointer_get ((volatile gpointer *) ((void**) aptr));
			rptr = _tmp7_;
			_tmp8_ = rptr;
			ptr = (void*) (((gsize) _tmp8_) & (~mask));
			_tmp9_ = rptr;
			_vala_old_mask = ((gsize) _tmp9_) & mask;
			_tmp10_ = node;
			_tmp11_ = ptr;
			gee_hazard_pointer_node_set (_tmp10_, _tmp11_);
		}
	}
	_tmp12_ = new_node;
	if (_tmp12_ != NULL) {
		GeeHazardPointerNode* _tmp13_;
		_tmp13_ = new_node;
		gee_hazard_pointer_node_release (_tmp13_);
	}
	_tmp14_ = ptr;
	if (_tmp14_ != NULL) {
		GeeHazardPointerNode* _tmp15_;
		GeeHazardPointer* _tmp16_;
		_tmp15_ = node;
		_tmp16_ = gee_hazard_pointer_new_from_node (_tmp15_);
		result = _tmp16_;
		((new_ptr == NULL) || (g_destroy_func == NULL)) ? NULL : (new_ptr = (g_destroy_func (new_ptr), NULL));
		if (old_mask) {
			*old_mask = _vala_old_mask;
		}
		return result;
	} else {
		GeeHazardPointerNode* _tmp17_;
		_tmp17_ = node;
		gee_hazard_pointer_node_release (_tmp17_);
		result = NULL;
		((new_ptr == NULL) || (g_destroy_func == NULL)) ? NULL : (new_ptr = (g_destroy_func (new_ptr), NULL));
		if (old_mask) {
			*old_mask = _vala_old_mask;
		}
		return result;
	}
}

/**
 * Sets object safely
 *
 * @param aptr Atomic pointer.
 * @param new_ptr New value
 * @param mask Mask of flags.
 * @param new_mask New mask.
 */
void
gee_hazard_pointer_set_pointer (GType g_type,
                                GBoxedCopyFunc g_dup_func,
                                GDestroyNotify g_destroy_func,
                                gconstpointer** aptr,
                                gpointer new_ptr,
                                gsize mask,
                                gsize new_mask)
{
	GeeHazardPointer* ptr = NULL;
	gpointer _tmp0_;
	GeeHazardPointer* _tmp1_;
	GeeHazardPointer* _tmp2_;
	_tmp0_ = ((new_ptr != NULL) && (g_dup_func != NULL)) ? g_dup_func ((gpointer) new_ptr) : ((gpointer) new_ptr);
	_tmp1_ = gee_hazard_pointer_exchange_hazard_pointer (g_type, (GBoxedCopyFunc) g_dup_func, (GDestroyNotify) g_destroy_func, aptr, _tmp0_, mask, new_mask, NULL);
	ptr = _tmp1_;
	_tmp2_ = ptr;
	if (_tmp2_ != NULL) {
		GDestroyNotify notify = NULL;
		GDestroyNotify _tmp3_;
		GDestroyNotify _tmp4_;
		_tmp3_ = gee_utils_free_get_destroy_notify (g_type, (GBoxedCopyFunc) g_dup_func, (GDestroyNotify) g_destroy_func);
		notify = _tmp3_;
		_tmp4_ = notify;
		if (_tmp4_ != NULL) {
			GeeHazardPointer* _tmp5_;
			GDestroyNotify _tmp6_;
			_tmp5_ = ptr;
			_tmp6_ = notify;
			notify = NULL;
			gee_hazard_pointer_release (_tmp5_, _tmp6_);
		}
	}
	_gee_hazard_pointer_free0 (ptr);
	((new_ptr == NULL) || (g_destroy_func == NULL)) ? NULL : (new_ptr = (g_destroy_func (new_ptr), NULL));
}

/**
 * Exchange objects safely.
 *
 * @param aptr Atomic pointer.
 * @param new_ptr New value
 * @param mask Mask of flags.
 * @param new_mask New mask.
 * @param old_mask Previous mask mask.
 * @return Value that was previously stored.
 */
gpointer
gee_hazard_pointer_exchange_pointer (GType g_type,
                                     GBoxedCopyFunc g_dup_func,
                                     GDestroyNotify g_destroy_func,
                                     gconstpointer** aptr,
                                     gpointer new_ptr,
                                     gsize mask,
                                     gsize new_mask,
                                     gsize* old_mask)
{
	gsize _vala_old_mask = 0UL;
	GeeHazardPointer* ptr = NULL;
	gpointer _tmp0_;
	gsize _tmp1_ = 0UL;
	GeeHazardPointer* _tmp2_;
	gconstpointer _tmp3_ = NULL;
	GeeHazardPointer* _tmp4_;
	gpointer rptr = NULL;
	gpointer _tmp7_;
	gpointer result;
	_tmp0_ = ((new_ptr != NULL) && (g_dup_func != NULL)) ? g_dup_func ((gpointer) new_ptr) : ((gpointer) new_ptr);
	_tmp2_ = gee_hazard_pointer_exchange_hazard_pointer (g_type, (GBoxedCopyFunc) g_dup_func, (GDestroyNotify) g_destroy_func, aptr, _tmp0_, mask, new_mask, &_tmp1_);
	_vala_old_mask = _tmp1_;
	ptr = _tmp2_;
	_tmp4_ = ptr;
	if (_tmp4_ != NULL) {
		GeeHazardPointer* _tmp5_;
		gconstpointer _tmp6_;
		_tmp5_ = ptr;
		_tmp6_ = gee_hazard_pointer_get (_tmp5_, FALSE);
		_tmp3_ = _tmp6_;
	} else {
		_tmp3_ = NULL;
	}
	_tmp7_ = ((_tmp3_ != NULL) && (g_dup_func != NULL)) ? g_dup_func ((gpointer) _tmp3_) : ((gpointer) _tmp3_);
	rptr = _tmp7_;
	result = rptr;
	_gee_hazard_pointer_free0 (ptr);
	((new_ptr == NULL) || (g_destroy_func == NULL)) ? NULL : (new_ptr = (g_destroy_func (new_ptr), NULL));
	if (old_mask) {
		*old_mask = _vala_old_mask;
	}
	return result;
}

/**
 * Compares and exchanges objects.
 *
 * @param aptr Atomic pointer.
 * @param old_ptr Old pointer.
 * @param _new_ptr New value.
 * @param old_mask Old mask.
 * @param new_mask New mask.
 * @return Value that was previously stored.
 */
gboolean
gee_hazard_pointer_compare_and_exchange_pointer (GType g_type,
                                                 GBoxedCopyFunc g_dup_func,
                                                 GDestroyNotify g_destroy_func,
                                                 gconstpointer** aptr,
                                                 gconstpointer old_ptr,
                                                 gpointer _new_ptr,
                                                 gsize mask,
                                                 gsize old_mask,
                                                 gsize new_mask)
{
	gconstpointer* new_ptr = NULL;
	gpointer _tmp0_;
	void* new_rptr = NULL;
	gconstpointer* _tmp1_;
	void* old_rptr = NULL;
	gboolean success = FALSE;
	void* _tmp2_;
	void* _tmp3_;
	gboolean result;
	_tmp0_ = _new_ptr;
	_new_ptr = NULL;
	new_ptr = _tmp0_;
	_tmp1_ = new_ptr;
	new_rptr = (void*) (((gsize) _tmp1_) | (mask & new_mask));
	old_rptr = (void*) (((gsize) old_ptr) | (mask & old_mask));
	_tmp2_ = old_rptr;
	_tmp3_ = new_rptr;
	success = g_atomic_pointer_compare_and_exchange ((volatile gpointer *) ((void**) aptr), _tmp2_, _tmp3_);
	if (success) {
		GDestroyNotify notify = NULL;
		GDestroyNotify _tmp4_;
		gboolean _tmp5_ = FALSE;
		_tmp4_ = gee_utils_free_get_destroy_notify (g_type, (GBoxedCopyFunc) g_dup_func, (GDestroyNotify) g_destroy_func);
		notify = _tmp4_;
		if (old_ptr != NULL) {
			GDestroyNotify _tmp6_;
			_tmp6_ = notify;
			_tmp5_ = _tmp6_ != NULL;
		} else {
			_tmp5_ = FALSE;
		}
		if (_tmp5_) {
			GeeHazardPointerContext* _tmp7_;
			GDestroyNotify _tmp8_;
			_tmp7_ = gee_hazard_pointer_context_get_current_context ();
			_tmp8_ = notify;
			notify = NULL;
			gee_hazard_pointer_context_release_ptr (_tmp7_, old_ptr, _tmp8_);
		}
	} else {
		gconstpointer* _tmp9_;
		_tmp9_ = new_ptr;
		if (_tmp9_ != NULL) {
			gconstpointer* _tmp10_;
			_tmp10_ = new_ptr;
			new_ptr = NULL;
			((_new_ptr == NULL) || (g_destroy_func == NULL)) ? NULL : (_new_ptr = (g_destroy_func (_new_ptr), NULL));
			_new_ptr = _tmp10_;
		}
	}
	result = success;
	((_new_ptr == NULL) || (g_destroy_func == NULL)) ? NULL : (_new_ptr = (g_destroy_func (_new_ptr), NULL));
	return result;
}

/**
 * Gets the pointer hold by hazard pointer.
 *
 * @param other_thread Have to be set to ``true`` if accessed from thread that did not create this thread.
 * @return The value hold by pointer.
 */
inline gconstpointer
gee_hazard_pointer_get (GeeHazardPointer* self,
                        gboolean other_thread)
{
	GeeHazardPointerNode* _tmp0_;
	void* _tmp1_;
	gconstpointer result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->_node;
	_tmp1_ = gee_hazard_pointer_node_get (_tmp0_, other_thread);
	result = _tmp1_;
	return result;
}

/**
 * Free the pointer.
 *
 * @param notify method freeing object
 */
void
gee_hazard_pointer_release (GeeHazardPointer* self,
                            GDestroyNotify notify)
{
	gconstpointer item = NULL;
	GeeHazardPointerNode* _tmp0_;
	void* _tmp1_;
	GeeHazardPointerNode* _tmp2_;
	gconstpointer _tmp3_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->_node;
	_tmp1_ = gee_hazard_pointer_node_get (_tmp0_, FALSE);
	item = _tmp1_;
	_tmp2_ = self->_node;
	gee_hazard_pointer_node_set (_tmp2_, NULL);
	_tmp3_ = item;
	if (_tmp3_ != NULL) {
		GeeHazardPointerContext* _tmp4_;
		gconstpointer _tmp5_;
		GDestroyNotify _tmp6_;
		_tmp4_ = gee_hazard_pointer_context_get_current_context ();
		_tmp5_ = item;
		_tmp6_ = notify;
		notify = NULL;
		gee_hazard_pointer_context_release_ptr (_tmp4_, _tmp5_, _tmp6_);
	}
}

/**
 * Sets default policy (i.e. default policy for user-created contexts).
 * The policy must be concrete and should not be blocking.
 *
 * @param policy New default policy.
 */
void
gee_hazard_pointer_set_default_policy (GeeHazardPointerPolicy policy)
{
	_vala_return_if_fail (gee_hazard_pointer_policy_is_concrete (policy), "policy.is_concrete ()");
	if (gee_hazard_pointer_policy_is_blocking (policy)) {
		g_warning ("hazardpointer.vala:252: Setting blocking default Gee.HazardPointer.Pol" \
"icy (there may be a deadlock).\n");
	}
	g_atomic_int_set ((volatile gint *) (&gee_hazard_pointer__default_policy), (gint) policy);
}

/**
 * Sets thread exit policy (i.e. default policy for the top-most Context).
 * The policy must be concrete and should not be unsafe.
 *
 * @param policy New thread policy.
 */
void
gee_hazard_pointer_set_thread_exit_policy (GeeHazardPointerPolicy policy)
{
	_vala_return_if_fail (gee_hazard_pointer_policy_is_concrete (policy), "policy.is_concrete ()");
	if (!gee_hazard_pointer_policy_is_safe (policy)) {
		g_warning ("hazardpointer.vala:264: Setting unsafe globale thread-exit Gee.HazardP" \
"ointer.Policy (there may be a memory leak).\n");
	}
	g_atomic_int_set ((volatile gint *) (&gee_hazard_pointer__thread_exit_policy), (gint) policy);
}

/**
 * Sets release (i.e. how exactly the released objects arefreed).
 *
 * The method can be only set before any objects is released and is not thread-safe.
 *
 * @param policy New release policy.
 */
gboolean
gee_hazard_pointer_set_release_policy (GeeHazardPointerReleasePolicy policy)
{
	gint old_policy = 0;
	gint _tmp0_;
	gboolean _tmp1_;
	gboolean result;
	_tmp0_ = g_atomic_int_get ((volatile gint *) (&gee_hazard_pointer_release_policy));
	old_policy = _tmp0_;
	if ((old_policy & ((sizeof (gint) * 8) - 1)) != 0) {
		g_critical ("hazardpointer.vala:278: Attempt to change the policy of running helper" \
". Failing.");
		result = FALSE;
		return result;
	}
	_tmp1_ = g_atomic_int_compare_and_exchange ((volatile gint *) (&gee_hazard_pointer_release_policy), old_policy, (gint) policy);
	if (!_tmp1_) {
		g_critical ("hazardpointer.vala:282: Concurrent access to release policy detected. " \
"Failing.");
		result = FALSE;
		return result;
	}
	result = TRUE;
	return result;
}

/**
 * Gets a new hazard pointer node.
 *
 * @return new hazard pointer node.
 */
 G_GNUC_INTERNAL inline GeeHazardPointerNode*
gee_hazard_pointer_acquire (void)
{
	GeeHazardPointerNode* node = NULL;
	GeeHazardPointerNode* _tmp7_;
	GeeHazardPointerNode* old_head = NULL;
	GeeHazardPointerNode* _tmp14_;
	GeeHazardPointerNode* result;
	{
		GeeHazardPointerNode* curr = NULL;
		GeeHazardPointerNode* _tmp0_;
		_tmp0_ = gee_hazard_pointer_get_head ();
		curr = _tmp0_;
		{
			gboolean _tmp1_ = FALSE;
			_tmp1_ = TRUE;
			while (TRUE) {
				GeeHazardPointerNode* _tmp4_;
				GeeHazardPointerNode* _tmp5_;
				if (!_tmp1_) {
					GeeHazardPointerNode* _tmp2_;
					GeeHazardPointerNode* _tmp3_;
					_tmp2_ = curr;
					_tmp3_ = gee_hazard_pointer_node_get_next (_tmp2_);
					curr = _tmp3_;
				}
				_tmp1_ = FALSE;
				_tmp4_ = curr;
				if (!(_tmp4_ != NULL)) {
					break;
				}
				_tmp5_ = curr;
				if (gee_hazard_pointer_node_activate (_tmp5_)) {
					GeeHazardPointerNode* _tmp6_;
					_tmp6_ = curr;
					result = _tmp6_;
					return result;
				}
			}
		}
	}
	_tmp7_ = gee_hazard_pointer_node_new ();
	node = _tmp7_;
	old_head = NULL;
	{
		gboolean _tmp8_ = FALSE;
		_tmp8_ = TRUE;
		while (TRUE) {
			GeeHazardPointerNode* _tmp11_;
			void* _tmp12_;
			GeeHazardPointerNode* _tmp13_;
			if (!_tmp8_) {
				GeeHazardPointerNode* _tmp9_;
				GeeHazardPointerNode* _tmp10_;
				_tmp9_ = old_head;
				_tmp10_ = node;
				if (!(!g_atomic_pointer_compare_and_exchange ((volatile gpointer *) (&gee_hazard_pointer__head), _tmp9_, _tmp10_))) {
					break;
				}
			}
			_tmp8_ = FALSE;
			_tmp11_ = node;
			_tmp12_ = g_atomic_pointer_get ((volatile gpointer *) (&gee_hazard_pointer__head));
			old_head = (GeeHazardPointerNode*) _tmp12_;
			_tmp13_ = old_head;
			gee_hazard_pointer_node_set_next (_tmp11_, _tmp13_);
		}
	}
	_tmp14_ = node;
	result = _tmp14_;
	return result;
}

/**
 * Tries to free from list.
 *
 * @return ``true`` if list is empty.
 */
 G_GNUC_INTERNAL gboolean
gee_hazard_pointer_try_free (GeeArrayList* to_free)
{
	GeeCollection* used = NULL;
	GeeHashSet* _tmp0_;
	gint _tmp30_;
	gint _tmp31_;
	gboolean result;
	g_return_val_if_fail (to_free != NULL, FALSE);
	_tmp0_ = gee_hash_set_new (G_TYPE_POINTER, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
	used = (GeeCollection*) _tmp0_;
	{
		GeeHazardPointerNode* current = NULL;
		GeeHazardPointerNode* _tmp1_;
		_tmp1_ = gee_hazard_pointer_get_head ();
		current = _tmp1_;
		{
			gboolean _tmp2_ = FALSE;
			_tmp2_ = TRUE;
			while (TRUE) {
				GeeHazardPointerNode* _tmp5_;
				GeeCollection* _tmp6_;
				GeeHazardPointerNode* _tmp7_;
				void* _tmp8_;
				if (!_tmp2_) {
					GeeHazardPointerNode* _tmp3_;
					GeeHazardPointerNode* _tmp4_;
					_tmp3_ = current;
					_tmp4_ = gee_hazard_pointer_node_get_next (_tmp3_);
					current = _tmp4_;
				}
				_tmp2_ = FALSE;
				_tmp5_ = current;
				if (!(_tmp5_ != NULL)) {
					break;
				}
				_tmp6_ = used;
				_tmp7_ = current;
				_tmp8_ = gee_hazard_pointer_node_get (_tmp7_, TRUE);
				gee_collection_add (_tmp6_, _tmp8_);
			}
		}
	}
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp9_ = FALSE;
			_tmp9_ = TRUE;
			while (TRUE) {
				gint _tmp10_;
				gint _tmp11_;
				GeeHazardPointerFreeNode* current = NULL;
				gpointer _tmp12_;
				GeeCollection* _tmp13_;
				GeeHazardPointerFreeNode* _tmp14_;
				void* _tmp15_;
				if (!_tmp9_) {
				}
				_tmp9_ = FALSE;
				_tmp10_ = gee_abstract_collection_get_size ((GeeAbstractCollection*) to_free);
				_tmp11_ = _tmp10_;
				if (!(i < _tmp11_)) {
					break;
				}
				_tmp12_ = gee_abstract_list_get ((GeeAbstractList*) to_free, i);
				current = _tmp12_;
				_tmp13_ = used;
				_tmp14_ = current;
				_tmp15_ = _tmp14_->pointer;
				if (gee_collection_contains (_tmp13_, _tmp15_)) {
					gint _tmp16_;
					_tmp16_ = i;
					i = _tmp16_ + 1;
				} else {
					GeeHazardPointerFreeNode* cur = NULL;
					gint _tmp17_;
					gint _tmp18_;
					gpointer _tmp19_;
					gint _tmp20_;
					gint _tmp21_;
					GeeHazardPointerFreeNode* _tmp25_;
					GDestroyNotify _tmp26_;
					GeeHazardPointerFreeNode* _tmp27_;
					void* _tmp28_;
					GeeHazardPointerFreeNode* _tmp29_;
					_tmp17_ = gee_abstract_collection_get_size ((GeeAbstractCollection*) to_free);
					_tmp18_ = _tmp17_;
					_tmp19_ = gee_abstract_list_remove_at ((GeeAbstractList*) to_free, _tmp18_ - 1);
					cur = _tmp19_;
					_tmp20_ = gee_abstract_collection_get_size ((GeeAbstractCollection*) to_free);
					_tmp21_ = _tmp20_;
					if (i != _tmp21_) {
						GeeHazardPointerFreeNode* temp = NULL;
						gpointer _tmp22_;
						GeeHazardPointerFreeNode* _tmp23_;
						GeeHazardPointerFreeNode* _tmp24_;
						_tmp22_ = gee_abstract_list_get ((GeeAbstractList*) to_free, i);
						temp = _tmp22_;
						_tmp23_ = cur;
						gee_abstract_list_set ((GeeAbstractList*) to_free, i, _tmp23_);
						_tmp24_ = temp;
						cur = _tmp24_;
					}
					_tmp25_ = cur;
					_tmp26_ = _tmp25_->destroy_notify;
					_tmp27_ = cur;
					_tmp28_ = _tmp27_->pointer;
					_tmp26_ (_tmp28_);
					_tmp29_ = cur;
					_gee_hazard_pointer_free_node_free0 (_tmp29_);
				}
			}
		}
	}
	_tmp30_ = gee_abstract_collection_get_size ((GeeAbstractCollection*) to_free);
	_tmp31_ = _tmp30_;
	result = _tmp31_ > 0;
	_g_object_unref0 (used);
	return result;
}

/**
 * Gets head of hazard pointers.
 * @return Hazard pointer head.
 */
 G_GNUC_INTERNAL GeeHazardPointerNode*
gee_hazard_pointer_get_head (void)
{
	void* _tmp0_;
	GeeHazardPointerNode* result;
	_tmp0_ = g_atomic_pointer_get ((volatile gpointer *) (&gee_hazard_pointer__head));
	result = (GeeHazardPointerNode*) _tmp0_;
	return result;
}

static GeeHazardPointerPolicy*
_gee_hazard_pointer_policy_dup (GeeHazardPointerPolicy* self)
{
	GeeHazardPointerPolicy* dup;
	dup = g_new0 (GeeHazardPointerPolicy, 1);
	memcpy (dup, self, sizeof (GeeHazardPointerPolicy));
	return dup;
}

static gpointer
__gee_hazard_pointer_policy_dup0 (gpointer self)
{
	return self ? _gee_hazard_pointer_policy_dup (self) : NULL;
}

GeeHazardPointerContext*
gee_hazard_pointer_context_new (GeeHazardPointerPolicy* policy)
{
	GeeHazardPointerContext* self;
	GeeArrayList* _tmp0_;
	void* _tmp1_;
	self = g_slice_new0 (GeeHazardPointerContext);
	gee_hazard_pointer_context_instance_init (self);
	_tmp0_ = gee_array_list_new (G_TYPE_POINTER, NULL, NULL, NULL, NULL, NULL);
	_g_object_unref0 (self->_to_free);
	self->_to_free = _tmp0_;
	_tmp1_ = g_static_private_get (&gee_hazard_pointer_context__current_context);
	self->_parent = _tmp1_;
	g_static_private_set (&gee_hazard_pointer_context__current_context, self, NULL);
	if (policy == NULL) {
		GeeHazardPointerContext* _tmp2_;
		_tmp2_ = self->_parent;
		if (_tmp2_ == NULL) {
			gint _tmp3_;
			GeeHazardPointerPolicy _tmp4_;
			GeeHazardPointerPolicy* _tmp5_;
			_tmp3_ = g_atomic_int_get ((volatile gint *) (&gee_hazard_pointer__thread_exit_policy));
			_tmp4_ = (GeeHazardPointerPolicy) _tmp3_;
			_tmp5_ = __gee_hazard_pointer_policy_dup0 (&_tmp4_);
			_g_free0 (self->_policy);
			self->_policy = _tmp5_;
		} else {
			gint _tmp6_;
			GeeHazardPointerPolicy _tmp7_;
			GeeHazardPointerPolicy* _tmp8_;
			_tmp6_ = g_atomic_int_get ((volatile gint *) (&gee_hazard_pointer__default_policy));
			_tmp7_ = (GeeHazardPointerPolicy) _tmp6_;
			_tmp8_ = __gee_hazard_pointer_policy_dup0 (&_tmp7_);
			_g_free0 (self->_policy);
			self->_policy = _tmp8_;
		}
	} else {
		GeeHazardPointerPolicy _tmp9_;
		GeeHazardPointerPolicy* _tmp10_;
		_tmp9_ = gee_hazard_pointer_policy_to_concrete (*policy);
		_tmp10_ = __gee_hazard_pointer_policy_dup0 (&_tmp9_);
		_g_free0 (self->_policy);
		self->_policy = _tmp10_;
	}
	return self;
}

/**
 * Tries to free all freed pointer in current context.
 */
void
gee_hazard_pointer_context_try_free (GeeHazardPointerContext* self)
{
	GeeArrayList* _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->_to_free;
	gee_hazard_pointer_try_free (_tmp0_);
}

/**
 * Ensure that whole context is freed. Please note that it might block.
 */
void
gee_hazard_pointer_context_free_all (GeeHazardPointerContext* self)
{
	g_return_if_fail (self != NULL);
	while (TRUE) {
		GeeArrayList* _tmp0_;
		_tmp0_ = self->_to_free;
		if (!gee_hazard_pointer_try_free (_tmp0_)) {
			break;
		}
		g_thread_yield ();
	}
}

/**
 * Tries to push the current context to releaser.
 */
void
gee_hazard_pointer_context_try_release (GeeHazardPointerContext* self)
{
	g_return_if_fail (self != NULL);
	if (g_static_mutex_trylock (&gee_hazard_pointer__queue_mutex)) {
		GeeQueue* _tmp0_;
		GeeArrayList* _tmp1_;
		GeeArrayList* _tmp2_;
		GeeArrayList* _tmp3_;
		_tmp0_ = gee_hazard_pointer__queue;
		_tmp1_ = self->_to_free;
		self->_to_free = NULL;
		_tmp2_ = _tmp1_;
		gee_queue_offer (_tmp0_, _tmp2_);
		_g_object_unref0 (_tmp2_);
		_tmp3_ = gee_array_list_new (G_TYPE_POINTER, NULL, NULL, NULL, NULL, NULL);
		_g_object_unref0 (self->_to_free);
		self->_to_free = _tmp3_;
		g_static_mutex_unlock (&gee_hazard_pointer__queue_mutex);
	}
}

/**
 * Pushes the current context to releaser. Please note that it might block.
 */
void
gee_hazard_pointer_context_release (GeeHazardPointerContext* self)
{
	GeeQueue* _tmp0_;
	GeeArrayList* _tmp1_;
	GeeArrayList* _tmp2_;
	GeeArrayList* _tmp3_;
	g_return_if_fail (self != NULL);
	g_static_mutex_lock (&gee_hazard_pointer__queue_mutex);
	_tmp0_ = gee_hazard_pointer__queue;
	_tmp1_ = self->_to_free;
	self->_to_free = NULL;
	_tmp2_ = _tmp1_;
	gee_queue_offer (_tmp0_, _tmp2_);
	_g_object_unref0 (_tmp2_);
	_tmp3_ = gee_array_list_new (G_TYPE_POINTER, NULL, NULL, NULL, NULL, NULL);
	_g_object_unref0 (self->_to_free);
	self->_to_free = _tmp3_;
	g_static_mutex_unlock (&gee_hazard_pointer__queue_mutex);
}

/**
 * Add pointer to freed array.
 */
 G_GNUC_INTERNAL inline void
gee_hazard_pointer_context_release_ptr (GeeHazardPointerContext* self,
                                        void* ptr,
                                        GDestroyNotify notify)
{
	GeeHazardPointerFreeNode* node = NULL;
	GeeHazardPointerFreeNode* _tmp0_;
	GeeHazardPointerFreeNode* _tmp1_;
	GeeHazardPointerFreeNode* _tmp2_;
	GDestroyNotify _tmp3_;
	GeeArrayList* _tmp4_;
	GeeHazardPointerFreeNode* _tmp5_;
	GeeArrayList* _tmp6_;
	gint _tmp7_;
	gint _tmp8_;
	g_return_if_fail (self != NULL);
	_tmp0_ = gee_hazard_pointer_free_node_new ();
	node = _tmp0_;
	_tmp1_ = node;
	_tmp1_->pointer = ptr;
	_tmp2_ = node;
	_tmp3_ = notify;
	notify = NULL;
	_tmp2_->destroy_notify = _tmp3_;
	_tmp4_ = self->_to_free;
	_tmp5_ = node;
	gee_abstract_collection_add ((GeeAbstractCollection*) _tmp4_, _tmp5_);
	_tmp6_ = self->_to_free;
	_tmp7_ = gee_abstract_collection_get_size ((GeeAbstractCollection*) _tmp6_);
	_tmp8_ = _tmp7_;
	if (((guint) _tmp8_) >= gee_hazard_pointer_context_THRESHOLD) {
		GeeArrayList* _tmp9_;
		_tmp9_ = self->_to_free;
		gee_hazard_pointer_try_free (_tmp9_);
	}
}

/**
 * Gets current context.
 */
 G_GNUC_INTERNAL inline GeeHazardPointerContext*
gee_hazard_pointer_context_get_current_context (void)
{
	void* _tmp0_;
	GeeHazardPointerContext* result;
	_tmp0_ = g_static_private_get (&gee_hazard_pointer_context__current_context);
	result = _tmp0_;
	return result;
}

static void
gee_hazard_pointer_context_instance_init (GeeHazardPointerContext * self)
{
}

void
gee_hazard_pointer_context_free (GeeHazardPointerContext * self)
{
	gint size = 0;
	GeeArrayList* _tmp0_;
	gint _tmp1_;
	gint _tmp2_;
	gboolean clean_parent = FALSE;
	GeeHazardPointerContext* _tmp13_;
	_tmp0_ = self->_to_free;
	_tmp1_ = gee_abstract_collection_get_size ((GeeAbstractCollection*) _tmp0_);
	_tmp2_ = _tmp1_;
	size = _tmp2_;
	clean_parent = FALSE;
	if (size > 0) {
		gboolean _tmp3_ = FALSE;
		GeeHazardPointerContext* _tmp4_;
		_tmp4_ = self->_parent;
		if (_tmp4_ == NULL) {
			_tmp3_ = TRUE;
		} else {
			_tmp3_ = ((guint) size) >= gee_hazard_pointer_context_THRESHOLD;
		}
		if (_tmp3_) {
			GeeHazardPointerPolicy* _tmp5_;
			gboolean _tmp6_;
			_tmp5_ = self->_policy;
			_tmp6_ = gee_hazard_pointer_policy_perform (*_tmp5_, &self->_to_free);
			if (!_tmp6_) {
				gboolean _tmp7_ = FALSE;
				GeeHazardPointerContext* _tmp8_;
				GeeHazardPointerContext* _tmp10_;
				GeeArrayList* _tmp11_;
				GeeArrayList* _tmp12_;
				_tmp8_ = self->_parent;
				if (_tmp8_ != NULL) {
					GeeArrayList* _tmp9_;
					_tmp9_ = self->_to_free;
					_tmp7_ = _tmp9_ != NULL;
				} else {
					_tmp7_ = FALSE;
				}
				_vala_assert (_tmp7_, "_parent != null && _to_free != null");
				_tmp10_ = self->_parent;
				_tmp11_ = _tmp10_->_to_free;
				_tmp12_ = self->_to_free;
				gee_array_list_add_all (_tmp11_, (GeeCollection*) _tmp12_);
				clean_parent = TRUE;
			}
		}
	}
	_tmp13_ = self->_parent;
	g_static_private_set (&gee_hazard_pointer_context__current_context, _tmp13_, NULL);
	if (clean_parent) {
		GeeHazardPointerContext* _tmp14_;
		GeeArrayList* _tmp15_;
		_tmp14_ = self->_parent;
		_tmp15_ = _tmp14_->_to_free;
		gee_hazard_pointer_try_free (_tmp15_);
	}
	_g_object_unref0 (self->_to_free);
	_g_free0 (self->_policy);
	g_slice_free (GeeHazardPointerContext, self);
}

 G_GNUC_INTERNAL GeeHazardPointerFreeNode*
gee_hazard_pointer_free_node_new (void)
{
	GeeHazardPointerFreeNode* self;
	self = g_slice_new0 (GeeHazardPointerFreeNode);
	gee_hazard_pointer_free_node_instance_init (self);
	return self;
}

static void
gee_hazard_pointer_free_node_instance_init (GeeHazardPointerFreeNode * self)
{
}

 G_GNUC_INTERNAL void
gee_hazard_pointer_free_node_free (GeeHazardPointerFreeNode * self)
{
	g_slice_free (GeeHazardPointerFreeNode, self);
}

 G_GNUC_INTERNAL GeeHazardPointerNode*
gee_hazard_pointer_node_new (void)
{
	GeeHazardPointerNode* self;
	self = g_slice_new0 (GeeHazardPointerNode);
	gee_hazard_pointer_node_instance_init (self);
	g_atomic_pointer_set ((volatile gpointer *) (&self->_hazard), NULL);
	g_atomic_int_set ((volatile gint *) (&self->_active), 1);
	return self;
}

 G_GNUC_INTERNAL void
gee_hazard_pointer_node_release (GeeHazardPointerNode* self)
{
	g_return_if_fail (self != NULL);
	g_atomic_pointer_set ((volatile gpointer *) (&self->_hazard), NULL);
	g_atomic_int_set ((volatile gint *) (&self->_active), 0);
}

 G_GNUC_INTERNAL inline gboolean
gee_hazard_pointer_node_is_active (GeeHazardPointerNode* self)
{
	gint _tmp0_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = g_atomic_int_get ((volatile gint *) (&self->_active));
	result = _tmp0_ != 0;
	return result;
}

 G_GNUC_INTERNAL inline gboolean
gee_hazard_pointer_node_activate (GeeHazardPointerNode* self)
{
	gboolean _tmp0_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = g_atomic_int_compare_and_exchange ((volatile gint *) (&self->_active), 0, 1);
	result = _tmp0_;
	return result;
}

 G_GNUC_INTERNAL inline void
gee_hazard_pointer_node_set (GeeHazardPointerNode* self,
                             void* ptr)
{
	g_return_if_fail (self != NULL);
	g_atomic_pointer_set ((volatile gpointer *) (&self->_hazard), ptr);
}

 G_GNUC_INTERNAL inline void*
gee_hazard_pointer_node_get (GeeHazardPointerNode* self,
                             gboolean safe)
{
	void* result;
	g_return_val_if_fail (self != NULL, NULL);
	if (safe) {
		void* _tmp0_;
		_tmp0_ = g_atomic_pointer_get ((volatile gpointer *) (&self->_hazard));
		result = (void*) _tmp0_;
		return result;
	} else {
		void* _tmp1_;
		_tmp1_ = self->_hazard;
		result = (void*) _tmp1_;
		return result;
	}
}

 G_GNUC_INTERNAL inline GeeHazardPointerNode*
gee_hazard_pointer_node_get_next (GeeHazardPointerNode* self)
{
	void* _tmp0_;
	GeeHazardPointerNode* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = g_atomic_pointer_get ((volatile gpointer *) (&self->_next));
	result = (GeeHazardPointerNode*) _tmp0_;
	return result;
}

 G_GNUC_INTERNAL inline void
gee_hazard_pointer_node_set_next (GeeHazardPointerNode* self,
                                  GeeHazardPointerNode* next)
{
	g_return_if_fail (self != NULL);
	g_atomic_pointer_set ((volatile gpointer *) (&self->_next), next);
}

static void
gee_hazard_pointer_node_instance_init (GeeHazardPointerNode * self)
{
}

 G_GNUC_INTERNAL void
gee_hazard_pointer_node_free (GeeHazardPointerNode * self)
{
	GeeHazardPointerNode* _tmp0_;
	_tmp0_ = self->_next;
	_gee_hazard_pointer_node_free0 (_tmp0_);
	g_slice_free (GeeHazardPointerNode, self);
}

static void
gee_hazard_pointer_instance_init (GeeHazardPointer * self)
{
}

void
gee_hazard_pointer_free (GeeHazardPointer * self)
{
	GeeHazardPointerNode* _tmp0_;
	_tmp0_ = self->_node;
	gee_hazard_pointer_node_release (_tmp0_);
	g_slice_free (GeeHazardPointer, self);
}

