// Helper function to attach a cb to a future without creating a new wrapper directly.
        // It'll be used in the construtor, to attach the cleaning cb to an intermediate future.
        private static IntPtr ThenRaw(IntPtr previous, ResolvedCb cb)
        {
            FutureDesc desc = new FutureDesc();

            desc.cb = NativeResolvedCbDelegate;
            GCHandle handle = GCHandle.Alloc(cb);

            desc.data = GCHandle.ToIntPtr(handle);
            return(eina_future_then_from_desc(previous, desc));
        }
Beispiel #2
0
        /// <summary>
        /// Creates a Future attached to the given Promise.
        ///
        /// Optionally a resolved callback may be provided. If so, it will be chained
        /// before the returned future.
        /// </summary>
        public Future(Promise promise, ResolvedCb cb = null)
        {
            IntPtr intermediate = eina_future_new(promise.Handle);

            Handle = ThenRaw(intermediate, (Eina.Value value) => {
                if (cb != null)
                {
                    value = cb(value);
                }
                Handle = IntPtr.Zero;
                return(value);
            });
        }
Beispiel #3
0
        private static Eina.ValueNative NativeResolvedCb(IntPtr data, Eina.ValueNative value, IntPtr dead_future)
        {
            GCHandle   handle = GCHandle.FromIntPtr(data);
            ResolvedCb cb     = handle.Target as ResolvedCb;

            if (cb != null)
            {
                value = cb(value);
            }
            else
            {
                Eina.Log.Warning("Failed to get future callback.");
            }
            handle.Free();
            return(value);
        }
        /// <summary>
        /// Helper method for chaining a group of callbacks in a single go.
        ///
        /// It is just syntatic sugar for sequential Then() calls, without creating intermediate
        /// futures explicitly.
        /// </summary>
        public Future Chain(IEnumerable <ResolvedCb> cbs)
        {
            SanityChecks();
            System.Collections.Generic.IList <ResolvedCb> cbsList = cbs.ToList();
            FutureDesc[] descs = new FutureDesc[cbsList.Count() + 1]; // +1 due to the null-cb terminating descriptor.
            int          i     = 0;

            try
            {
                for (; i < cbsList.Count(); i++)
                {
                    ResolvedCb cb = cbsList[i];
                    descs[i].cb = NativeResolvedCbDelegate;
                    GCHandle handle = GCHandle.Alloc(cb);
                    descs[i].data = GCHandle.ToIntPtr(handle);
                }

                descs[i].cb   = null;
                descs[i].data = IntPtr.Zero;
            }
            catch (Exception e)
            {
                for (int j = 0; j <= i; j++)
                {
                    if (descs[i].data == IntPtr.Zero)
                    {
                        continue;
                    }

                    GCHandle handle = GCHandle.FromIntPtr(descs[i].data);
                    handle.Free();
                }

                Eina.Log.Error($"Failed to create native future description for callbacks. Error: {e.ToString()}");
                return(null);
            }

            return(new Future(eina_future_chain_array(Handle, descs)));
        }
        private static Eina.ValueNative NativeResolvedCb(IntPtr data, Eina.ValueNative value, IntPtr dead_future)
        {
            GCHandle   handle = GCHandle.FromIntPtr(data);
            ResolvedCb cb     = handle.Target as ResolvedCb;

            if (cb != null)
            {
                Eina.Value managedValue = cb(value);
                // Both `value` and `managedValue` will point to the same internal value data.
                // Avoid C# wrapper invalidating the underlying C Eina_Value as the eina_future.c
                // code will release it.
                value = managedValue.GetNative();
                managedValue.ReleaseOwnership();
            }
            else
            {
                Eina.Log.Warning("Failed to get future callback.");
            }

            handle.Free();
            return(value);
        }
 /// <summary>
 /// Creates a new future to be called after this one.
 ///
 /// Once the promise this future is attached to resolves, the callbacks on the chain
 /// are called in the order they were chained.
 ///
 /// CAUTION: Calling Then() on a future that had it called before will replace the previous chain
 /// from this point on.
 /// </summary>
 public Future Then(ResolvedCb cb)
 {
     SanityChecks();
     return(new Future(ThenRaw(Handle, cb)));
 }