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

/* future.vala
 *
 * Copyright (C) 2013  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-object.h>
#include <glib.h>
#include <gio/gio.h>
#include <string.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif

typedef struct _Block7Data Block7Data;
#define _gee_promise_unref0(var) ((var == NULL) ? NULL : (var = (gee_promise_unref (var), NULL)))
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL)))

#define GEE_TYPE_LIGHT_MAP_FUTURE (gee_light_map_future_get_type ())
#define GEE_LIGHT_MAP_FUTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEE_TYPE_LIGHT_MAP_FUTURE, GeeLightMapFuture))
#define GEE_LIGHT_MAP_FUTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEE_TYPE_LIGHT_MAP_FUTURE, GeeLightMapFutureClass))
#define GEE_IS_LIGHT_MAP_FUTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEE_TYPE_LIGHT_MAP_FUTURE))
#define GEE_IS_LIGHT_MAP_FUTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEE_TYPE_LIGHT_MAP_FUTURE))
#define GEE_LIGHT_MAP_FUTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEE_TYPE_LIGHT_MAP_FUTURE, GeeLightMapFutureClass))

typedef struct _GeeLightMapFuture GeeLightMapFuture;
typedef struct _GeeLightMapFutureClass GeeLightMapFutureClass;
typedef struct _Block8Data Block8Data;
typedef struct _GeeFutureDoZipData GeeFutureDoZipData;
typedef struct _Block9Data Block9Data;
typedef struct _GeeFutureDoFlatMapData GeeFutureDoFlatMapData;

#define GEE_FUTURE_TYPE_SOURCE_FUNC_ARRAY_ELEMENT (gee_future_source_func_array_element_get_type ())
typedef struct _GeeFutureSourceFuncArrayElement GeeFutureSourceFuncArrayElement;

struct _Block7Data {
	int _ref_count_;
	GeeFuture* self;
	GType a_type;
	GBoxedCopyFunc a_dup_func;
	GDestroyNotify a_destroy_func;
	GeePromise* promise;
	GeeFutureMapFunc func;
	gpointer func_target;
	GDestroyNotify func_target_destroy_notify;
};

struct _Block8Data {
	int _ref_count_;
	GeeFuture* self;
	GType a_type;
	GBoxedCopyFunc a_dup_func;
	GDestroyNotify a_destroy_func;
	GType b_type;
	GBoxedCopyFunc b_dup_func;
	GDestroyNotify b_destroy_func;
};

struct _GeeFutureDoZipData {
	int _state_;
	GObject* _source_object_;
	GAsyncResult* _res_;
	GTask* _async_result;
	GeeFutureZipFunc zip_func;
	gpointer zip_func_target;
	GeeFuture* first;
	GeeFuture* second;
	GeePromise* _result_;
	GType a_type;
	GBoxedCopyFunc a_dup_func;
	GDestroyNotify a_destroy_func;
	GType b_type;
	GBoxedCopyFunc b_dup_func;
	GDestroyNotify b_destroy_func;
	GType c_type;
	GBoxedCopyFunc c_dup_func;
	GDestroyNotify c_destroy_func;
	gpointer left;
	gconstpointer _tmp0_;
	gpointer _tmp1_;
	gpointer right;
	gconstpointer _tmp2_;
	gpointer _tmp3_;
	gconstpointer _tmp4_;
	gconstpointer _tmp5_;
	gpointer _tmp6_;
	GError* ex;
	GError* _tmp7_;
	GError* _inner_error0_;
};

struct _Block9Data {
	int _ref_count_;
	GeeFuture* self;
	GType a_type;
	GBoxedCopyFunc a_dup_func;
	GDestroyNotify a_destroy_func;
};

struct _GeeFutureDoFlatMapData {
	int _state_;
	GObject* _source_object_;
	GAsyncResult* _res_;
	GTask* _async_result;
	GeeFutureFlatMapFunc func;
	gpointer func_target;
	GDestroyNotify func_target_destroy_notify;
	GeeFuture* future;
	GeePromise* promise;
	GType a_type;
	GBoxedCopyFunc a_dup_func;
	GDestroyNotify a_destroy_func;
	GType b_type;
	GBoxedCopyFunc b_dup_func;
	GDestroyNotify b_destroy_func;
	gpointer input;
	gconstpointer _tmp0_;
	gpointer _tmp1_;
	GeeFuture* output_future;
	gconstpointer _tmp2_;
	GeeFuture* _tmp3_;
	gpointer output;
	GeeFuture* _tmp4_;
	gconstpointer _tmp5_;
	gpointer _tmp6_;
	gpointer _tmp7_;
	GeeFuture* _tmp8_;
	GError* _tmp9_;
	GError* _tmp10_;
	GError* _tmp11_;
	GError* _tmp12_;
	GError* _tmp13_;
	GError* _tmp14_;
	GError* ex;
	GError* _tmp15_;
	GError* _inner_error0_;
};

struct _GeeFutureSourceFuncArrayElement {
	GSourceFunc func;
	gpointer func_target;
	GDestroyNotify func_target_destroy_notify;
};

static GeeFuture* gee_future_real_map (GeeFuture* self,
                                GType a_type,
                                GBoxedCopyFunc a_dup_func,
                                GDestroyNotify a_destroy_func,
                                GeeFutureMapFunc func,
                                gpointer func_target,
                                GDestroyNotify func_target_destroy_notify);
static Block7Data* block7_data_ref (Block7Data* _data7_);
static void block7_data_unref (void * _userdata_);
static void __lambda4_ (Block7Data* _data7_,
                 GObject* obj,
                 GAsyncResult* res);
static void ___lambda4__gasync_ready_callback (GObject* source_object,
                                        GAsyncResult* res,
                                        gpointer self);
static GeeFuture* gee_future_real_light_map (GeeFuture* self,
                                      GType a_type,
                                      GBoxedCopyFunc a_dup_func,
                                      GDestroyNotify a_destroy_func,
                                      GeeFutureLightMapFunc func,
                                      gpointer func_target,
                                      GDestroyNotify func_target_destroy_notify);
 G_GNUC_INTERNAL GeeLightMapFuture* gee_light_map_future_new (GType a_type,
                                             GBoxedCopyFunc a_dup_func,
                                             GDestroyNotify a_destroy_func,
                                             GType g_type,
                                             GBoxedCopyFunc g_dup_func,
                                             GDestroyNotify g_destroy_func,
                                             GeeFuture* base_future,
                                             GeeFutureLightMapFunc func,
                                             gpointer func_target,
                                             GDestroyNotify func_target_destroy_notify);
 G_GNUC_INTERNAL GeeLightMapFuture* gee_light_map_future_construct (GType object_type,
                                                   GType a_type,
                                                   GBoxedCopyFunc a_dup_func,
                                                   GDestroyNotify a_destroy_func,
                                                   GType g_type,
                                                   GBoxedCopyFunc g_dup_func,
                                                   GDestroyNotify g_destroy_func,
                                                   GeeFuture* base_future,
                                                   GeeFutureLightMapFunc func,
                                                   gpointer func_target,
                                                   GDestroyNotify func_target_destroy_notify);
 G_GNUC_INTERNAL GType gee_light_map_future_get_type (void) G_GNUC_CONST  G_GNUC_UNUSED ;
static GeeFuture* gee_future_real_light_map_broken (GeeFuture* self,
                                             GType a_type,
                                             GBoxedCopyFunc a_dup_func,
                                             GDestroyNotify a_destroy_func,
                                             GeeFutureLightMapFunc func,
                                             gpointer func_target);
static GeeFuture* gee_future_real_zip (GeeFuture* self,
                                GType a_type,
                                GBoxedCopyFunc a_dup_func,
                                GDestroyNotify a_destroy_func,
                                GType b_type,
                                GBoxedCopyFunc b_dup_func,
                                GDestroyNotify b_destroy_func,
                                GeeFutureZipFunc zip_func,
                                gpointer zip_func_target,
                                GeeFuture* second);
static Block8Data* block8_data_ref (Block8Data* _data8_);
static void block8_data_unref (void * _userdata_);
static void gee_future_do_zip (GType a_type,
                        GBoxedCopyFunc a_dup_func,
                        GDestroyNotify a_destroy_func,
                        GType b_type,
                        GBoxedCopyFunc b_dup_func,
                        GDestroyNotify b_destroy_func,
                        GType c_type,
                        GBoxedCopyFunc c_dup_func,
                        GDestroyNotify c_destroy_func,
                        GeeFutureZipFunc zip_func,
                        gpointer zip_func_target,
                        GeeFuture* first,
                        GeeFuture* second,
                        GeePromise* _result_,
                        GAsyncReadyCallback _callback_,
                        gpointer _user_data_);
static void gee_future_do_zip_finish (GAsyncResult* _res_);
static void __lambda5_ (Block8Data* _data8_,
                 GObject* obj,
                 GAsyncResult* res);
static void ___lambda5__gasync_ready_callback (GObject* source_object,
                                        GAsyncResult* res,
                                        gpointer self);
static void gee_future_do_zip_data_free (gpointer _data);
static gboolean gee_future_do_zip_co (GeeFutureDoZipData* _data_);
static void gee_future_do_zip_ready (GObject* source_object,
                              GAsyncResult* _res_,
                              gpointer _user_data_);
static GeeFuture* gee_future_real_flat_map (GeeFuture* self,
                                     GType a_type,
                                     GBoxedCopyFunc a_dup_func,
                                     GDestroyNotify a_destroy_func,
                                     GeeFutureFlatMapFunc func,
                                     gpointer func_target,
                                     GDestroyNotify func_target_destroy_notify);
static Block9Data* block9_data_ref (Block9Data* _data9_);
static void block9_data_unref (void * _userdata_);
static void gee_future_do_flat_map (GType a_type,
                             GBoxedCopyFunc a_dup_func,
                             GDestroyNotify a_destroy_func,
                             GType b_type,
                             GBoxedCopyFunc b_dup_func,
                             GDestroyNotify b_destroy_func,
                             GeeFutureFlatMapFunc func,
                             gpointer func_target,
                             GDestroyNotify func_target_destroy_notify,
                             GeeFuture* future,
                             GeePromise* promise,
                             GAsyncReadyCallback _callback_,
                             gpointer _user_data_);
static void gee_future_do_flat_map_finish (GAsyncResult* _res_);
static void __lambda6_ (Block9Data* _data9_,
                 GObject* obj,
                 GAsyncResult* res);
static void ___lambda6__gasync_ready_callback (GObject* source_object,
                                        GAsyncResult* res,
                                        gpointer self);
static void gee_future_do_flat_map_data_free (gpointer _data);
static gboolean gee_future_do_flat_map_co (GeeFutureDoFlatMapData* _data_);
static void gee_future_do_flat_map_ready (GObject* source_object,
                                   GAsyncResult* _res_,
                                   gpointer _user_data_);
 G_GNUC_INTERNAL GType gee_future_source_func_array_element_get_type (void) G_GNUC_CONST  G_GNUC_UNUSED ;
 G_GNUC_INTERNAL GeeFutureSourceFuncArrayElement* gee_future_source_func_array_element_dup (const GeeFutureSourceFuncArrayElement* self);
 G_GNUC_INTERNAL void gee_future_source_func_array_element_free (GeeFutureSourceFuncArrayElement* self);
 G_GNUC_INTERNAL void gee_future_source_func_array_element_copy (const GeeFutureSourceFuncArrayElement* self,
                                                GeeFutureSourceFuncArrayElement* dest);
 G_GNUC_INTERNAL void gee_future_source_func_array_element_destroy (GeeFutureSourceFuncArrayElement* self);
 G_GNUC_INTERNAL void gee_future_source_func_array_element_init (GeeFutureSourceFuncArrayElement *self,
                                                GSourceFunc func,
                                                gpointer func_target,
                                                GDestroyNotify func_target_destroy_notify);
static GType gee_future_get_type_once (void);

/**
 * Waits until the value is ready.
 *
 * @return The {@link value} associated with future
 * @see ready
 * @see wait_until
 * @see wait_async
 */
gconstpointer
gee_future_wait (GeeFuture* self,
                 GError** error)
{
	GeeFutureIface* _iface_;
	g_return_val_if_fail (self != NULL, NULL);
	_iface_ = GEE_FUTURE_GET_INTERFACE (self);
	if (_iface_->wait) {
		return _iface_->wait (self, error);
	}
	return NULL;
}

/**
 * Waits until the value is ready or deadline have passed.
 *
 * @param end_time The time when the wait should finish
 * @param value The {@link value} associated with future if the wait was successful
 * @return ``true`` if the value was ready within deadline or ``false`` otherwise
 * @see ready
 * @see wait
 * @see wait_async
 */
gboolean
gee_future_wait_until (GeeFuture* self,
                       gint64 end_time,
                       gconstpointer* value,
                       GError** error)
{
	GeeFutureIface* _iface_;
	g_return_val_if_fail (self != NULL, FALSE);
	_iface_ = GEE_FUTURE_GET_INTERFACE (self);
	if (_iface_->wait_until) {
		return _iface_->wait_until (self, end_time, value, error);
	}
	return FALSE;
}

void
gee_future_wait_async (GeeFuture* self,
                       GAsyncReadyCallback _callback_,
                       gpointer _user_data_)
{
	GeeFutureIface* _iface_;
	_iface_ = GEE_FUTURE_GET_INTERFACE (self);
	if (_iface_->wait_async) {
		_iface_->wait_async (self, _callback_, _user_data_);
	}
}

gconstpointer
gee_future_wait_finish (GeeFuture* self,
                        GAsyncResult* _res_,
                        GError** error)
{
	GeeFutureIface* _iface_;
	_iface_ = GEE_FUTURE_GET_INTERFACE (self);
	if (_iface_->wait_finish) {
		return _iface_->wait_finish (self, _res_, error);
	}
	return NULL;
}

/**
 * Maps a future value to another value by a function and returns the
 * another value in future.
 *
 * Note: As time taken by function might not contribute to
 *   {@link wait_until} and the implementation is allowed to compute
 *   value eagerly by {@link wait_async} it is recommended to use
 *   {@link task} and {@link flat_map} for longer computation.
 *
 * @param func Function applied to {@link value}
 * @return Value returned by function
 *
 * @see flat_map
 * @see light_map
 */
static Block7Data*
block7_data_ref (Block7Data* _data7_)
{
	g_atomic_int_inc (&_data7_->_ref_count_);
	return _data7_;
}

static void
block7_data_unref (void * _userdata_)
{
	Block7Data* _data7_;
	_data7_ = (Block7Data*) _userdata_;
	if (g_atomic_int_dec_and_test (&_data7_->_ref_count_)) {
		GeeFuture* self;
		GType a_type;
		GBoxedCopyFunc a_dup_func;
		GDestroyNotify a_destroy_func;
		self = _data7_->self;
		a_type = _data7_->a_type;
		a_dup_func = _data7_->a_dup_func;
		a_destroy_func = _data7_->a_destroy_func;
		_gee_promise_unref0 (_data7_->promise);
		(_data7_->func_target_destroy_notify == NULL) ? NULL : (_data7_->func_target_destroy_notify (_data7_->func_target), NULL);
		_data7_->func = NULL;
		_data7_->func_target = NULL;
		_data7_->func_target_destroy_notify = NULL;
		_g_object_unref0 (self);
		g_slice_free (Block7Data, _data7_);
	}
}

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

static void
__lambda4_ (Block7Data* _data7_,
            GObject* obj,
            GAsyncResult* res)
{
	GeeFuture* self;
	GType a_type;
	GBoxedCopyFunc a_dup_func;
	GDestroyNotify a_destroy_func;
	GError* _inner_error0_ = NULL;
	self = _data7_->self;
	a_type = _data7_->a_type;
	a_dup_func = _data7_->a_dup_func;
	a_destroy_func = _data7_->a_destroy_func;
	g_return_if_fail (res != NULL);
	{
		gconstpointer _tmp0_ = NULL;
		gconstpointer _tmp1_;
		gpointer _tmp2_;
		_tmp1_ = gee_future_wait_finish (self, res, &_inner_error0_);
		_tmp0_ = _tmp1_;
		if (G_UNLIKELY (_inner_error0_ != NULL)) {
			if (g_error_matches (_inner_error0_, GEE_FUTURE_ERROR, GEE_FUTURE_ERROR_EXCEPTION)) {
				goto __catch0_gee_future_error_exception;
			}
			goto __catch0_g_error;
		}
		_tmp2_ = _data7_->func (_tmp0_, _data7_->func_target);
		gee_promise_set_value (_data7_->promise, _tmp2_);
	}
	goto __finally0;
	__catch0_gee_future_error_exception:
	{
		GError* _tmp3_;
		GError* _tmp4_;
		GError* _tmp5_;
		g_clear_error (&_inner_error0_);
		_tmp3_ = gee_future_get_exception (self);
		_tmp4_ = _tmp3_;
		_tmp5_ = _g_error_copy0 (_tmp4_);
		gee_promise_set_exception (_data7_->promise, _tmp5_);
	}
	goto __finally0;
	__catch0_g_error:
	{
		GError* ex = NULL;
		GError* _tmp6_;
		ex = _inner_error0_;
		_inner_error0_ = NULL;
		_tmp6_ = ex;
		ex = NULL;
		gee_promise_set_exception (_data7_->promise, _tmp6_);
		_g_error_free0 (ex);
	}
	__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;
	}
}

static void
___lambda4__gasync_ready_callback (GObject* source_object,
                                   GAsyncResult* res,
                                   gpointer self)
{
	__lambda4_ (self, source_object, res);
	block7_data_unref (self);
}

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

static GeeFuture*
gee_future_real_map (GeeFuture* self,
                     GType a_type,
                     GBoxedCopyFunc a_dup_func,
                     GDestroyNotify a_destroy_func,
                     GeeFutureMapFunc func,
                     gpointer func_target,
                     GDestroyNotify func_target_destroy_notify)
{
	Block7Data* _data7_;
	GeePromise* _tmp0_;
	GeeFuture* _tmp1_;
	GeeFuture* _tmp2_;
	GeeFuture* _tmp3_;
	GeeFuture* result;
	_data7_ = g_slice_new0 (Block7Data);
	_data7_->_ref_count_ = 1;
	_data7_->self = g_object_ref (self);
	_data7_->a_type = a_type;
	_data7_->a_dup_func = a_dup_func;
	_data7_->a_destroy_func = a_destroy_func;
	(_data7_->func_target_destroy_notify == NULL) ? NULL : (_data7_->func_target_destroy_notify (_data7_->func_target), NULL);
	_data7_->func = NULL;
	_data7_->func_target = NULL;
	_data7_->func_target_destroy_notify = NULL;
	_data7_->func = func;
	_data7_->func_target = func_target;
	_data7_->func_target_destroy_notify = func_target_destroy_notify;
	_tmp0_ = gee_promise_new (a_type, (GBoxedCopyFunc) a_dup_func, (GDestroyNotify) a_destroy_func);
	_data7_->promise = _tmp0_;
	gee_future_wait_async (self, ___lambda4__gasync_ready_callback, block7_data_ref (_data7_));
	_tmp1_ = gee_promise_get_future (_data7_->promise);
	_tmp2_ = _tmp1_;
	_tmp3_ = _g_object_ref0 (_tmp2_);
	result = _tmp3_;
	block7_data_unref (_data7_);
	_data7_ = NULL;
	return result;
}

GeeFuture*
gee_future_map (GeeFuture* self,
                GType a_type,
                GBoxedCopyFunc a_dup_func,
                GDestroyNotify a_destroy_func,
                GeeFutureMapFunc func,
                gpointer func_target,
                GDestroyNotify func_target_destroy_notify)
{
	GeeFutureIface* _iface_;
	g_return_val_if_fail (self != NULL, NULL);
	_iface_ = GEE_FUTURE_GET_INTERFACE (self);
	if (_iface_->map) {
		return _iface_->map (self, a_type, a_dup_func, a_destroy_func, func, func_target, func_target_destroy_notify);
	}
	return NULL;
}

/**
 * Maps a future value to another value by a function and returns the
 * another value in future.
 *
 * Note: The function may be reevaluated at any time and it might
 *   be called lazily. Therefore it is recommended for it to be
 *   idempotent. If the function needs to be called eagerly or have
 *   side-effects it is recommended to use {@link map}.
 *
 * Note: As time taken by function does not contribute to
 *   {@link wait_until} and the implementation is allowed to compute
 *   value eagerly by {@link wait_async} it is recommended to use
 *   {@link task} and {@link flat_map} for longer computation.
 *
 * @param func Function applied to {@link value}
 * @return Value returned by function
 *
 * @see flat_map
 * @see map
 * @since 0.11.4
 */
static GeeFuture*
gee_future_real_light_map (GeeFuture* self,
                           GType a_type,
                           GBoxedCopyFunc a_dup_func,
                           GDestroyNotify a_destroy_func,
                           GeeFutureLightMapFunc func,
                           gpointer func_target,
                           GDestroyNotify func_target_destroy_notify)
{
	GeeFutureLightMapFunc _tmp0_;
	gpointer _tmp0__target;
	GDestroyNotify _tmp0__target_destroy_notify;
	GeeLightMapFuture* _tmp1_;
	GeeFuture* result;
	_tmp0_ = func;
	_tmp0__target = func_target;
	_tmp0__target_destroy_notify = func_target_destroy_notify;
	func = NULL;
	func_target = NULL;
	func_target_destroy_notify = NULL;
	_tmp1_ = gee_light_map_future_new (a_type, (GBoxedCopyFunc) a_dup_func, (GDestroyNotify) a_destroy_func, GEE_FUTURE_GET_INTERFACE (self)->get_g_type (self), (GBoxedCopyFunc) GEE_FUTURE_GET_INTERFACE (self)->get_g_dup_func (self), (GDestroyNotify) GEE_FUTURE_GET_INTERFACE (self)->get_g_destroy_func (self), self, _tmp0_, _tmp0__target, _tmp0__target_destroy_notify);
	result = (GeeFuture*) _tmp1_;
	(func_target_destroy_notify == NULL) ? NULL : (func_target_destroy_notify (func_target), NULL);
	func = NULL;
	func_target = NULL;
	func_target_destroy_notify = NULL;
	return result;
}

GeeFuture*
gee_future_light_map_fixed (GeeFuture* self,
                            GType a_type,
                            GBoxedCopyFunc a_dup_func,
                            GDestroyNotify a_destroy_func,
                            GeeFutureLightMapFunc func,
                            gpointer func_target,
                            GDestroyNotify func_target_destroy_notify)
{
	GeeFutureIface* _iface_;
	g_return_val_if_fail (self != NULL, NULL);
	_iface_ = GEE_FUTURE_GET_INTERFACE (self);
	if (_iface_->light_map_fixed) {
		return _iface_->light_map_fixed (self, a_type, a_dup_func, a_destroy_func, func, func_target, func_target_destroy_notify);
	}
	return NULL;
}

static GeeFuture*
gee_future_real_light_map_broken (GeeFuture* self,
                                  GType a_type,
                                  GBoxedCopyFunc a_dup_func,
                                  GDestroyNotify a_destroy_func,
                                  GeeFutureLightMapFunc func,
                                  gpointer func_target)
{
	GeeFuture* _tmp0_;
	GeeFuture* result;
	_tmp0_ = gee_future_light_map_fixed (self, a_type, (GBoxedCopyFunc) a_dup_func, (GDestroyNotify) a_destroy_func, func, func_target, NULL);
	result = _tmp0_;
	return result;
}

GeeFuture*
gee_future_light_map (GeeFuture* self,
                      GType a_type,
                      GBoxedCopyFunc a_dup_func,
                      GDestroyNotify a_destroy_func,
                      GeeFutureLightMapFunc func,
                      gpointer func_target)
{
	GeeFutureIface* _iface_;
	g_return_val_if_fail (self != NULL, NULL);
	_iface_ = GEE_FUTURE_GET_INTERFACE (self);
	if (_iface_->light_map) {
		return _iface_->light_map (self, a_type, a_dup_func, a_destroy_func, func, func_target);
	}
	return NULL;
}

/**
 * Combines values of two futures using a function returning the combined
 * value in future (call does not block).
 *
 * Note: As time taken by function does not contribute to
 *   {@link wait_until} and the implementation is allowed to compute
 *   value eagerly by {@link wait_async} it is recommended to return a
 *   future from {@link task} and use {@link flat_map} for longer computation.
 *
 * @param zip_func Function applied to values
 * @param second Second parameter
 * @return A combine value
 * @since 0.11.4
 */
static Block8Data*
block8_data_ref (Block8Data* _data8_)
{
	g_atomic_int_inc (&_data8_->_ref_count_);
	return _data8_;
}

static void
block8_data_unref (void * _userdata_)
{
	Block8Data* _data8_;
	_data8_ = (Block8Data*) _userdata_;
	if (g_atomic_int_dec_and_test (&_data8_->_ref_count_)) {
		GeeFuture* self;
		GType a_type;
		GBoxedCopyFunc a_dup_func;
		GDestroyNotify a_destroy_func;
		GType b_type;
		GBoxedCopyFunc b_dup_func;
		GDestroyNotify b_destroy_func;
		self = _data8_->self;
		a_type = _data8_->a_type;
		a_dup_func = _data8_->a_dup_func;
		a_destroy_func = _data8_->a_destroy_func;
		b_type = _data8_->b_type;
		b_dup_func = _data8_->b_dup_func;
		b_destroy_func = _data8_->b_destroy_func;
		_g_object_unref0 (self);
		g_slice_free (Block8Data, _data8_);
	}
}

static void
__lambda5_ (Block8Data* _data8_,
            GObject* obj,
            GAsyncResult* res)
{
	GeeFuture* self;
	GType a_type;
	GBoxedCopyFunc a_dup_func;
	GDestroyNotify a_destroy_func;
	GType b_type;
	GBoxedCopyFunc b_dup_func;
	GDestroyNotify b_destroy_func;
	self = _data8_->self;
	a_type = _data8_->a_type;
	a_dup_func = _data8_->a_dup_func;
	a_destroy_func = _data8_->a_destroy_func;
	b_type = _data8_->b_type;
	b_dup_func = _data8_->b_dup_func;
	b_destroy_func = _data8_->b_destroy_func;
	g_return_if_fail (res != NULL);
	gee_future_do_zip_finish (res);
}

static void
___lambda5__gasync_ready_callback (GObject* source_object,
                                   GAsyncResult* res,
                                   gpointer self)
{
	__lambda5_ (self, source_object, res);
	block8_data_unref (self);
}

static GeeFuture*
gee_future_real_zip (GeeFuture* self,
                     GType a_type,
                     GBoxedCopyFunc a_dup_func,
                     GDestroyNotify a_destroy_func,
                     GType b_type,
                     GBoxedCopyFunc b_dup_func,
                     GDestroyNotify b_destroy_func,
                     GeeFutureZipFunc zip_func,
                     gpointer zip_func_target,
                     GeeFuture* second)
{
	Block8Data* _data8_;
	GeePromise* promise = NULL;
	GeePromise* _tmp0_;
	GeeFutureZipFunc _tmp1_;
	gpointer _tmp1__target;
	GeeFuture* _tmp2_;
	GeeFuture* _tmp3_;
	GeeFuture* _tmp4_;
	GeeFuture* result;
	g_return_val_if_fail (second != NULL, NULL);
	_data8_ = g_slice_new0 (Block8Data);
	_data8_->_ref_count_ = 1;
	_data8_->self = g_object_ref (self);
	_data8_->a_type = a_type;
	_data8_->a_dup_func = a_dup_func;
	_data8_->a_destroy_func = a_destroy_func;
	_data8_->b_type = b_type;
	_data8_->b_dup_func = b_dup_func;
	_data8_->b_destroy_func = b_destroy_func;
	_tmp0_ = gee_promise_new (b_type, (GBoxedCopyFunc) b_dup_func, (GDestroyNotify) b_destroy_func);
	promise = _tmp0_;
	_tmp1_ = zip_func;
	_tmp1__target = zip_func_target;
	zip_func = NULL;
	zip_func_target = NULL;
	gee_future_do_zip (GEE_FUTURE_GET_INTERFACE (self)->get_g_type (self), (GBoxedCopyFunc) GEE_FUTURE_GET_INTERFACE (self)->get_g_dup_func (self), (GDestroyNotify) GEE_FUTURE_GET_INTERFACE (self)->get_g_destroy_func (self), a_type, (GBoxedCopyFunc) a_dup_func, (GDestroyNotify) a_destroy_func, b_type, (GBoxedCopyFunc) b_dup_func, (GDestroyNotify) b_destroy_func, _tmp1_, _tmp1__target, self, second, promise, ___lambda5__gasync_ready_callback, block8_data_ref (_data8_));
	_tmp2_ = gee_promise_get_future (promise);
	_tmp3_ = _tmp2_;
	_tmp4_ = _g_object_ref0 (_tmp3_);
	result = _tmp4_;
	_gee_promise_unref0 (promise);
	block8_data_unref (_data8_);
	_data8_ = NULL;
	return result;
}

GeeFuture*
gee_future_zip (GeeFuture* self,
                GType a_type,
                GBoxedCopyFunc a_dup_func,
                GDestroyNotify a_destroy_func,
                GType b_type,
                GBoxedCopyFunc b_dup_func,
                GDestroyNotify b_destroy_func,
                GeeFutureZipFunc zip_func,
                gpointer zip_func_target,
                GeeFuture* second)
{
	GeeFutureIface* _iface_;
	g_return_val_if_fail (self != NULL, NULL);
	_iface_ = GEE_FUTURE_GET_INTERFACE (self);
	if (_iface_->zip) {
		return _iface_->zip (self, a_type, a_dup_func, a_destroy_func, b_type, b_dup_func, b_destroy_func, zip_func, zip_func_target, second);
	}
	return NULL;
}

static void
gee_future_do_zip_data_free (gpointer _data)
{
	GeeFutureDoZipData* _data_;
	_data_ = _data;
	_g_object_unref0 (_data_->first);
	_g_object_unref0 (_data_->second);
	_gee_promise_unref0 (_data_->_result_);
	g_slice_free (GeeFutureDoZipData, _data_);
}

static gpointer
_gee_promise_ref0 (gpointer self)
{
	return self ? gee_promise_ref (self) : NULL;
}

static void
gee_future_do_zip (GType a_type,
                   GBoxedCopyFunc a_dup_func,
                   GDestroyNotify a_destroy_func,
                   GType b_type,
                   GBoxedCopyFunc b_dup_func,
                   GDestroyNotify b_destroy_func,
                   GType c_type,
                   GBoxedCopyFunc c_dup_func,
                   GDestroyNotify c_destroy_func,
                   GeeFutureZipFunc zip_func,
                   gpointer zip_func_target,
                   GeeFuture* first,
                   GeeFuture* second,
                   GeePromise* _result_,
                   GAsyncReadyCallback _callback_,
                   gpointer _user_data_)
{
	GeeFutureDoZipData* _data_;
	GeeFuture* _tmp0_;
	GeeFuture* _tmp1_;
	GeePromise* _tmp2_;
	g_return_if_fail (first != NULL);
	g_return_if_fail (second != NULL);
	g_return_if_fail (_result_ != NULL);
	_data_ = g_slice_new0 (GeeFutureDoZipData);
	_data_->_async_result = g_task_new (NULL, NULL, _callback_, _user_data_);
	g_task_set_task_data (_data_->_async_result, _data_, gee_future_do_zip_data_free);
	_data_->zip_func = zip_func;
	_data_->zip_func_target = zip_func_target;
	_tmp0_ = _g_object_ref0 (first);
	_g_object_unref0 (_data_->first);
	_data_->first = _tmp0_;
	_tmp1_ = _g_object_ref0 (second);
	_g_object_unref0 (_data_->second);
	_data_->second = _tmp1_;
	_tmp2_ = _gee_promise_ref0 (_result_);
	_gee_promise_unref0 (_data_->_result_);
	_data_->_result_ = _tmp2_;
	_data_->a_type = a_type;
	_data_->a_dup_func = a_dup_func;
	_data_->a_destroy_func = a_destroy_func;
	_data_->b_type = b_type;
	_data_->b_dup_func = b_dup_func;
	_data_->b_destroy_func = b_destroy_func;
	_data_->c_type = c_type;
	_data_->c_dup_func = c_dup_func;
	_data_->c_destroy_func = c_destroy_func;
	gee_future_do_zip_co (_data_);
}

static void
gee_future_do_zip_finish (GAsyncResult* _res_)
{
	GeeFutureDoZipData* _data_;
	_data_ = g_task_propagate_pointer (G_TASK (_res_), NULL);
}

static void
gee_future_do_zip_ready (GObject* source_object,
                         GAsyncResult* _res_,
                         gpointer _user_data_)
{
	GeeFutureDoZipData* _data_;
	_data_ = _user_data_;
	_data_->_source_object_ = source_object;
	_data_->_res_ = _res_;
	gee_future_do_zip_co (_data_);
}

static gboolean
gee_future_do_zip_co (GeeFutureDoZipData* _data_)
{
	switch (_data_->_state_) {
		case 0:
		goto _state_0;
		case 1:
		goto _state_1;
		case 2:
		goto _state_2;
		default:
		g_assert_not_reached ();
	}
	_state_0:
	{
		_data_->_state_ = 1;
		gee_future_wait_async (_data_->first, gee_future_do_zip_ready, _data_);
		return FALSE;
		_state_1:
		_data_->_tmp0_ = gee_future_wait_finish (_data_->first, _data_->_res_, &_data_->_inner_error0_);
		_data_->_tmp1_ = ((_data_->_tmp0_ != NULL) && (_data_->a_dup_func != NULL)) ? _data_->a_dup_func ((gpointer) _data_->_tmp0_) : ((gpointer) _data_->_tmp0_);
		_data_->left = _data_->_tmp1_;
		if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
			goto __catch0_g_error;
		}
		_data_->_state_ = 2;
		gee_future_wait_async (_data_->second, gee_future_do_zip_ready, _data_);
		return FALSE;
		_state_2:
		_data_->_tmp2_ = gee_future_wait_finish (_data_->second, _data_->_res_, &_data_->_inner_error0_);
		_data_->_tmp3_ = ((_data_->_tmp2_ != NULL) && (_data_->b_dup_func != NULL)) ? _data_->b_dup_func ((gpointer) _data_->_tmp2_) : ((gpointer) _data_->_tmp2_);
		_data_->right = _data_->_tmp3_;
		if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
			((_data_->left == NULL) || (_data_->a_destroy_func == NULL)) ? NULL : (_data_->left = (_data_->a_destroy_func (_data_->left), NULL));
			goto __catch0_g_error;
		}
		_data_->_tmp4_ = _data_->left;
		_data_->_tmp5_ = _data_->right;
		_data_->_tmp6_ = _data_->zip_func (_data_->_tmp4_, _data_->_tmp5_, _data_->zip_func_target);
		gee_promise_set_value (_data_->_result_, _data_->_tmp6_);
		((_data_->right == NULL) || (_data_->b_destroy_func == NULL)) ? NULL : (_data_->right = (_data_->b_destroy_func (_data_->right), NULL));
		((_data_->left == NULL) || (_data_->a_destroy_func == NULL)) ? NULL : (_data_->left = (_data_->a_destroy_func (_data_->left), NULL));
	}
	goto __finally0;
	__catch0_g_error:
	{
		_data_->ex = _data_->_inner_error0_;
		_data_->_inner_error0_ = NULL;
		_data_->_tmp7_ = _data_->ex;
		_data_->ex = NULL;
		gee_promise_set_exception (_data_->_result_, _data_->_tmp7_);
		_g_error_free0 (_data_->ex);
	}
	__finally0:
	if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
		g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _data_->_inner_error0_->message, g_quark_to_string (_data_->_inner_error0_->domain), _data_->_inner_error0_->code);
		g_clear_error (&_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;
}

/**
 * Maps a future value to another future value which is returned (call does not block).
 *
 * Note: As time taken by function does not contribute to
 *   {@link wait_until} and the implementation is allowed to compute
 *   value eagerly by {@link wait_async} it is recommended to put the
 *   larger computation inside the returned future for example by
 *   {@link task}
 *
 * @param func Function applied to {@link value}
 * @return Value of a future returned by function
 *
 * @see map
 */
static Block9Data*
block9_data_ref (Block9Data* _data9_)
{
	g_atomic_int_inc (&_data9_->_ref_count_);
	return _data9_;
}

static void
block9_data_unref (void * _userdata_)
{
	Block9Data* _data9_;
	_data9_ = (Block9Data*) _userdata_;
	if (g_atomic_int_dec_and_test (&_data9_->_ref_count_)) {
		GeeFuture* self;
		GType a_type;
		GBoxedCopyFunc a_dup_func;
		GDestroyNotify a_destroy_func;
		self = _data9_->self;
		a_type = _data9_->a_type;
		a_dup_func = _data9_->a_dup_func;
		a_destroy_func = _data9_->a_destroy_func;
		_g_object_unref0 (self);
		g_slice_free (Block9Data, _data9_);
	}
}

static void
__lambda6_ (Block9Data* _data9_,
            GObject* obj,
            GAsyncResult* res)
{
	GeeFuture* self;
	GType a_type;
	GBoxedCopyFunc a_dup_func;
	GDestroyNotify a_destroy_func;
	self = _data9_->self;
	a_type = _data9_->a_type;
	a_dup_func = _data9_->a_dup_func;
	a_destroy_func = _data9_->a_destroy_func;
	g_return_if_fail (res != NULL);
	gee_future_do_flat_map_finish (res);
}

static void
___lambda6__gasync_ready_callback (GObject* source_object,
                                   GAsyncResult* res,
                                   gpointer self)
{
	__lambda6_ (self, source_object, res);
	block9_data_unref (self);
}

static GeeFuture*
gee_future_real_flat_map (GeeFuture* self,
                          GType a_type,
                          GBoxedCopyFunc a_dup_func,
                          GDestroyNotify a_destroy_func,
                          GeeFutureFlatMapFunc func,
                          gpointer func_target,
                          GDestroyNotify func_target_destroy_notify)
{
	Block9Data* _data9_;
	GeePromise* promise = NULL;
	GeePromise* _tmp0_;
	GeeFutureFlatMapFunc _tmp1_;
	gpointer _tmp1__target;
	GDestroyNotify _tmp1__target_destroy_notify;
	GeeFuture* _tmp2_;
	GeeFuture* _tmp3_;
	GeeFuture* _tmp4_;
	GeeFuture* result;
	_data9_ = g_slice_new0 (Block9Data);
	_data9_->_ref_count_ = 1;
	_data9_->self = g_object_ref (self);
	_data9_->a_type = a_type;
	_data9_->a_dup_func = a_dup_func;
	_data9_->a_destroy_func = a_destroy_func;
	_tmp0_ = gee_promise_new (a_type, (GBoxedCopyFunc) a_dup_func, (GDestroyNotify) a_destroy_func);
	promise = _tmp0_;
	_tmp1_ = func;
	_tmp1__target = func_target;
	_tmp1__target_destroy_notify = func_target_destroy_notify;
	func = NULL;
	func_target = NULL;
	func_target_destroy_notify = NULL;
	gee_future_do_flat_map (GEE_FUTURE_GET_INTERFACE (self)->get_g_type (self), (GBoxedCopyFunc) GEE_FUTURE_GET_INTERFACE (self)->get_g_dup_func (self), (GDestroyNotify) GEE_FUTURE_GET_INTERFACE (self)->get_g_destroy_func (self), a_type, (GBoxedCopyFunc) a_dup_func, (GDestroyNotify) a_destroy_func, _tmp1_, _tmp1__target, _tmp1__target_destroy_notify, self, promise, ___lambda6__gasync_ready_callback, block9_data_ref (_data9_));
	_tmp2_ = gee_promise_get_future (promise);
	_tmp3_ = _tmp2_;
	_tmp4_ = _g_object_ref0 (_tmp3_);
	result = _tmp4_;
	_gee_promise_unref0 (promise);
	block9_data_unref (_data9_);
	_data9_ = NULL;
	(func_target_destroy_notify == NULL) ? NULL : (func_target_destroy_notify (func_target), NULL);
	func = NULL;
	func_target = NULL;
	func_target_destroy_notify = NULL;
	return result;
}

GeeFuture*
gee_future_flat_map (GeeFuture* self,
                     GType a_type,
                     GBoxedCopyFunc a_dup_func,
                     GDestroyNotify a_destroy_func,
                     GeeFutureFlatMapFunc func,
                     gpointer func_target,
                     GDestroyNotify func_target_destroy_notify)
{
	GeeFutureIface* _iface_;
	g_return_val_if_fail (self != NULL, NULL);
	_iface_ = GEE_FUTURE_GET_INTERFACE (self);
	if (_iface_->flat_map) {
		return _iface_->flat_map (self, a_type, a_dup_func, a_destroy_func, func, func_target, func_target_destroy_notify);
	}
	return NULL;
}

static void
gee_future_do_flat_map_data_free (gpointer _data)
{
	GeeFutureDoFlatMapData* _data_;
	_data_ = _data;
	(_data_->func_target_destroy_notify == NULL) ? NULL : (_data_->func_target_destroy_notify (_data_->func_target), NULL);
	_data_->func = NULL;
	_data_->func_target = NULL;
	_data_->func_target_destroy_notify = NULL;
	_g_object_unref0 (_data_->future);
	_gee_promise_unref0 (_data_->promise);
	g_slice_free (GeeFutureDoFlatMapData, _data_);
}

static void
gee_future_do_flat_map (GType a_type,
                        GBoxedCopyFunc a_dup_func,
                        GDestroyNotify a_destroy_func,
                        GType b_type,
                        GBoxedCopyFunc b_dup_func,
                        GDestroyNotify b_destroy_func,
                        GeeFutureFlatMapFunc func,
                        gpointer func_target,
                        GDestroyNotify func_target_destroy_notify,
                        GeeFuture* future,
                        GeePromise* promise,
                        GAsyncReadyCallback _callback_,
                        gpointer _user_data_)
{
	GeeFutureDoFlatMapData* _data_;
	GeeFuture* _tmp0_;
	GeePromise* _tmp1_;
	g_return_if_fail (future != NULL);
	g_return_if_fail (promise != NULL);
	_data_ = g_slice_new0 (GeeFutureDoFlatMapData);
	_data_->_async_result = g_task_new (NULL, NULL, _callback_, _user_data_);
	g_task_set_task_data (_data_->_async_result, _data_, gee_future_do_flat_map_data_free);
	(_data_->func_target_destroy_notify == NULL) ? NULL : (_data_->func_target_destroy_notify (_data_->func_target), NULL);
	_data_->func = NULL;
	_data_->func_target = NULL;
	_data_->func_target_destroy_notify = NULL;
	_data_->func = func;
	_data_->func_target = func_target;
	_data_->func_target_destroy_notify = func_target_destroy_notify;
	_tmp0_ = _g_object_ref0 (future);
	_g_object_unref0 (_data_->future);
	_data_->future = _tmp0_;
	_tmp1_ = _gee_promise_ref0 (promise);
	_gee_promise_unref0 (_data_->promise);
	_data_->promise = _tmp1_;
	_data_->a_type = a_type;
	_data_->a_dup_func = a_dup_func;
	_data_->a_destroy_func = a_destroy_func;
	_data_->b_type = b_type;
	_data_->b_dup_func = b_dup_func;
	_data_->b_destroy_func = b_destroy_func;
	gee_future_do_flat_map_co (_data_);
}

static void
gee_future_do_flat_map_finish (GAsyncResult* _res_)
{
	GeeFutureDoFlatMapData* _data_;
	_data_ = g_task_propagate_pointer (G_TASK (_res_), NULL);
}

static void
gee_future_do_flat_map_ready (GObject* source_object,
                              GAsyncResult* _res_,
                              gpointer _user_data_)
{
	GeeFutureDoFlatMapData* _data_;
	_data_ = _user_data_;
	_data_->_source_object_ = source_object;
	_data_->_res_ = _res_;
	gee_future_do_flat_map_co (_data_);
}

static gboolean
gee_future_do_flat_map_co (GeeFutureDoFlatMapData* _data_)
{
	switch (_data_->_state_) {
		case 0:
		goto _state_0;
		case 1:
		goto _state_1;
		case 2:
		goto _state_2;
		default:
		g_assert_not_reached ();
	}
	_state_0:
	{
		_data_->_state_ = 1;
		gee_future_wait_async (_data_->future, gee_future_do_flat_map_ready, _data_);
		return FALSE;
		_state_1:
		_data_->_tmp0_ = gee_future_wait_finish (_data_->future, _data_->_res_, &_data_->_inner_error0_);
		_data_->_tmp1_ = ((_data_->_tmp0_ != NULL) && (_data_->a_dup_func != NULL)) ? _data_->a_dup_func ((gpointer) _data_->_tmp0_) : ((gpointer) _data_->_tmp0_);
		_data_->input = _data_->_tmp1_;
		if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
			if (g_error_matches (_data_->_inner_error0_, GEE_FUTURE_ERROR, GEE_FUTURE_ERROR_EXCEPTION)) {
				goto __catch0_gee_future_error_exception;
			}
			goto __catch0_g_error;
		}
		_data_->_tmp2_ = _data_->input;
		_data_->_tmp3_ = _data_->func (_data_->_tmp2_, _data_->func_target);
		_data_->output_future = _data_->_tmp3_;
		{
			_data_->_tmp4_ = _data_->output_future;
			_data_->_state_ = 2;
			gee_future_wait_async (_data_->_tmp4_, gee_future_do_flat_map_ready, _data_);
			return FALSE;
			_state_2:
			_data_->_tmp5_ = gee_future_wait_finish (_data_->_tmp4_, _data_->_res_, &_data_->_inner_error0_);
			_data_->_tmp6_ = ((_data_->_tmp5_ != NULL) && (_data_->b_dup_func != NULL)) ? _data_->b_dup_func ((gpointer) _data_->_tmp5_) : ((gpointer) _data_->_tmp5_);
			_data_->output = _data_->_tmp6_;
			if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
				if (g_error_matches (_data_->_inner_error0_, GEE_FUTURE_ERROR, GEE_FUTURE_ERROR_EXCEPTION)) {
					goto __catch1_gee_future_error_exception;
				}
				goto __finally1;
			}
			_data_->_tmp7_ = _data_->output;
			_data_->output = NULL;
			gee_promise_set_value (_data_->promise, _data_->_tmp7_);
			((_data_->output == NULL) || (_data_->b_destroy_func == NULL)) ? NULL : (_data_->output = (_data_->b_destroy_func (_data_->output), NULL));
		}
		goto __finally1;
		__catch1_gee_future_error_exception:
		{
			g_clear_error (&_data_->_inner_error0_);
			_data_->_tmp8_ = _data_->output_future;
			_data_->_tmp9_ = gee_future_get_exception (_data_->_tmp8_);
			_data_->_tmp10_ = _data_->_tmp9_;
			_data_->_tmp11_ = _g_error_copy0 (_data_->_tmp10_);
			gee_promise_set_exception (_data_->promise, _data_->_tmp11_);
		}
		__finally1:
		if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
			_g_object_unref0 (_data_->output_future);
			((_data_->input == NULL) || (_data_->a_destroy_func == NULL)) ? NULL : (_data_->input = (_data_->a_destroy_func (_data_->input), NULL));
			if (g_error_matches (_data_->_inner_error0_, GEE_FUTURE_ERROR, GEE_FUTURE_ERROR_EXCEPTION)) {
				goto __catch0_gee_future_error_exception;
			}
			goto __catch0_g_error;
		}
		_g_object_unref0 (_data_->output_future);
		((_data_->input == NULL) || (_data_->a_destroy_func == NULL)) ? NULL : (_data_->input = (_data_->a_destroy_func (_data_->input), NULL));
	}
	goto __finally0;
	__catch0_gee_future_error_exception:
	{
		g_clear_error (&_data_->_inner_error0_);
		_data_->_tmp12_ = gee_future_get_exception (_data_->future);
		_data_->_tmp13_ = _data_->_tmp12_;
		_data_->_tmp14_ = _g_error_copy0 (_data_->_tmp13_);
		gee_promise_set_exception (_data_->promise, _data_->_tmp14_);
	}
	goto __finally0;
	__catch0_g_error:
	{
		_data_->ex = _data_->_inner_error0_;
		_data_->_inner_error0_ = NULL;
		_data_->_tmp15_ = _data_->ex;
		_data_->ex = NULL;
		gee_promise_set_exception (_data_->promise, _data_->_tmp15_);
		_g_error_free0 (_data_->ex);
	}
	__finally0:
	if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
		(_data_->func_target_destroy_notify == NULL) ? NULL : (_data_->func_target_destroy_notify (_data_->func_target), NULL);
		_data_->func = NULL;
		_data_->func_target = NULL;
		_data_->func_target_destroy_notify = NULL;
		g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _data_->_inner_error0_->message, g_quark_to_string (_data_->_inner_error0_->domain), _data_->_inner_error0_->code);
		g_clear_error (&_data_->_inner_error0_);
		g_object_unref (_data_->_async_result);
		return FALSE;
	}
	(_data_->func_target_destroy_notify == NULL) ? NULL : (_data_->func_target_destroy_notify (_data_->func_target), NULL);
	_data_->func = NULL;
	_data_->func_target = NULL;
	_data_->func_target_destroy_notify = NULL;
	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;
}

gconstpointer
gee_future_get_value (GeeFuture* self)
{
	GeeFutureIface* _iface_;
	g_return_val_if_fail (self != NULL, NULL);
	_iface_ = GEE_FUTURE_GET_INTERFACE (self);
	if (_iface_->get_value) {
		return _iface_->get_value (self);
	}
	return NULL;
}

static gconstpointer
gee_future_real_get_value (GeeFuture* base)
{
	gconstpointer result;
	GeeFuture* self;
	GError* _inner_error0_ = NULL;
	self = base;
	{
		gconstpointer _tmp0_ = NULL;
		gconstpointer _tmp1_;
		_tmp1_ = gee_future_wait (self, &_inner_error0_);
		_tmp0_ = _tmp1_;
		if (G_UNLIKELY (_inner_error0_ != NULL)) {
			if (_inner_error0_->domain == GEE_FUTURE_ERROR) {
				goto __catch0_gee_future_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;
		}
		result = _tmp0_;
		return result;
	}
	goto __finally0;
	__catch0_gee_future_error:
	{
		g_clear_error (&_inner_error0_);
		result = NULL;
		return result;
	}
	__finally0:
	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;
}

gboolean
gee_future_get_ready (GeeFuture* self)
{
	GeeFutureIface* _iface_;
	g_return_val_if_fail (self != NULL, FALSE);
	_iface_ = GEE_FUTURE_GET_INTERFACE (self);
	if (_iface_->get_ready) {
		return _iface_->get_ready (self);
	}
	return FALSE;
}

GError*
gee_future_get_exception (GeeFuture* self)
{
	GeeFutureIface* _iface_;
	g_return_val_if_fail (self != NULL, NULL);
	_iface_ = GEE_FUTURE_GET_INTERFACE (self);
	if (_iface_->get_exception) {
		return _iface_->get_exception (self);
	}
	return NULL;
}

 G_GNUC_INTERNAL void
gee_future_source_func_array_element_init (GeeFutureSourceFuncArrayElement *self,
                                           GSourceFunc func,
                                           gpointer func_target,
                                           GDestroyNotify func_target_destroy_notify)
{
	GSourceFunc _tmp0_;
	gpointer _tmp0__target;
	GDestroyNotify _tmp0__target_destroy_notify;
	memset (self, 0, sizeof (GeeFutureSourceFuncArrayElement));
	_tmp0_ = func;
	_tmp0__target = func_target;
	_tmp0__target_destroy_notify = func_target_destroy_notify;
	func = NULL;
	func_target = NULL;
	func_target_destroy_notify = NULL;
	((*self).func_target_destroy_notify == NULL) ? NULL : ((*self).func_target_destroy_notify ((*self).func_target), NULL);
	(*self).func = NULL;
	(*self).func_target = NULL;
	(*self).func_target_destroy_notify = NULL;
	(*self).func = _tmp0_;
	(*self).func_target = _tmp0__target;
	(*self).func_target_destroy_notify = _tmp0__target_destroy_notify;
	(func_target_destroy_notify == NULL) ? NULL : (func_target_destroy_notify (func_target), NULL);
	func = NULL;
	func_target = NULL;
	func_target_destroy_notify = NULL;
}

 G_GNUC_INTERNAL void
gee_future_source_func_array_element_copy (const GeeFutureSourceFuncArrayElement* self,
                                           GeeFutureSourceFuncArrayElement* dest)
{
	GSourceFunc _tmp0_;
	gpointer _tmp0__target;
	_tmp0_ = (*self).func;
	_tmp0__target = (*self).func_target;
	((*dest).func_target_destroy_notify == NULL) ? NULL : ((*dest).func_target_destroy_notify ((*dest).func_target), NULL);
	(*dest).func = NULL;
	(*dest).func_target = NULL;
	(*dest).func_target_destroy_notify = NULL;
	(*dest).func = _tmp0_;
	(*dest).func_target = _tmp0__target;
	(*dest).func_target_destroy_notify = NULL;
}

 G_GNUC_INTERNAL void
gee_future_source_func_array_element_destroy (GeeFutureSourceFuncArrayElement* self)
{
	((*self).func_target_destroy_notify == NULL) ? NULL : ((*self).func_target_destroy_notify ((*self).func_target), NULL);
	(*self).func = NULL;
	(*self).func_target = NULL;
	(*self).func_target_destroy_notify = NULL;
}

GeeFutureSourceFuncArrayElement*
gee_future_source_func_array_element_dup (const GeeFutureSourceFuncArrayElement* self)
{
	GeeFutureSourceFuncArrayElement* dup;
	dup = g_new0 (GeeFutureSourceFuncArrayElement, 1);
	gee_future_source_func_array_element_copy (self, dup);
	return dup;
}

 G_GNUC_INTERNAL void
gee_future_source_func_array_element_free (GeeFutureSourceFuncArrayElement* self)
{
	gee_future_source_func_array_element_destroy (self);
	g_free (self);
}

static GType
gee_future_source_func_array_element_get_type_once (void)
{
	GType gee_future_source_func_array_element_type_id;
	gee_future_source_func_array_element_type_id = g_boxed_type_register_static ("GeeFutureSourceFuncArrayElement", (GBoxedCopyFunc) gee_future_source_func_array_element_dup, (GBoxedFreeFunc) gee_future_source_func_array_element_free);
	return gee_future_source_func_array_element_type_id;
}

 G_GNUC_INTERNAL GType
gee_future_source_func_array_element_get_type (void)
{
	static volatile gsize gee_future_source_func_array_element_type_id__once = 0;
	if (g_once_init_enter (&gee_future_source_func_array_element_type_id__once)) {
		GType gee_future_source_func_array_element_type_id;
		gee_future_source_func_array_element_type_id = gee_future_source_func_array_element_get_type_once ();
		g_once_init_leave (&gee_future_source_func_array_element_type_id__once, gee_future_source_func_array_element_type_id);
	}
	return gee_future_source_func_array_element_type_id__once;
}

static void
gee_future_default_init (GeeFutureIface * iface,
                         gpointer iface_data)
{
	/**
	 * Checks if value is ready. If it is calls to {@link wait} and
	 * {@link wait_until} will not block and value is returned immediately.
	 */
	g_object_interface_install_property (iface, g_param_spec_boolean ("ready", "ready", "ready", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	/**
	 * Checks the exception that have been set. I.e. if the computation
	 * has thrown the exception it should be set here and the {@link wait},
	 * {@link wait_until} and {@link wait_async} should throw
	 * {@link FutureError.EXCEPTION}.
	 *
	 * @since 0.11.5
	 */
	g_object_interface_install_property (iface, g_param_spec_boxed ("exception", "exception", "exception", G_TYPE_ERROR, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	iface->map = gee_future_real_map;
	iface->light_map_fixed = gee_future_real_light_map;
	iface->light_map = gee_future_real_light_map_broken;
	iface->zip = gee_future_real_zip;
	iface->flat_map = gee_future_real_flat_map;
	iface->get_value = gee_future_real_get_value;
}

/**
 * Future is a value which might not yet be computed - for example it is calculated
 * in different thread or depends on I/O value.
 *
 * All methods can be called from many threads as part of interface.
 *
 * Note: Statement that call does not block does not mean that it is lock-free.
 *   Internally the implementation is allowed to take mutex but it should guarantee
 *   that it is not for a long time (including blocking on anything else, I/O calls
 *   or callbacks).
 *
 * @see Promise
 * @see Lazy
 * @see task
 * @see async_task
 * @since 0.11.0
 */
static GType
gee_future_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (GeeFutureIface), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gee_future_default_init, (GClassFinalizeFunc) NULL, NULL, 0, 0, (GInstanceInitFunc) NULL, NULL };
	GType gee_future_type_id;
	gee_future_type_id = g_type_register_static (G_TYPE_INTERFACE, "GeeFuture", &g_define_type_info, 0);
	g_type_interface_add_prerequisite (gee_future_type_id, G_TYPE_OBJECT);
	return gee_future_type_id;
}

GType
gee_future_get_type (void)
{
	static volatile gsize gee_future_type_id__once = 0;
	if (g_once_init_enter (&gee_future_type_id__once)) {
		GType gee_future_type_id;
		gee_future_type_id = gee_future_get_type_once ();
		g_once_init_leave (&gee_future_type_id__once, gee_future_type_id);
	}
	return gee_future_type_id__once;
}

GQuark
gee_future_error_quark (void)
{
	return g_quark_from_static_string ("gee-future-error-quark");
}

static GType
gee_future_error_get_type_once (void)
{
	static const GEnumValue values[] = {{GEE_FUTURE_ERROR_ABANDON_PROMISE, "GEE_FUTURE_ERROR_ABANDON_PROMISE", "abandon-promise"}, {GEE_FUTURE_ERROR_EXCEPTION, "GEE_FUTURE_ERROR_EXCEPTION", "exception"}, {0, NULL, NULL}};
	GType gee_future_error_type_id;
	gee_future_error_type_id = g_enum_register_static ("GeeFutureError", values);
	return gee_future_error_type_id;
}

GType
gee_future_error_get_type (void)
{
	static volatile gsize gee_future_error_type_id__once = 0;
	if (g_once_init_enter (&gee_future_error_type_id__once)) {
		GType gee_future_error_type_id;
		gee_future_error_type_id = gee_future_error_get_type_once ();
		g_once_init_leave (&gee_future_error_type_id__once, gee_future_error_type_id);
	}
	return gee_future_error_type_id__once;
}

