efl/src/bindings/mono/eina_mono/eina_promises.cs

486 lines
16 KiB
C#
Raw Normal View History

/*
* Copyright 2019 by its authors. See AUTHORS.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel;
using System.Diagnostics.Contracts;
csharp: Change to new class API. Summary: As discussed in T7204: - Eo Interfaces/mixins -> C# Interfaces with concrete class implementations - Eo Regular/Abstracts -> Proper C# classes - Added some new generators and helper methods. - Refactored the class generator, splitting into helper methods Eo handles now are stored only in the "root" class in any given inheritance tree (generally, Efl.Object), and accessible to each child. Methods also are defined in a single place instead of repeatedly generated in everyfile, reducing the size of the generated .dll from 30MB to around 4.5MB. Mixins are generated as C# interfaces but any regular class it inherits from is lost, as we can't have interfaces inheriting from regular classes. This will be dealt with in a later commit. Summary of API Changes: - Merged Inherit/Concrete classes. (These suffixes disappear from regular classes). - Interface still have implementations with 'Concrete' suffix for when they are returned from methods. - Removed 'I' from interface names. - Removed interfaces for regular/abstract Eo classes. - Concrete classes for interfaces/mixins hold the event argument struct. - Removed '_' from classes, enums, structs, etc, as indicated in C# naming conventions. - Namespaces are now Camel.Cased. - Renamed IWrapper's raw_handle/raw_klass to NativeHandle/NativeClass Also renamed the test classes as after the namespace change, the test namespace Test can conflict with the helper Test namespace. (And use more meaningful names than Test.Testing...) Also Fixes T7336 by removing a deprecated example and adding efl_loop_timer_example to build system. Fixes T7451 by hiding the class_get DllImports and renaming the IWrapper fields. The native handlers are used in the manual binding. Still need to work: - As there are still some events names clashing (e.g. Efl.Ui.Bg with "resize" from Efl.Gfx.Entity and Efl.Gfx.Image), Events are currently declared on the interface and implemented "namespaced" in the classes, requiring the cast to the interface to access the event. - The Mixin Conundrum. Mixin inheritance will be dealt in a future commit. Depends on D7260 Reviewers: segfaultxavi, vitor.sousa, felipealmeida, Jaehyun_Cho Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7451, T7336 Differential Revision: https://phab.enlightenment.org/D7262
2018-11-29 15:04:37 -08:00
using static Eina.EinaNative.PromiseNativeMethods;
namespace Eina
{
namespace EinaNative
{
[EditorBrowsable(EditorBrowsableState.Never)]
static internal class PromiseNativeMethods
{
internal delegate void Promise_Cancel_Cb(IntPtr data, IntPtr dead);
[DllImport(efl.Libs.Ecore)]
internal static extern IntPtr efl_loop_promise_new(IntPtr obj, Promise_Cancel_Cb cancel_cb, IntPtr data);
[DllImport(efl.Libs.Eina)]
internal static extern IntPtr eina_promise_new(IntPtr scheduler, Promise_Cancel_Cb cancel_cb, IntPtr data);
[DllImport(efl.Libs.Eina)]
csharp: Change to new class API. Summary: As discussed in T7204: - Eo Interfaces/mixins -> C# Interfaces with concrete class implementations - Eo Regular/Abstracts -> Proper C# classes - Added some new generators and helper methods. - Refactored the class generator, splitting into helper methods Eo handles now are stored only in the "root" class in any given inheritance tree (generally, Efl.Object), and accessible to each child. Methods also are defined in a single place instead of repeatedly generated in everyfile, reducing the size of the generated .dll from 30MB to around 4.5MB. Mixins are generated as C# interfaces but any regular class it inherits from is lost, as we can't have interfaces inheriting from regular classes. This will be dealt with in a later commit. Summary of API Changes: - Merged Inherit/Concrete classes. (These suffixes disappear from regular classes). - Interface still have implementations with 'Concrete' suffix for when they are returned from methods. - Removed 'I' from interface names. - Removed interfaces for regular/abstract Eo classes. - Concrete classes for interfaces/mixins hold the event argument struct. - Removed '_' from classes, enums, structs, etc, as indicated in C# naming conventions. - Namespaces are now Camel.Cased. - Renamed IWrapper's raw_handle/raw_klass to NativeHandle/NativeClass Also renamed the test classes as after the namespace change, the test namespace Test can conflict with the helper Test namespace. (And use more meaningful names than Test.Testing...) Also Fixes T7336 by removing a deprecated example and adding efl_loop_timer_example to build system. Fixes T7451 by hiding the class_get DllImports and renaming the IWrapper fields. The native handlers are used in the manual binding. Still need to work: - As there are still some events names clashing (e.g. Efl.Ui.Bg with "resize" from Efl.Gfx.Entity and Efl.Gfx.Image), Events are currently declared on the interface and implemented "namespaced" in the classes, requiring the cast to the interface to access the event. - The Mixin Conundrum. Mixin inheritance will be dealt in a future commit. Depends on D7260 Reviewers: segfaultxavi, vitor.sousa, felipealmeida, Jaehyun_Cho Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7451, T7336 Differential Revision: https://phab.enlightenment.org/D7262
2018-11-29 15:04:37 -08:00
internal static extern void eina_promise_resolve(IntPtr scheduler, Eina.ValueNative value);
[DllImport(efl.Libs.Eina)]
csharp: Change to new class API. Summary: As discussed in T7204: - Eo Interfaces/mixins -> C# Interfaces with concrete class implementations - Eo Regular/Abstracts -> Proper C# classes - Added some new generators and helper methods. - Refactored the class generator, splitting into helper methods Eo handles now are stored only in the "root" class in any given inheritance tree (generally, Efl.Object), and accessible to each child. Methods also are defined in a single place instead of repeatedly generated in everyfile, reducing the size of the generated .dll from 30MB to around 4.5MB. Mixins are generated as C# interfaces but any regular class it inherits from is lost, as we can't have interfaces inheriting from regular classes. This will be dealt with in a later commit. Summary of API Changes: - Merged Inherit/Concrete classes. (These suffixes disappear from regular classes). - Interface still have implementations with 'Concrete' suffix for when they are returned from methods. - Removed 'I' from interface names. - Removed interfaces for regular/abstract Eo classes. - Concrete classes for interfaces/mixins hold the event argument struct. - Removed '_' from classes, enums, structs, etc, as indicated in C# naming conventions. - Namespaces are now Camel.Cased. - Renamed IWrapper's raw_handle/raw_klass to NativeHandle/NativeClass Also renamed the test classes as after the namespace change, the test namespace Test can conflict with the helper Test namespace. (And use more meaningful names than Test.Testing...) Also Fixes T7336 by removing a deprecated example and adding efl_loop_timer_example to build system. Fixes T7451 by hiding the class_get DllImports and renaming the IWrapper fields. The native handlers are used in the manual binding. Still need to work: - As there are still some events names clashing (e.g. Efl.Ui.Bg with "resize" from Efl.Gfx.Entity and Efl.Gfx.Image), Events are currently declared on the interface and implemented "namespaced" in the classes, requiring the cast to the interface to access the event. - The Mixin Conundrum. Mixin inheritance will be dealt in a future commit. Depends on D7260 Reviewers: segfaultxavi, vitor.sousa, felipealmeida, Jaehyun_Cho Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7451, T7336 Differential Revision: https://phab.enlightenment.org/D7262
2018-11-29 15:04:37 -08:00
internal static extern void eina_promise_reject(IntPtr scheduler, Eina.Error reason);
efl-csharp: fix resource deallocation causing errors everywhere Summary: This commit mainly fixes errors caused by deallocating resources in the garbage collector thread. Using `ecore_main_loop_thread_safe_call_async` to queue resource deallocation in the main thread seems to solve it. Also, some `efl_ref` calls are added in places they were missing, mainly objects that unref in the destructor thus taking ownership if efl_ref is not called. Also fix improper resource deallocation in tests that were causing it to crash, enabling it to call Efl.All.Shutdown again. This allocation and the deallocation process was moved from the Eo class constructor to static class methods that are called in the test 'set up' and 'tear down' methods. Queuing resource deallocation in the main thread make it mandatory that tests call `Efl.App.AppMain.Iterate()` if they want to check proper resource deallocation (like TestFunctionPointers.set_callback_inherited_called_from_c). Extras: Remove duplicated declaration of 'eflcustomexportsmono' in meson in order to fix some linking problems. Remove some unused code around deallocation functions that had to be reworked. Object allocation is now supplied with the call site information it expects (file name and line for _efl_add_start). Depends on D8550 Test Plan: meson test Reviewers: felipealmeida, lauromoura, cedric, segfaultxavi Reviewed By: lauromoura Subscribers: segfaultxavi Tags: #efl_language_bindings, #do_not_merge Differential Revision: https://phab.enlightenment.org/D8431
2019-04-05 15:57:29 -07:00
[DllImport(efl.Libs.CustomExports)]
internal static extern void efl_mono_thread_safe_promise_reject(IntPtr scheduler, Eina.Error reason);
[DllImport(efl.Libs.Eina)]
internal static extern IntPtr eina_future_new(IntPtr promise);
[DllImport(efl.Libs.Eina)]
internal static extern void eina_future_cancel(IntPtr future);
[DllImport(efl.Libs.Ecore)]
internal static extern IntPtr efl_loop_future_scheduler_get(IntPtr obj);
[DllImport(efl.Libs.Eina)]
internal static extern IntPtr eina_future_then_from_desc(IntPtr prev, FutureDesc desc);
[DllImport(efl.Libs.Eina)]
internal static extern IntPtr eina_future_chain_array(IntPtr prev, FutureDesc[] desc);
csharp: Change to new class API. Summary: As discussed in T7204: - Eo Interfaces/mixins -> C# Interfaces with concrete class implementations - Eo Regular/Abstracts -> Proper C# classes - Added some new generators and helper methods. - Refactored the class generator, splitting into helper methods Eo handles now are stored only in the "root" class in any given inheritance tree (generally, Efl.Object), and accessible to each child. Methods also are defined in a single place instead of repeatedly generated in everyfile, reducing the size of the generated .dll from 30MB to around 4.5MB. Mixins are generated as C# interfaces but any regular class it inherits from is lost, as we can't have interfaces inheriting from regular classes. This will be dealt with in a later commit. Summary of API Changes: - Merged Inherit/Concrete classes. (These suffixes disappear from regular classes). - Interface still have implementations with 'Concrete' suffix for when they are returned from methods. - Removed 'I' from interface names. - Removed interfaces for regular/abstract Eo classes. - Concrete classes for interfaces/mixins hold the event argument struct. - Removed '_' from classes, enums, structs, etc, as indicated in C# naming conventions. - Namespaces are now Camel.Cased. - Renamed IWrapper's raw_handle/raw_klass to NativeHandle/NativeClass Also renamed the test classes as after the namespace change, the test namespace Test can conflict with the helper Test namespace. (And use more meaningful names than Test.Testing...) Also Fixes T7336 by removing a deprecated example and adding efl_loop_timer_example to build system. Fixes T7451 by hiding the class_get DllImports and renaming the IWrapper fields. The native handlers are used in the manual binding. Still need to work: - As there are still some events names clashing (e.g. Efl.Ui.Bg with "resize" from Efl.Gfx.Entity and Efl.Gfx.Image), Events are currently declared on the interface and implemented "namespaced" in the classes, requiring the cast to the interface to access the event. - The Mixin Conundrum. Mixin inheritance will be dealt in a future commit. Depends on D7260 Reviewers: segfaultxavi, vitor.sousa, felipealmeida, Jaehyun_Cho Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7451, T7336 Differential Revision: https://phab.enlightenment.org/D7262
2018-11-29 15:04:37 -08:00
internal delegate Eina.ValueNative FutureCb(IntPtr data, Eina.ValueNative value, IntPtr dead_future);
[StructLayout(LayoutKind.Sequential)]
internal struct FutureDesc
{
internal FutureCb cb;
internal IntPtr data;
internal IntPtr storage; // Internal use by eina
public FutureDesc(FutureCb cb, IntPtr data, IntPtr storage)
{
this.cb = cb;
this.data = data;
this.storage = storage;
}
}
}
} // namespace EinaNative
/// <summary>
/// Promises act as placeholders for a value that may be available in the future.
///
/// With a Promise you can attach futures to it, which will be used to notify of the value being available.
///
/// <para>Since Efl 1.23.</para>
/// </summary>
public class Promise : IDisposable
{
internal IntPtr Handle;
private GCHandle CleanupHandle;
/// <summary>Delegate for functions that will be called upon a promise cancellation.
/// <para>Since EFL 1.23.</para>
/// </summary>
public delegate void CancelCb();
/// <summary>
/// Creates a new Promise with the given callback.
///
/// Currently, creating a promise directly uses the Main Loop scheduler the source of notifications (i.e. the
/// future callbacks will be called mainly from a loop iteration).
/// <para>Since EFL 1.23.</para>
/// </summary>
public Promise(CancelCb cancelCb = null)
{
Efl.Loop loop = Efl.App.AppMain;
// Should we be able to pass different schedulers?
csharp: Change to new class API. Summary: As discussed in T7204: - Eo Interfaces/mixins -> C# Interfaces with concrete class implementations - Eo Regular/Abstracts -> Proper C# classes - Added some new generators and helper methods. - Refactored the class generator, splitting into helper methods Eo handles now are stored only in the "root" class in any given inheritance tree (generally, Efl.Object), and accessible to each child. Methods also are defined in a single place instead of repeatedly generated in everyfile, reducing the size of the generated .dll from 30MB to around 4.5MB. Mixins are generated as C# interfaces but any regular class it inherits from is lost, as we can't have interfaces inheriting from regular classes. This will be dealt with in a later commit. Summary of API Changes: - Merged Inherit/Concrete classes. (These suffixes disappear from regular classes). - Interface still have implementations with 'Concrete' suffix for when they are returned from methods. - Removed 'I' from interface names. - Removed interfaces for regular/abstract Eo classes. - Concrete classes for interfaces/mixins hold the event argument struct. - Removed '_' from classes, enums, structs, etc, as indicated in C# naming conventions. - Namespaces are now Camel.Cased. - Renamed IWrapper's raw_handle/raw_klass to NativeHandle/NativeClass Also renamed the test classes as after the namespace change, the test namespace Test can conflict with the helper Test namespace. (And use more meaningful names than Test.Testing...) Also Fixes T7336 by removing a deprecated example and adding efl_loop_timer_example to build system. Fixes T7451 by hiding the class_get DllImports and renaming the IWrapper fields. The native handlers are used in the manual binding. Still need to work: - As there are still some events names clashing (e.g. Efl.Ui.Bg with "resize" from Efl.Gfx.Entity and Efl.Gfx.Image), Events are currently declared on the interface and implemented "namespaced" in the classes, requiring the cast to the interface to access the event. - The Mixin Conundrum. Mixin inheritance will be dealt in a future commit. Depends on D7260 Reviewers: segfaultxavi, vitor.sousa, felipealmeida, Jaehyun_Cho Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7451, T7336 Differential Revision: https://phab.enlightenment.org/D7262
2018-11-29 15:04:37 -08:00
IntPtr scheduler = efl_loop_future_scheduler_get(loop.NativeHandle);
IntPtr cb_data = IntPtr.Zero;
// A safety clean callback to mark this wrapper as invalid
CancelCb safetyCb = () =>
{
Handle = IntPtr.Zero;
if (cancelCb != null)
{
cancelCb();
}
};
CleanupHandle = GCHandle.Alloc(safetyCb);
cb_data = GCHandle.ToIntPtr(CleanupHandle);
this.Handle = eina_promise_new(scheduler, NativeCancelCb, cb_data);
}
private static void NativeCancelCb(IntPtr data, IntPtr dead)
{
if (data == IntPtr.Zero)
{
return;
}
GCHandle handle = GCHandle.FromIntPtr(data);
CancelCb cb = handle.Target as CancelCb;
if (cb != null)
{
cb();
}
else
{
csharp: Change to new class API. Summary: As discussed in T7204: - Eo Interfaces/mixins -> C# Interfaces with concrete class implementations - Eo Regular/Abstracts -> Proper C# classes - Added some new generators and helper methods. - Refactored the class generator, splitting into helper methods Eo handles now are stored only in the "root" class in any given inheritance tree (generally, Efl.Object), and accessible to each child. Methods also are defined in a single place instead of repeatedly generated in everyfile, reducing the size of the generated .dll from 30MB to around 4.5MB. Mixins are generated as C# interfaces but any regular class it inherits from is lost, as we can't have interfaces inheriting from regular classes. This will be dealt with in a later commit. Summary of API Changes: - Merged Inherit/Concrete classes. (These suffixes disappear from regular classes). - Interface still have implementations with 'Concrete' suffix for when they are returned from methods. - Removed 'I' from interface names. - Removed interfaces for regular/abstract Eo classes. - Concrete classes for interfaces/mixins hold the event argument struct. - Removed '_' from classes, enums, structs, etc, as indicated in C# naming conventions. - Namespaces are now Camel.Cased. - Renamed IWrapper's raw_handle/raw_klass to NativeHandle/NativeClass Also renamed the test classes as after the namespace change, the test namespace Test can conflict with the helper Test namespace. (And use more meaningful names than Test.Testing...) Also Fixes T7336 by removing a deprecated example and adding efl_loop_timer_example to build system. Fixes T7451 by hiding the class_get DllImports and renaming the IWrapper fields. The native handlers are used in the manual binding. Still need to work: - As there are still some events names clashing (e.g. Efl.Ui.Bg with "resize" from Efl.Gfx.Entity and Efl.Gfx.Image), Events are currently declared on the interface and implemented "namespaced" in the classes, requiring the cast to the interface to access the event. - The Mixin Conundrum. Mixin inheritance will be dealt in a future commit. Depends on D7260 Reviewers: segfaultxavi, vitor.sousa, felipealmeida, Jaehyun_Cho Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7451, T7336 Differential Revision: https://phab.enlightenment.org/D7262
2018-11-29 15:04:37 -08:00
Eina.Log.Info("Null promise CancelCb found");
}
handle.Free();
}
/// <summary>Dispose this promise, causing its cancellation if it isn't already fulfilled.
/// <para>Since EFL 1.23.</para>
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>Finalizer to be called from the Garbage Collector.
/// <para>Since EFL 1.23.</para>
/// </summary>
~Promise()
{
Dispose(false);
}
/// <summary>Disposes of this wrapper, rejecting the native promise with <see cref="Eina.Error.ECANCELED"/>.
/// <para>Since EFL 1.23.</para>
/// </summary>
/// <param name="disposing">True if this was called from <see cref="Dispose()"/> public method. False if
/// called from the C# finalizer.</param>
protected virtual void Dispose(bool disposing)
{
if (Handle != IntPtr.Zero)
{
efl-csharp: fix resource deallocation causing errors everywhere Summary: This commit mainly fixes errors caused by deallocating resources in the garbage collector thread. Using `ecore_main_loop_thread_safe_call_async` to queue resource deallocation in the main thread seems to solve it. Also, some `efl_ref` calls are added in places they were missing, mainly objects that unref in the destructor thus taking ownership if efl_ref is not called. Also fix improper resource deallocation in tests that were causing it to crash, enabling it to call Efl.All.Shutdown again. This allocation and the deallocation process was moved from the Eo class constructor to static class methods that are called in the test 'set up' and 'tear down' methods. Queuing resource deallocation in the main thread make it mandatory that tests call `Efl.App.AppMain.Iterate()` if they want to check proper resource deallocation (like TestFunctionPointers.set_callback_inherited_called_from_c). Extras: Remove duplicated declaration of 'eflcustomexportsmono' in meson in order to fix some linking problems. Remove some unused code around deallocation functions that had to be reworked. Object allocation is now supplied with the call site information it expects (file name and line for _efl_add_start). Depends on D8550 Test Plan: meson test Reviewers: felipealmeida, lauromoura, cedric, segfaultxavi Reviewed By: lauromoura Subscribers: segfaultxavi Tags: #efl_language_bindings, #do_not_merge Differential Revision: https://phab.enlightenment.org/D8431
2019-04-05 15:57:29 -07:00
if (disposing)
{
eina_promise_reject(Handle, Eina.Error.ECANCELED);
}
else
{
efl_mono_thread_safe_promise_reject(Handle, Eina.Error.ECANCELED);
}
Handle = IntPtr.Zero;
}
}
private void SanityChecks()
{
if (this.Handle == IntPtr.Zero)
{
throw new ObjectDisposedException(GetType().Name);
}
}
/// <summary>
/// Fulfills a promise with the given value.
///
/// <para>This will make all futures attached to it to be called with the given value as payload.</para>
/// <para>Since EFL 1.23.</para>
/// </summary>
csharp: Change to new class API. Summary: As discussed in T7204: - Eo Interfaces/mixins -> C# Interfaces with concrete class implementations - Eo Regular/Abstracts -> Proper C# classes - Added some new generators and helper methods. - Refactored the class generator, splitting into helper methods Eo handles now are stored only in the "root" class in any given inheritance tree (generally, Efl.Object), and accessible to each child. Methods also are defined in a single place instead of repeatedly generated in everyfile, reducing the size of the generated .dll from 30MB to around 4.5MB. Mixins are generated as C# interfaces but any regular class it inherits from is lost, as we can't have interfaces inheriting from regular classes. This will be dealt with in a later commit. Summary of API Changes: - Merged Inherit/Concrete classes. (These suffixes disappear from regular classes). - Interface still have implementations with 'Concrete' suffix for when they are returned from methods. - Removed 'I' from interface names. - Removed interfaces for regular/abstract Eo classes. - Concrete classes for interfaces/mixins hold the event argument struct. - Removed '_' from classes, enums, structs, etc, as indicated in C# naming conventions. - Namespaces are now Camel.Cased. - Renamed IWrapper's raw_handle/raw_klass to NativeHandle/NativeClass Also renamed the test classes as after the namespace change, the test namespace Test can conflict with the helper Test namespace. (And use more meaningful names than Test.Testing...) Also Fixes T7336 by removing a deprecated example and adding efl_loop_timer_example to build system. Fixes T7451 by hiding the class_get DllImports and renaming the IWrapper fields. The native handlers are used in the manual binding. Still need to work: - As there are still some events names clashing (e.g. Efl.Ui.Bg with "resize" from Efl.Gfx.Entity and Efl.Gfx.Image), Events are currently declared on the interface and implemented "namespaced" in the classes, requiring the cast to the interface to access the event. - The Mixin Conundrum. Mixin inheritance will be dealt in a future commit. Depends on D7260 Reviewers: segfaultxavi, vitor.sousa, felipealmeida, Jaehyun_Cho Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7451, T7336 Differential Revision: https://phab.enlightenment.org/D7262
2018-11-29 15:04:37 -08:00
public void Resolve(Eina.Value value)
{
Contract.Requires(value != null, nameof(value));
SanityChecks();
eina_promise_resolve(this.Handle, value);
// Promise will take care of releasing this value correctly.
value.ReleaseOwnership();
this.Handle = IntPtr.Zero;
// Resolving a cb does *not* call its cancellation callback, so we have to release the
// lambda created in the constructor for cleanup.
CleanupHandle.Free();
}
/// <summary>
/// Rejects a promise.
///
/// <para>The future chain attached to this promise will be called with an Eina.Value of type
/// <see cref="Eina.ValueType.Error" /> and payload <see cref="Eina.Error.ECANCELED" />.</para>
/// <para>Since EFL 1.23.</para>
/// </summary>
csharp: Change to new class API. Summary: As discussed in T7204: - Eo Interfaces/mixins -> C# Interfaces with concrete class implementations - Eo Regular/Abstracts -> Proper C# classes - Added some new generators and helper methods. - Refactored the class generator, splitting into helper methods Eo handles now are stored only in the "root" class in any given inheritance tree (generally, Efl.Object), and accessible to each child. Methods also are defined in a single place instead of repeatedly generated in everyfile, reducing the size of the generated .dll from 30MB to around 4.5MB. Mixins are generated as C# interfaces but any regular class it inherits from is lost, as we can't have interfaces inheriting from regular classes. This will be dealt with in a later commit. Summary of API Changes: - Merged Inherit/Concrete classes. (These suffixes disappear from regular classes). - Interface still have implementations with 'Concrete' suffix for when they are returned from methods. - Removed 'I' from interface names. - Removed interfaces for regular/abstract Eo classes. - Concrete classes for interfaces/mixins hold the event argument struct. - Removed '_' from classes, enums, structs, etc, as indicated in C# naming conventions. - Namespaces are now Camel.Cased. - Renamed IWrapper's raw_handle/raw_klass to NativeHandle/NativeClass Also renamed the test classes as after the namespace change, the test namespace Test can conflict with the helper Test namespace. (And use more meaningful names than Test.Testing...) Also Fixes T7336 by removing a deprecated example and adding efl_loop_timer_example to build system. Fixes T7451 by hiding the class_get DllImports and renaming the IWrapper fields. The native handlers are used in the manual binding. Still need to work: - As there are still some events names clashing (e.g. Efl.Ui.Bg with "resize" from Efl.Gfx.Entity and Efl.Gfx.Image), Events are currently declared on the interface and implemented "namespaced" in the classes, requiring the cast to the interface to access the event. - The Mixin Conundrum. Mixin inheritance will be dealt in a future commit. Depends on D7260 Reviewers: segfaultxavi, vitor.sousa, felipealmeida, Jaehyun_Cho Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7451, T7336 Differential Revision: https://phab.enlightenment.org/D7262
2018-11-29 15:04:37 -08:00
public void Reject(Eina.Error reason)
{
SanityChecks();
eina_promise_reject(this.Handle, reason);
this.Handle = IntPtr.Zero;
}
}
/// <summary>
/// Futures are the structures holding the callbacks to be notified of a promise fullfillment
/// or cancellation.
/// <para>Since EFL 1.23.</para>
/// </summary>
public class Future
{
/// <summary>
/// Callback attached to a future and to be called when resolving/rejecting a promise.
///
/// <para>The Eina.Value as argument can come with an <see cref="Eina.Error.ECANCELED" /> as payload if the
/// promise/future was rejected/cancelled.</para>
///
/// <para>The return value usually is same as the argument, forwarded, but can be changed in
/// case were the chain act as a transforming pipeline.</para>
/// <para>Since EFL 1.23.</para>
/// </summary>
csharp: Change to new class API. Summary: As discussed in T7204: - Eo Interfaces/mixins -> C# Interfaces with concrete class implementations - Eo Regular/Abstracts -> Proper C# classes - Added some new generators and helper methods. - Refactored the class generator, splitting into helper methods Eo handles now are stored only in the "root" class in any given inheritance tree (generally, Efl.Object), and accessible to each child. Methods also are defined in a single place instead of repeatedly generated in everyfile, reducing the size of the generated .dll from 30MB to around 4.5MB. Mixins are generated as C# interfaces but any regular class it inherits from is lost, as we can't have interfaces inheriting from regular classes. This will be dealt with in a later commit. Summary of API Changes: - Merged Inherit/Concrete classes. (These suffixes disappear from regular classes). - Interface still have implementations with 'Concrete' suffix for when they are returned from methods. - Removed 'I' from interface names. - Removed interfaces for regular/abstract Eo classes. - Concrete classes for interfaces/mixins hold the event argument struct. - Removed '_' from classes, enums, structs, etc, as indicated in C# naming conventions. - Namespaces are now Camel.Cased. - Renamed IWrapper's raw_handle/raw_klass to NativeHandle/NativeClass Also renamed the test classes as after the namespace change, the test namespace Test can conflict with the helper Test namespace. (And use more meaningful names than Test.Testing...) Also Fixes T7336 by removing a deprecated example and adding efl_loop_timer_example to build system. Fixes T7451 by hiding the class_get DllImports and renaming the IWrapper fields. The native handlers are used in the manual binding. Still need to work: - As there are still some events names clashing (e.g. Efl.Ui.Bg with "resize" from Efl.Gfx.Entity and Efl.Gfx.Image), Events are currently declared on the interface and implemented "namespaced" in the classes, requiring the cast to the interface to access the event. - The Mixin Conundrum. Mixin inheritance will be dealt in a future commit. Depends on D7260 Reviewers: segfaultxavi, vitor.sousa, felipealmeida, Jaehyun_Cho Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7451, T7336 Differential Revision: https://phab.enlightenment.org/D7262
2018-11-29 15:04:37 -08:00
public delegate Eina.Value ResolvedCb(Eina.Value value);
internal IntPtr Handle;
/// <summary>
/// Creates a Future from a native pointer.
/// <para>Since EFL 1.23.</para>
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public Future(IntPtr handle)
{
handle = ThenRaw(handle, (Eina.Value value) =>
{
Handle = IntPtr.Zero;
return value;
});
Handle = handle;
}
/// <summary>
/// Creates a Future attached to the given Promise.
///
/// <para>Optionally a resolved callback may be provided. If so, it will be chained
/// before the returned future.</para>
/// <para>Since EFL 1.23.</para>
/// </summary>
/// <param name="promise">The <see cref="Eina.Promise" /> which rejection or resolution will cause
/// the future to trigger.</param>
/// <param name="cb">The callback to be called when the attached promise resolves.</param>
public Future(Promise promise, ResolvedCb cb = null)
{
Contract.Requires(promise != null, nameof(promise));
IntPtr intermediate = eina_future_new(promise.Handle);
Handle = ThenRaw(intermediate, (Eina.Value value) =>
{
if (cb != null)
{
value = cb(value);
}
Handle = IntPtr.Zero;
return value;
});
}
private void SanityChecks()
{
if (this.Handle == IntPtr.Zero)
{
throw new ObjectDisposedException(GetType().Name);
}
}
/// <summary>
/// Cancels this future and the chain it belongs to, along with the promise linked against it.
///
/// <para>The callbacks will still be called with <see cref="Eina.Error.ECANCELED" /> as payload. The promise cancellation
/// callback will also be called if present.</para>
/// <para>Since EFL 1.23.</para>
/// </summary>
public void Cancel()
{
SanityChecks();
eina_future_cancel(this.Handle);
}
/// <summary>
/// Creates a new future to be called after this one.
///
/// <para>Once the promise this future is attached to resolves, the callbacks on the chain
/// are called in the order they were chained.</para>
///
/// <para>CAUTION: Calling Then() on a future that had it called before will replace the previous chain
/// from this point on.</para>
/// <para>Since EFL 1.23.</para>
/// </summary>
/// <param name="cb">The callback to be called when this future is resolved.</param>
/// <returns>A new future in the chain after registering the callback.</returns>
public Future Then(ResolvedCb cb)
{
SanityChecks();
return new Future(ThenRaw(Handle, cb));
}
// 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);
}
private static FutureCb NativeResolvedCbDelegate = new FutureCb(NativeResolvedCb);
csharp: Change to new class API. Summary: As discussed in T7204: - Eo Interfaces/mixins -> C# Interfaces with concrete class implementations - Eo Regular/Abstracts -> Proper C# classes - Added some new generators and helper methods. - Refactored the class generator, splitting into helper methods Eo handles now are stored only in the "root" class in any given inheritance tree (generally, Efl.Object), and accessible to each child. Methods also are defined in a single place instead of repeatedly generated in everyfile, reducing the size of the generated .dll from 30MB to around 4.5MB. Mixins are generated as C# interfaces but any regular class it inherits from is lost, as we can't have interfaces inheriting from regular classes. This will be dealt with in a later commit. Summary of API Changes: - Merged Inherit/Concrete classes. (These suffixes disappear from regular classes). - Interface still have implementations with 'Concrete' suffix for when they are returned from methods. - Removed 'I' from interface names. - Removed interfaces for regular/abstract Eo classes. - Concrete classes for interfaces/mixins hold the event argument struct. - Removed '_' from classes, enums, structs, etc, as indicated in C# naming conventions. - Namespaces are now Camel.Cased. - Renamed IWrapper's raw_handle/raw_klass to NativeHandle/NativeClass Also renamed the test classes as after the namespace change, the test namespace Test can conflict with the helper Test namespace. (And use more meaningful names than Test.Testing...) Also Fixes T7336 by removing a deprecated example and adding efl_loop_timer_example to build system. Fixes T7451 by hiding the class_get DllImports and renaming the IWrapper fields. The native handlers are used in the manual binding. Still need to work: - As there are still some events names clashing (e.g. Efl.Ui.Bg with "resize" from Efl.Gfx.Entity and Efl.Gfx.Image), Events are currently declared on the interface and implemented "namespaced" in the classes, requiring the cast to the interface to access the event. - The Mixin Conundrum. Mixin inheritance will be dealt in a future commit. Depends on D7260 Reviewers: segfaultxavi, vitor.sousa, felipealmeida, Jaehyun_Cho Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7451, T7336 Differential Revision: https://phab.enlightenment.org/D7262
2018-11-29 15:04:37 -08:00
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
{
csharp: Change to new class API. Summary: As discussed in T7204: - Eo Interfaces/mixins -> C# Interfaces with concrete class implementations - Eo Regular/Abstracts -> Proper C# classes - Added some new generators and helper methods. - Refactored the class generator, splitting into helper methods Eo handles now are stored only in the "root" class in any given inheritance tree (generally, Efl.Object), and accessible to each child. Methods also are defined in a single place instead of repeatedly generated in everyfile, reducing the size of the generated .dll from 30MB to around 4.5MB. Mixins are generated as C# interfaces but any regular class it inherits from is lost, as we can't have interfaces inheriting from regular classes. This will be dealt with in a later commit. Summary of API Changes: - Merged Inherit/Concrete classes. (These suffixes disappear from regular classes). - Interface still have implementations with 'Concrete' suffix for when they are returned from methods. - Removed 'I' from interface names. - Removed interfaces for regular/abstract Eo classes. - Concrete classes for interfaces/mixins hold the event argument struct. - Removed '_' from classes, enums, structs, etc, as indicated in C# naming conventions. - Namespaces are now Camel.Cased. - Renamed IWrapper's raw_handle/raw_klass to NativeHandle/NativeClass Also renamed the test classes as after the namespace change, the test namespace Test can conflict with the helper Test namespace. (And use more meaningful names than Test.Testing...) Also Fixes T7336 by removing a deprecated example and adding efl_loop_timer_example to build system. Fixes T7451 by hiding the class_get DllImports and renaming the IWrapper fields. The native handlers are used in the manual binding. Still need to work: - As there are still some events names clashing (e.g. Efl.Ui.Bg with "resize" from Efl.Gfx.Entity and Efl.Gfx.Image), Events are currently declared on the interface and implemented "namespaced" in the classes, requiring the cast to the interface to access the event. - The Mixin Conundrum. Mixin inheritance will be dealt in a future commit. Depends on D7260 Reviewers: segfaultxavi, vitor.sousa, felipealmeida, Jaehyun_Cho Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7451, T7336 Differential Revision: https://phab.enlightenment.org/D7262
2018-11-29 15:04:37 -08:00
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.
/// <para>Since EFL 1.23.</para>
/// </summary>
/// <param name="cbs">An enumerable with the callbacks to be chained together.</param>
/// <returns>The future representing the chain.</returns>
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();
}
csharp: Change to new class API. Summary: As discussed in T7204: - Eo Interfaces/mixins -> C# Interfaces with concrete class implementations - Eo Regular/Abstracts -> Proper C# classes - Added some new generators and helper methods. - Refactored the class generator, splitting into helper methods Eo handles now are stored only in the "root" class in any given inheritance tree (generally, Efl.Object), and accessible to each child. Methods also are defined in a single place instead of repeatedly generated in everyfile, reducing the size of the generated .dll from 30MB to around 4.5MB. Mixins are generated as C# interfaces but any regular class it inherits from is lost, as we can't have interfaces inheriting from regular classes. This will be dealt with in a later commit. Summary of API Changes: - Merged Inherit/Concrete classes. (These suffixes disappear from regular classes). - Interface still have implementations with 'Concrete' suffix for when they are returned from methods. - Removed 'I' from interface names. - Removed interfaces for regular/abstract Eo classes. - Concrete classes for interfaces/mixins hold the event argument struct. - Removed '_' from classes, enums, structs, etc, as indicated in C# naming conventions. - Namespaces are now Camel.Cased. - Renamed IWrapper's raw_handle/raw_klass to NativeHandle/NativeClass Also renamed the test classes as after the namespace change, the test namespace Test can conflict with the helper Test namespace. (And use more meaningful names than Test.Testing...) Also Fixes T7336 by removing a deprecated example and adding efl_loop_timer_example to build system. Fixes T7451 by hiding the class_get DllImports and renaming the IWrapper fields. The native handlers are used in the manual binding. Still need to work: - As there are still some events names clashing (e.g. Efl.Ui.Bg with "resize" from Efl.Gfx.Entity and Efl.Gfx.Image), Events are currently declared on the interface and implemented "namespaced" in the classes, requiring the cast to the interface to access the event. - The Mixin Conundrum. Mixin inheritance will be dealt in a future commit. Depends on D7260 Reviewers: segfaultxavi, vitor.sousa, felipealmeida, Jaehyun_Cho Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T7451, T7336 Differential Revision: https://phab.enlightenment.org/D7262
2018-11-29 15:04:37 -08:00
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));
}
}
/// <summary>Custom marshaler to convert between managed and native <see cref="Eina.Future"/>.
/// Internal usage in generated code.</summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public class FutureMarshaler : ICustomMarshaler
{
///<summary>Wrap the native future with a managed wrapper.</summary>
///<param name="pNativeData">Handle to the native future.</param>
///<returns>An <see cref="Eina.Future"/> wrapping the native future.</returns>
public object MarshalNativeToManaged(IntPtr pNativeData)
{
return new Future(pNativeData);
}
///<summary>Extracts the native future from a managed wrapper.</summary>
///<param name="managedObj">The managed wrapper. If it is not an <see cref="Eina.Future"/>, the value returned
///is <see cref="System.IntPtr.Zero"/>.</param>
///<returns>A <see cref="System.IntPtr"/> pointing to the native future.</returns>
public IntPtr MarshalManagedToNative(object managedObj)
{
Future f = managedObj as Future;
if (f == null)
{
return IntPtr.Zero;
}
return f.Handle;
}
///<summary>Not implemented. The code receiving the native data is in charge of releasing it.</summary>
///<param name="pNativeData">The native pointer to be released.</param>
public void CleanUpNativeData(IntPtr pNativeData)
{
}
///<summary>Not implemented. The runtime takes care of releasing it.</summary>
///<param name="managedObj">The managed object to be cleaned.</param>
public void CleanUpManagedData(object managedObj)
{
}
///<summary>Size of the native data size returned</summary>
///<returns>The size of the data.</returns>
public int GetNativeDataSize()
{
return -1;
}
///<summary>Gets an instance of this marshaller.</summary>
///<param name="cookie">A name that could be used to customize the returned marshaller. Currently not used.</param>
///<returns>The <see cref="Eina.FutureMarshaler"/> instance that will marshall the data.</returns>
public static ICustomMarshaler GetInstance(string cookie)
{
if (marshaler == null)
{
marshaler = new FutureMarshaler();
}
return marshaler;
}
private static FutureMarshaler marshaler;
}
} // namespace eina