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

/* Copyright 2016 Software Freedom Conservancy Inc.
 *
 * This software is licensed under the GNU Lesser General Public License
 * (version 2.1 or later).  See the COPYING file in this distribution.
 */

#include "geary-engine.h"
#include <glib.h>
#include <glib-object.h>
#include <stdlib.h>
#include <string.h>
#include <gio/gio.h>

#define GEARY_NONBLOCKING_CONCURRENT_TYPE_CONCURRENT_OPERATION (geary_nonblocking_concurrent_concurrent_operation_get_type ())
#define GEARY_NONBLOCKING_CONCURRENT_CONCURRENT_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEARY_NONBLOCKING_CONCURRENT_TYPE_CONCURRENT_OPERATION, GearyNonblockingConcurrentConcurrentOperation))
#define GEARY_NONBLOCKING_CONCURRENT_CONCURRENT_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEARY_NONBLOCKING_CONCURRENT_TYPE_CONCURRENT_OPERATION, GearyNonblockingConcurrentConcurrentOperationClass))
#define GEARY_NONBLOCKING_CONCURRENT_IS_CONCURRENT_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEARY_NONBLOCKING_CONCURRENT_TYPE_CONCURRENT_OPERATION))
#define GEARY_NONBLOCKING_CONCURRENT_IS_CONCURRENT_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEARY_NONBLOCKING_CONCURRENT_TYPE_CONCURRENT_OPERATION))
#define GEARY_NONBLOCKING_CONCURRENT_CONCURRENT_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEARY_NONBLOCKING_CONCURRENT_TYPE_CONCURRENT_OPERATION, GearyNonblockingConcurrentConcurrentOperationClass))

typedef struct _GearyNonblockingConcurrentConcurrentOperation GearyNonblockingConcurrentConcurrentOperation;
typedef struct _GearyNonblockingConcurrentConcurrentOperationClass GearyNonblockingConcurrentConcurrentOperationClass;
enum  {
	GEARY_NONBLOCKING_CONCURRENT_0_PROPERTY,
	GEARY_NONBLOCKING_CONCURRENT_NUM_PROPERTIES
};
static GParamSpec* geary_nonblocking_concurrent_properties[GEARY_NONBLOCKING_CONCURRENT_NUM_PROPERTIES];
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _g_thread_pool_free0(var) ((var == NULL) ? NULL : (var = (g_thread_pool_free (var, FALSE, TRUE), NULL)))
#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL)))
typedef struct _GearyNonblockingConcurrentScheduleAsyncData GearyNonblockingConcurrentScheduleAsyncData;
typedef struct _GearyNonblockingConcurrentConcurrentOperationPrivate GearyNonblockingConcurrentConcurrentOperationPrivate;
enum  {
	GEARY_NONBLOCKING_CONCURRENT_CONCURRENT_OPERATION_0_PROPERTY,
	GEARY_NONBLOCKING_CONCURRENT_CONCURRENT_OPERATION_NUM_PROPERTIES
};
static GParamSpec* geary_nonblocking_concurrent_concurrent_operation_properties[GEARY_NONBLOCKING_CONCURRENT_CONCURRENT_OPERATION_NUM_PROPERTIES];
typedef struct _GearyNonblockingConcurrentConcurrentOperationWaitAsyncData GearyNonblockingConcurrentConcurrentOperationWaitAsyncData;

struct _GearyNonblockingConcurrentPrivate {
	GThreadPool* thread_pool;
	GError* init_err;
};

struct _GearyNonblockingConcurrentScheduleAsyncData {
	int _state_;
	GObject* _source_object_;
	GAsyncResult* _res_;
	GTask* _async_result;
	GearyNonblockingConcurrent* self;
	GearyNonblockingConcurrentConcurrentCallback cb;
	gpointer cb_target;
	GCancellable* cancellable;
	GError* _tmp0_;
	GError* _tmp1_;
	GError* _tmp2_;
	GearyNonblockingConcurrentConcurrentOperation* op;
	GearyNonblockingConcurrentConcurrentOperation* _tmp3_;
	GThreadPool* _tmp4_;
	GearyNonblockingConcurrentConcurrentOperation* _tmp5_;
	GearyNonblockingConcurrentConcurrentOperation* _tmp6_;
	GearyNonblockingConcurrentConcurrentOperation* _tmp7_;
	GError* _inner_error0_;
};

struct _GearyNonblockingConcurrentConcurrentOperation {
	GearyBaseObject parent_instance;
	GearyNonblockingConcurrentConcurrentOperationPrivate * priv;
};

struct _GearyNonblockingConcurrentConcurrentOperationClass {
	GearyBaseObjectClass parent_class;
};

struct _GearyNonblockingConcurrentConcurrentOperationPrivate {
	GearyNonblockingConcurrentConcurrentCallback cb;
	gpointer cb_target;
	GCancellable* cancellable;
	GError* caught_err;
	GearyNonblockingEvent* event;
};

struct _GearyNonblockingConcurrentConcurrentOperationWaitAsyncData {
	int _state_;
	GObject* _source_object_;
	GAsyncResult* _res_;
	GTask* _async_result;
	GearyNonblockingConcurrentConcurrentOperation* self;
	GearyNonblockingEvent* _tmp0_;
	GError* _tmp1_;
	GError* _tmp2_;
	GError* _tmp3_;
	gboolean _tmp4_;
	GCancellable* _tmp5_;
	GCancellable* _tmp6_;
	GError* _tmp7_;
	GError* _inner_error0_;
};

static gint GearyNonblockingConcurrent_private_offset;
static gpointer geary_nonblocking_concurrent_parent_class = NULL;
static GearyNonblockingConcurrent* geary_nonblocking_concurrent__global;
static GearyNonblockingConcurrent* geary_nonblocking_concurrent__global = NULL;
static gint GearyNonblockingConcurrentConcurrentOperation_private_offset;
static gpointer geary_nonblocking_concurrent_concurrent_operation_parent_class = NULL;

static GType geary_nonblocking_concurrent_concurrent_operation_get_type (void) G_GNUC_CONST  G_GNUC_UNUSED ;
static void geary_nonblocking_concurrent_on_work_ready (GearyNonblockingConcurrent* self,
                                                 GearyNonblockingConcurrentConcurrentOperation* op);
static void _geary_nonblocking_concurrent_on_work_ready_gfunc (gpointer data,
                                                        gpointer self);
static void geary_nonblocking_concurrent_schedule_async_data_free (gpointer _data);
static gboolean geary_nonblocking_concurrent_schedule_async_co (GearyNonblockingConcurrentScheduleAsyncData* _data_);
static GearyNonblockingConcurrentConcurrentOperation* geary_nonblocking_concurrent_concurrent_operation_new (GearyNonblockingConcurrentConcurrentCallback cb,
                                                                                                      gpointer cb_target,
                                                                                                      GCancellable* cancellable);
static GearyNonblockingConcurrentConcurrentOperation* geary_nonblocking_concurrent_concurrent_operation_construct (GType object_type,
                                                                                                            GearyNonblockingConcurrentConcurrentCallback cb,
                                                                                                            gpointer cb_target,
                                                                                                            GCancellable* cancellable);
static void geary_nonblocking_concurrent_concurrent_operation_wait_async (GearyNonblockingConcurrentConcurrentOperation* self,
                                                                   GAsyncReadyCallback _callback_,
                                                                   gpointer _user_data_);
static void geary_nonblocking_concurrent_concurrent_operation_wait_finish (GearyNonblockingConcurrentConcurrentOperation* self,
                                                                    GAsyncResult* _res_,
                                                                    GError** error);
static void geary_nonblocking_concurrent_schedule_async_ready (GObject* source_object,
                                                        GAsyncResult* _res_,
                                                        gpointer _user_data_);
static void geary_nonblocking_concurrent_concurrent_operation_execute (GearyNonblockingConcurrentConcurrentOperation* self);
static void geary_nonblocking_concurrent_concurrent_operation_wait_async_data_free (gpointer _data);
static gboolean geary_nonblocking_concurrent_concurrent_operation_wait_async_co (GearyNonblockingConcurrentConcurrentOperationWaitAsyncData* _data_);
static void geary_nonblocking_concurrent_concurrent_operation_wait_async_ready (GObject* source_object,
                                                                         GAsyncResult* _res_,
                                                                         gpointer _user_data_);
static gboolean geary_nonblocking_concurrent_concurrent_operation_on_notify_completed (GearyNonblockingConcurrentConcurrentOperation* self);
static gboolean _geary_nonblocking_concurrent_concurrent_operation_on_notify_completed_gsource_func (gpointer self);
static void geary_nonblocking_concurrent_concurrent_operation_finalize (GObject * obj);
static GType geary_nonblocking_concurrent_concurrent_operation_get_type_once (void);
static void geary_nonblocking_concurrent_finalize (GObject * obj);
static GType geary_nonblocking_concurrent_get_type_once (void);
static void _vala_geary_nonblocking_concurrent_get_property (GObject * object,
                                                      guint property_id,
                                                      GValue * value,
                                                      GParamSpec * pspec);

static inline gpointer
geary_nonblocking_concurrent_get_instance_private (GearyNonblockingConcurrent* self)
{
	return G_STRUCT_MEMBER_P (self, GearyNonblockingConcurrent_private_offset);
}

GearyNonblockingConcurrent*
geary_nonblocking_concurrent_get_global (void)
{
	GearyNonblockingConcurrent* result;
	GearyNonblockingConcurrent* _tmp0_ = NULL;
	GearyNonblockingConcurrent* _tmp1_;
	_tmp1_ = geary_nonblocking_concurrent__global;
	if (_tmp1_ != NULL) {
		GearyNonblockingConcurrent* _tmp2_;
		_tmp2_ = geary_nonblocking_concurrent__global;
		_tmp0_ = _tmp2_;
	} else {
		GearyNonblockingConcurrent* _tmp3_;
		GearyNonblockingConcurrent* _tmp4_;
		_tmp3_ = geary_nonblocking_concurrent_new (GEARY_NONBLOCKING_CONCURRENT_DEFAULT_MAX_THREADS);
		_g_object_unref0 (geary_nonblocking_concurrent__global);
		geary_nonblocking_concurrent__global = _tmp3_;
		_tmp4_ = geary_nonblocking_concurrent__global;
		_tmp0_ = _tmp4_;
	}
	result = _tmp0_;
	return result;
}

/**
     * Creates a new Concurrent pool for scheduling background work.
     *
     * A caller may create their own pool, or they may use the default one available with
     * {link instance}.
     */
static void
_geary_nonblocking_concurrent_on_work_ready_gfunc (gpointer data,
                                                   gpointer self)
{
	geary_nonblocking_concurrent_on_work_ready ((GearyNonblockingConcurrent*) self, (GearyNonblockingConcurrentConcurrentOperation*) data);
}

static gpointer
_g_error_copy0 (gpointer self)
{
	return self ? g_error_copy (self) : NULL;
}

GearyNonblockingConcurrent*
geary_nonblocking_concurrent_construct (GType object_type,
                                        gint max_threads)
{
	GearyNonblockingConcurrent * self = NULL;
	GError* _inner_error0_ = NULL;
	self = (GearyNonblockingConcurrent*) geary_base_object_construct (object_type);
	{
		GThreadPool* _tmp0_ = NULL;
		GThreadPool* _tmp1_;
		GThreadPool* _tmp2_;
		_tmp1_ = g_thread_pool_new (_geary_nonblocking_concurrent_on_work_ready_gfunc, self, max_threads, FALSE, &_inner_error0_);
		_tmp0_ = _tmp1_;
		if (G_UNLIKELY (_inner_error0_ != NULL)) {
			if (_inner_error0_->domain == G_THREAD_ERROR) {
				goto __catch0_g_thread_error;
			}
			g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return NULL;
		}
		_tmp2_ = _tmp0_;
		_tmp0_ = NULL;
		_g_thread_pool_free0 (self->priv->thread_pool);
		self->priv->thread_pool = _tmp2_;
		_g_thread_pool_free0 (_tmp0_);
	}
	goto __finally0;
	__catch0_g_thread_error:
	{
		GError* err = NULL;
		GError* _tmp3_;
		GError* _tmp4_;
		GError* _tmp5_;
		const gchar* _tmp6_;
		err = _inner_error0_;
		_inner_error0_ = NULL;
		_tmp3_ = err;
		_tmp4_ = _g_error_copy0 (_tmp3_);
		_g_error_free0 (self->priv->init_err);
		self->priv->init_err = _tmp4_;
		_tmp5_ = err;
		_tmp6_ = _tmp5_->message;
		g_warning ("nonblocking-concurrent.vala:115: Unable to create Geary.Nonblocking.Co" \
"ncurrent: %s", _tmp6_);
		_g_error_free0 (err);
	}
	__finally0:
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
		g_clear_error (&_inner_error0_);
		return NULL;
	}
	return self;
}

GearyNonblockingConcurrent*
geary_nonblocking_concurrent_new (gint max_threads)
{
	return geary_nonblocking_concurrent_construct (GEARY_NONBLOCKING_TYPE_CONCURRENT, max_threads);
}

static void
geary_nonblocking_concurrent_schedule_async_data_free (gpointer _data)
{
	GearyNonblockingConcurrentScheduleAsyncData* _data_;
	_data_ = _data;
	_g_object_unref0 (_data_->cancellable);
	_g_object_unref0 (_data_->self);
	g_slice_free (GearyNonblockingConcurrentScheduleAsyncData, _data_);
}

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

void
geary_nonblocking_concurrent_schedule_async (GearyNonblockingConcurrent* self,
                                             GearyNonblockingConcurrentConcurrentCallback cb,
                                             gpointer cb_target,
                                             GCancellable* cancellable,
                                             GAsyncReadyCallback _callback_,
                                             gpointer _user_data_)
{
	GearyNonblockingConcurrentScheduleAsyncData* _data_;
	GearyNonblockingConcurrent* _tmp0_;
	GCancellable* _tmp1_;
	g_return_if_fail (GEARY_NONBLOCKING_IS_CONCURRENT (self));
	g_return_if_fail ((cancellable == NULL) || G_TYPE_CHECK_INSTANCE_TYPE (cancellable, g_cancellable_get_type ()));
	_data_ = g_slice_new0 (GearyNonblockingConcurrentScheduleAsyncData);
	_data_->_async_result = g_task_new (G_OBJECT (self), cancellable, _callback_, _user_data_);
	g_task_set_task_data (_data_->_async_result, _data_, geary_nonblocking_concurrent_schedule_async_data_free);
	_tmp0_ = _g_object_ref0 (self);
	_data_->self = _tmp0_;
	_data_->cb = cb;
	_data_->cb_target = cb_target;
	_tmp1_ = _g_object_ref0 (cancellable);
	_g_object_unref0 (_data_->cancellable);
	_data_->cancellable = _tmp1_;
	geary_nonblocking_concurrent_schedule_async_co (_data_);
}

void
geary_nonblocking_concurrent_schedule_finish (GearyNonblockingConcurrent* self,
                                              GAsyncResult* _res_,
                                              GError** error)
{
	GearyNonblockingConcurrentScheduleAsyncData* _data_;
	_data_ = g_task_propagate_pointer (G_TASK (_res_), error);
	if (NULL == _data_) {
		return;
	}
}

/**
     * Schedule a callback to be invoked in a background thread.
     *
     * The caller should take care that the callback's state is available until
     * {@link schedule_async} completes.
     *
     * This method is thread-safe.
     */
static void
geary_nonblocking_concurrent_schedule_async_ready (GObject* source_object,
                                                   GAsyncResult* _res_,
                                                   gpointer _user_data_)
{
	GearyNonblockingConcurrentScheduleAsyncData* _data_;
	_data_ = _user_data_;
	_data_->_source_object_ = source_object;
	_data_->_res_ = _res_;
	geary_nonblocking_concurrent_schedule_async_co (_data_);
}

static gboolean
geary_nonblocking_concurrent_schedule_async_co (GearyNonblockingConcurrentScheduleAsyncData* _data_)
{
	switch (_data_->_state_) {
		case 0:
		goto _state_0;
		case 1:
		goto _state_1;
		default:
		g_assert_not_reached ();
	}
	_state_0:
	_data_->_tmp0_ = _data_->self->priv->init_err;
	if (_data_->_tmp0_ != NULL) {
		_data_->_tmp1_ = _data_->self->priv->init_err;
		_data_->_tmp2_ = _g_error_copy0 (_data_->_tmp1_);
		_data_->_inner_error0_ = _data_->_tmp2_;
		g_task_return_error (_data_->_async_result, _data_->_inner_error0_);
		g_object_unref (_data_->_async_result);
		return FALSE;
	}
	_data_->_tmp3_ = geary_nonblocking_concurrent_concurrent_operation_new (_data_->cb, _data_->cb_target, _data_->cancellable);
	_data_->op = _data_->_tmp3_;
	_data_->_tmp4_ = _data_->self->priv->thread_pool;
	_data_->_tmp5_ = _data_->op;
	_data_->_tmp6_ = _g_object_ref0 (_data_->_tmp5_);
	g_thread_pool_push (_data_->_tmp4_, _data_->_tmp6_, &_data_->_inner_error0_);
	if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
		g_task_return_error (_data_->_async_result, _data_->_inner_error0_);
		_g_object_unref0 (_data_->op);
		g_object_unref (_data_->_async_result);
		return FALSE;
	}
	_data_->_tmp7_ = _data_->op;
	_data_->_state_ = 1;
	geary_nonblocking_concurrent_concurrent_operation_wait_async (_data_->_tmp7_, geary_nonblocking_concurrent_schedule_async_ready, _data_);
	return FALSE;
	_state_1:
	geary_nonblocking_concurrent_concurrent_operation_wait_finish (_data_->_tmp7_, _data_->_res_, &_data_->_inner_error0_);
	if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
		g_task_return_error (_data_->_async_result, _data_->_inner_error0_);
		_g_object_unref0 (_data_->op);
		g_object_unref (_data_->_async_result);
		return FALSE;
	}
	_g_object_unref0 (_data_->op);
	g_task_return_pointer (_data_->_async_result, _data_, NULL);
	if (_data_->_state_ != 0) {
		while (!g_task_get_completed (_data_->_async_result)) {
			g_main_context_iteration (g_task_get_context (_data_->_async_result), TRUE);
		}
	}
	g_object_unref (_data_->_async_result);
	return FALSE;
}

static void
geary_nonblocking_concurrent_on_work_ready (GearyNonblockingConcurrent* self,
                                            GearyNonblockingConcurrentConcurrentOperation* op)
{
	g_return_if_fail (GEARY_NONBLOCKING_IS_CONCURRENT (self));
	g_return_if_fail (GEARY_NONBLOCKING_CONCURRENT_IS_CONCURRENT_OPERATION (op));
	geary_nonblocking_concurrent_concurrent_operation_execute (op);
	_g_object_unref0 (op);
}

static inline gpointer
geary_nonblocking_concurrent_concurrent_operation_get_instance_private (GearyNonblockingConcurrentConcurrentOperation* self)
{
	return G_STRUCT_MEMBER_P (self, GearyNonblockingConcurrentConcurrentOperation_private_offset);
}

static GearyNonblockingConcurrentConcurrentOperation*
geary_nonblocking_concurrent_concurrent_operation_construct (GType object_type,
                                                             GearyNonblockingConcurrentConcurrentCallback cb,
                                                             gpointer cb_target,
                                                             GCancellable* cancellable)
{
	GearyNonblockingConcurrentConcurrentOperation * self = NULL;
	GCancellable* _tmp0_;
	g_return_val_if_fail ((cancellable == NULL) || G_TYPE_CHECK_INSTANCE_TYPE (cancellable, g_cancellable_get_type ()), NULL);
	self = (GearyNonblockingConcurrentConcurrentOperation*) geary_base_object_construct (object_type);
	self->priv->cb = cb;
	self->priv->cb_target = cb_target;
	_tmp0_ = _g_object_ref0 (cancellable);
	_g_object_unref0 (self->priv->cancellable);
	self->priv->cancellable = _tmp0_;
	return self;
}

static GearyNonblockingConcurrentConcurrentOperation*
geary_nonblocking_concurrent_concurrent_operation_new (GearyNonblockingConcurrentConcurrentCallback cb,
                                                       gpointer cb_target,
                                                       GCancellable* cancellable)
{
	return geary_nonblocking_concurrent_concurrent_operation_construct (GEARY_NONBLOCKING_CONCURRENT_TYPE_CONCURRENT_OPERATION, cb, cb_target, cancellable);
}

static void
geary_nonblocking_concurrent_concurrent_operation_wait_async_data_free (gpointer _data)
{
	GearyNonblockingConcurrentConcurrentOperationWaitAsyncData* _data_;
	_data_ = _data;
	_g_object_unref0 (_data_->self);
	g_slice_free (GearyNonblockingConcurrentConcurrentOperationWaitAsyncData, _data_);
}

static void
geary_nonblocking_concurrent_concurrent_operation_wait_async (GearyNonblockingConcurrentConcurrentOperation* self,
                                                              GAsyncReadyCallback _callback_,
                                                              gpointer _user_data_)
{
	GearyNonblockingConcurrentConcurrentOperationWaitAsyncData* _data_;
	GearyNonblockingConcurrentConcurrentOperation* _tmp0_;
	g_return_if_fail (GEARY_NONBLOCKING_CONCURRENT_IS_CONCURRENT_OPERATION (self));
	_data_ = g_slice_new0 (GearyNonblockingConcurrentConcurrentOperationWaitAsyncData);
	_data_->_async_result = g_task_new (G_OBJECT (self), NULL, _callback_, _user_data_);
	g_task_set_task_data (_data_->_async_result, _data_, geary_nonblocking_concurrent_concurrent_operation_wait_async_data_free);
	_tmp0_ = _g_object_ref0 (self);
	_data_->self = _tmp0_;
	geary_nonblocking_concurrent_concurrent_operation_wait_async_co (_data_);
}

static void
geary_nonblocking_concurrent_concurrent_operation_wait_finish (GearyNonblockingConcurrentConcurrentOperation* self,
                                                               GAsyncResult* _res_,
                                                               GError** error)
{
	GearyNonblockingConcurrentConcurrentOperationWaitAsyncData* _data_;
	_data_ = g_task_propagate_pointer (G_TASK (_res_), error);
	if (NULL == _data_) {
		return;
	}
}

static void
geary_nonblocking_concurrent_concurrent_operation_wait_async_ready (GObject* source_object,
                                                                    GAsyncResult* _res_,
                                                                    gpointer _user_data_)
{
	GearyNonblockingConcurrentConcurrentOperationWaitAsyncData* _data_;
	_data_ = _user_data_;
	_data_->_source_object_ = source_object;
	_data_->_res_ = _res_;
	geary_nonblocking_concurrent_concurrent_operation_wait_async_co (_data_);
}

static gboolean
geary_nonblocking_concurrent_concurrent_operation_wait_async_co (GearyNonblockingConcurrentConcurrentOperationWaitAsyncData* _data_)
{
	switch (_data_->_state_) {
		case 0:
		goto _state_0;
		case 1:
		goto _state_1;
		default:
		g_assert_not_reached ();
	}
	_state_0:
	_data_->_tmp0_ = _data_->self->priv->event;
	_data_->_state_ = 1;
	geary_nonblocking_lock_wait_async (G_TYPE_CHECK_INSTANCE_CAST (_data_->_tmp0_, GEARY_NONBLOCKING_TYPE_LOCK, GearyNonblockingLock), NULL, geary_nonblocking_concurrent_concurrent_operation_wait_async_ready, _data_);
	return FALSE;
	_state_1:
	geary_nonblocking_lock_wait_finish (G_TYPE_CHECK_INSTANCE_CAST (_data_->_tmp0_, GEARY_NONBLOCKING_TYPE_LOCK, GearyNonblockingLock), _data_->_res_, &_data_->_inner_error0_);
	if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
		g_task_return_error (_data_->_async_result, _data_->_inner_error0_);
		g_object_unref (_data_->_async_result);
		return FALSE;
	}
	_data_->_tmp1_ = _data_->self->priv->caught_err;
	if (_data_->_tmp1_ != NULL) {
		_data_->_tmp2_ = _data_->self->priv->caught_err;
		_data_->_tmp3_ = _g_error_copy0 (_data_->_tmp2_);
		_data_->_inner_error0_ = _data_->_tmp3_;
		g_task_return_error (_data_->_async_result, _data_->_inner_error0_);
		g_object_unref (_data_->_async_result);
		return FALSE;
	}
	_data_->_tmp5_ = _data_->self->priv->cancellable;
	if (_data_->_tmp5_ != NULL) {
		_data_->_tmp6_ = _data_->self->priv->cancellable;
		_data_->_tmp4_ = g_cancellable_is_cancelled (_data_->_tmp6_);
	} else {
		_data_->_tmp4_ = FALSE;
	}
	if (_data_->_tmp4_) {
		_data_->_tmp7_ = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED, "Geary.Nonblocking.Concurrent cancelled");
		_data_->_inner_error0_ = _data_->_tmp7_;
		g_task_return_error (_data_->_async_result, _data_->_inner_error0_);
		g_object_unref (_data_->_async_result);
		return FALSE;
	}
	g_task_return_pointer (_data_->_async_result, _data_, NULL);
	if (_data_->_state_ != 0) {
		while (!g_task_get_completed (_data_->_async_result)) {
			g_main_context_iteration (g_task_get_context (_data_->_async_result), TRUE);
		}
	}
	g_object_unref (_data_->_async_result);
	return FALSE;
}

static gboolean
_geary_nonblocking_concurrent_concurrent_operation_on_notify_completed_gsource_func (gpointer self)
{
	gboolean result;
	result = geary_nonblocking_concurrent_concurrent_operation_on_notify_completed ((GearyNonblockingConcurrentConcurrentOperation*) self);
	return result;
}

static void
geary_nonblocking_concurrent_concurrent_operation_execute (GearyNonblockingConcurrentConcurrentOperation* self)
{
	gboolean _tmp0_ = FALSE;
	GCancellable* _tmp1_;
	GError* _inner_error0_ = NULL;
	g_return_if_fail (GEARY_NONBLOCKING_CONCURRENT_IS_CONCURRENT_OPERATION (self));
	_tmp1_ = self->priv->cancellable;
	if (_tmp1_ == NULL) {
		_tmp0_ = TRUE;
	} else {
		GCancellable* _tmp2_;
		_tmp2_ = self->priv->cancellable;
		_tmp0_ = !g_cancellable_is_cancelled (_tmp2_);
	}
	if (_tmp0_) {
		{
			GearyNonblockingConcurrentConcurrentCallback _tmp3_;
			gpointer _tmp3__target;
			GCancellable* _tmp4_;
			_tmp3_ = self->priv->cb;
			_tmp3__target = self->priv->cb_target;
			_tmp4_ = self->priv->cancellable;
			_tmp3_ (_tmp4_, _tmp3__target, &_inner_error0_);
			if (G_UNLIKELY (_inner_error0_ != NULL)) {
				goto __catch0_g_error;
			}
		}
		goto __finally0;
		__catch0_g_error:
		{
			GError* err = NULL;
			GError* _tmp5_;
			GError* _tmp6_;
			err = _inner_error0_;
			_inner_error0_ = NULL;
			_tmp5_ = err;
			_tmp6_ = _g_error_copy0 (_tmp5_);
			_g_error_free0 (self->priv->caught_err);
			self->priv->caught_err = _tmp6_;
			_g_error_free0 (err);
		}
		__finally0:
		if (G_UNLIKELY (_inner_error0_ != NULL)) {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return;
		}
	}
	g_object_ref (G_TYPE_CHECK_INSTANCE_CAST (self, G_TYPE_OBJECT, GObject));
	g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, _geary_nonblocking_concurrent_concurrent_operation_on_notify_completed_gsource_func, g_object_ref (self), g_object_unref);
}

static gboolean
geary_nonblocking_concurrent_concurrent_operation_on_notify_completed (GearyNonblockingConcurrentConcurrentOperation* self)
{
	GearyNonblockingEvent* _tmp0_;
	gboolean result;
	g_return_val_if_fail (GEARY_NONBLOCKING_CONCURRENT_IS_CONCURRENT_OPERATION (self), FALSE);
	_tmp0_ = self->priv->event;
	geary_nonblocking_lock_blind_notify (G_TYPE_CHECK_INSTANCE_CAST (_tmp0_, GEARY_NONBLOCKING_TYPE_LOCK, GearyNonblockingLock));
	g_object_unref (G_TYPE_CHECK_INSTANCE_CAST (self, G_TYPE_OBJECT, GObject));
	result = FALSE;
	return result;
}

static void
geary_nonblocking_concurrent_concurrent_operation_class_init (GearyNonblockingConcurrentConcurrentOperationClass * klass,
                                                              gpointer klass_data)
{
	geary_nonblocking_concurrent_concurrent_operation_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &GearyNonblockingConcurrentConcurrentOperation_private_offset);
	G_OBJECT_CLASS (klass)->finalize = geary_nonblocking_concurrent_concurrent_operation_finalize;
}

static void
geary_nonblocking_concurrent_concurrent_operation_instance_init (GearyNonblockingConcurrentConcurrentOperation * self,
                                                                 gpointer klass)
{
	GearyNonblockingEvent* _tmp0_;
	self->priv = geary_nonblocking_concurrent_concurrent_operation_get_instance_private (self);
	self->priv->caught_err = NULL;
	_tmp0_ = geary_nonblocking_event_new (NULL);
	self->priv->event = _tmp0_;
}

static void
geary_nonblocking_concurrent_concurrent_operation_finalize (GObject * obj)
{
	GearyNonblockingConcurrentConcurrentOperation * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, GEARY_NONBLOCKING_CONCURRENT_TYPE_CONCURRENT_OPERATION, GearyNonblockingConcurrentConcurrentOperation);
	_g_object_unref0 (self->priv->cancellable);
	_g_error_free0 (self->priv->caught_err);
	_g_object_unref0 (self->priv->event);
	G_OBJECT_CLASS (geary_nonblocking_concurrent_concurrent_operation_parent_class)->finalize (obj);
}

 G_GNUC_NO_INLINE static GType
geary_nonblocking_concurrent_concurrent_operation_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (GearyNonblockingConcurrentConcurrentOperationClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) geary_nonblocking_concurrent_concurrent_operation_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (GearyNonblockingConcurrentConcurrentOperation), 0, (GInstanceInitFunc) geary_nonblocking_concurrent_concurrent_operation_instance_init, NULL };
	GType geary_nonblocking_concurrent_concurrent_operation_type_id;
	geary_nonblocking_concurrent_concurrent_operation_type_id = g_type_register_static (GEARY_TYPE_BASE_OBJECT, "GearyNonblockingConcurrentConcurrentOperation", &g_define_type_info, 0);
	GearyNonblockingConcurrentConcurrentOperation_private_offset = g_type_add_instance_private (geary_nonblocking_concurrent_concurrent_operation_type_id, sizeof (GearyNonblockingConcurrentConcurrentOperationPrivate));
	return geary_nonblocking_concurrent_concurrent_operation_type_id;
}

static GType
geary_nonblocking_concurrent_concurrent_operation_get_type (void)
{
	static gsize geary_nonblocking_concurrent_concurrent_operation_type_id__once = 0;
	if (g_once_init_enter (&geary_nonblocking_concurrent_concurrent_operation_type_id__once)) {
		GType geary_nonblocking_concurrent_concurrent_operation_type_id;
		geary_nonblocking_concurrent_concurrent_operation_type_id = geary_nonblocking_concurrent_concurrent_operation_get_type_once ();
		g_once_init_leave (&geary_nonblocking_concurrent_concurrent_operation_type_id__once, geary_nonblocking_concurrent_concurrent_operation_type_id);
	}
	return geary_nonblocking_concurrent_concurrent_operation_type_id__once;
}

static void
geary_nonblocking_concurrent_class_init (GearyNonblockingConcurrentClass * klass,
                                         gpointer klass_data)
{
	geary_nonblocking_concurrent_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &GearyNonblockingConcurrent_private_offset);
	G_OBJECT_CLASS (klass)->get_property = _vala_geary_nonblocking_concurrent_get_property;
	G_OBJECT_CLASS (klass)->finalize = geary_nonblocking_concurrent_finalize;
}

static void
geary_nonblocking_concurrent_instance_init (GearyNonblockingConcurrent * self,
                                            gpointer klass)
{
	self->priv = geary_nonblocking_concurrent_get_instance_private (self);
	self->priv->thread_pool = NULL;
	self->priv->init_err = NULL;
}

static void
geary_nonblocking_concurrent_finalize (GObject * obj)
{
	GearyNonblockingConcurrent * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, GEARY_NONBLOCKING_TYPE_CONCURRENT, GearyNonblockingConcurrent);
	_g_thread_pool_free0 (self->priv->thread_pool);
	_g_error_free0 (self->priv->init_err);
	G_OBJECT_CLASS (geary_nonblocking_concurrent_parent_class)->finalize (obj);
}

/**
 * Schedule an asynchronous operation (a {@link ConcurrentCallback} to run in a background thread.
 *
 * Useful to perform blocking I/O or CPU-bound tasks where the result must be ready before
 * other work can proceed.
 */
 G_GNUC_NO_INLINE static GType
geary_nonblocking_concurrent_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (GearyNonblockingConcurrentClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) geary_nonblocking_concurrent_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (GearyNonblockingConcurrent), 0, (GInstanceInitFunc) geary_nonblocking_concurrent_instance_init, NULL };
	GType geary_nonblocking_concurrent_type_id;
	geary_nonblocking_concurrent_type_id = g_type_register_static (GEARY_TYPE_BASE_OBJECT, "GearyNonblockingConcurrent", &g_define_type_info, 0);
	GearyNonblockingConcurrent_private_offset = g_type_add_instance_private (geary_nonblocking_concurrent_type_id, sizeof (GearyNonblockingConcurrentPrivate));
	return geary_nonblocking_concurrent_type_id;
}

GType
geary_nonblocking_concurrent_get_type (void)
{
	static gsize geary_nonblocking_concurrent_type_id__once = 0;
	if (g_once_init_enter (&geary_nonblocking_concurrent_type_id__once)) {
		GType geary_nonblocking_concurrent_type_id;
		geary_nonblocking_concurrent_type_id = geary_nonblocking_concurrent_get_type_once ();
		g_once_init_leave (&geary_nonblocking_concurrent_type_id__once, geary_nonblocking_concurrent_type_id);
	}
	return geary_nonblocking_concurrent_type_id__once;
}

static void
_vala_geary_nonblocking_concurrent_get_property (GObject * object,
                                                 guint property_id,
                                                 GValue * value,
                                                 GParamSpec * pspec)
{
	GearyNonblockingConcurrent * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, GEARY_NONBLOCKING_TYPE_CONCURRENT, GearyNonblockingConcurrent);
	switch (property_id) {
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

