mirror of
https://gitee.com/csharpui/CPF.git
synced 2025-04-05 17:37:51 +08:00
209 lines
4.9 KiB
C#
209 lines
4.9 KiB
C#
using CPF.Mac.Foundation;
|
|
using CPF.Mac.ObjCRuntime;
|
|
using System;
|
|
using System.Runtime.InteropServices;
|
|
using System.Threading;
|
|
|
|
namespace CPF.Mac.CoreFoundation
|
|
{
|
|
public class DispatchQueue : DispatchObject
|
|
{
|
|
internal delegate void dispatch_callback_t(IntPtr context);
|
|
|
|
private static IntPtr main_q;
|
|
|
|
private static object lockobj = new object();
|
|
|
|
internal static readonly dispatch_callback_t static_dispatch = static_dispatcher_to_managed;
|
|
|
|
public string Label
|
|
{
|
|
get
|
|
{
|
|
if (handle == IntPtr.Zero)
|
|
{
|
|
throw new ObjectDisposedException("DispatchQueue");
|
|
}
|
|
return Marshal.PtrToStringAnsi(dispatch_queue_get_label(handle));
|
|
}
|
|
}
|
|
|
|
public IntPtr Context
|
|
{
|
|
get
|
|
{
|
|
Check();
|
|
return dispatch_get_context(handle);
|
|
}
|
|
set
|
|
{
|
|
Check();
|
|
dispatch_set_context(handle, value);
|
|
}
|
|
}
|
|
|
|
[Obsolete("Deprecated in iOS 6.0")]
|
|
public static DispatchQueue CurrentQueue => new DispatchQueue(dispatch_get_current_queue(), owns: false);
|
|
|
|
public static DispatchQueue DefaultGlobalQueue => new DispatchQueue(dispatch_get_global_queue((IntPtr)0, IntPtr.Zero), owns: false);
|
|
|
|
public static DispatchQueue MainQueue
|
|
{
|
|
get
|
|
{
|
|
lock (lockobj)
|
|
{
|
|
if (main_q == IntPtr.Zero)
|
|
{
|
|
main_q = Dlfcn.dlsym((IntPtr)(-2), "_dispatch_main_q");
|
|
if (main_q == IntPtr.Zero)
|
|
{
|
|
IntPtr handle = Dlfcn.dlopen("/usr/lib/libSystem.dylib", 0);
|
|
main_q = Dlfcn.GetIndirect(handle, "_dispatch_main_q");
|
|
Dlfcn.dlclose(handle);
|
|
}
|
|
}
|
|
}
|
|
if (main_q == IntPtr.Zero)
|
|
{
|
|
return PInvokeDispatchGetMainQueue();
|
|
}
|
|
return new DispatchQueue(main_q, owns: false);
|
|
}
|
|
}
|
|
|
|
[Preserve(Conditional = true)]
|
|
internal DispatchQueue(IntPtr handle, bool owns)
|
|
: base(handle, owns)
|
|
{
|
|
}
|
|
|
|
public DispatchQueue(IntPtr handle)
|
|
: base(handle, owns: false)
|
|
{
|
|
}
|
|
|
|
public DispatchQueue(string label)
|
|
{
|
|
handle = dispatch_queue_create(label, IntPtr.Zero);
|
|
if (handle == IntPtr.Zero)
|
|
{
|
|
throw new Exception("Error creating dispatch queue");
|
|
}
|
|
}
|
|
|
|
[DllImport("libc")]
|
|
private static extern void dispatch_suspend(IntPtr o);
|
|
|
|
public void Suspend()
|
|
{
|
|
Check();
|
|
dispatch_suspend(handle);
|
|
}
|
|
|
|
[DllImport("libc")]
|
|
private static extern void dispatch_resume(IntPtr o);
|
|
|
|
public void Resume()
|
|
{
|
|
Check();
|
|
dispatch_resume(handle);
|
|
}
|
|
|
|
[DllImport("libc")]
|
|
private static extern IntPtr dispatch_get_context(IntPtr o);
|
|
|
|
[DllImport("libc")]
|
|
private static extern void dispatch_set_context(IntPtr o, IntPtr ctx);
|
|
|
|
public static DispatchQueue GetGlobalQueue(DispatchQueuePriority priority)
|
|
{
|
|
return new DispatchQueue(dispatch_get_global_queue((IntPtr)(int)priority, IntPtr.Zero), owns: false);
|
|
}
|
|
|
|
private static DispatchQueue PInvokeDispatchGetMainQueue()
|
|
{
|
|
return new DispatchQueue(dispatch_get_main_queue(), owns: false);
|
|
}
|
|
|
|
[MonoPInvokeCallback(typeof(dispatch_callback_t))]
|
|
private static void static_dispatcher_to_managed(IntPtr context)
|
|
{
|
|
GCHandle gCHandle = GCHandle.FromIntPtr(context);
|
|
Tuple<NSAction, DispatchQueue> tuple = gCHandle.Target as Tuple<NSAction, DispatchQueue>;
|
|
if (tuple != null)
|
|
{
|
|
SynchronizationContext current = SynchronizationContext.Current;
|
|
if (current == null)
|
|
{
|
|
SynchronizationContext.SetSynchronizationContext(new DispatchQueueSynchronizationContext(tuple.Item2));
|
|
}
|
|
try
|
|
{
|
|
tuple.Item1();
|
|
}
|
|
catch
|
|
{
|
|
gCHandle.Free();
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
if (current == null)
|
|
{
|
|
SynchronizationContext.SetSynchronizationContext(null);
|
|
}
|
|
}
|
|
}
|
|
gCHandle.Free();
|
|
}
|
|
|
|
public void DispatchAsync(NSAction action)
|
|
{
|
|
if (action == null)
|
|
{
|
|
throw new ArgumentNullException("action");
|
|
}
|
|
dispatch_async_f(handle, (IntPtr)GCHandle.Alloc(Tuple.Create(action, this)), static_dispatch);
|
|
}
|
|
|
|
public void DispatchSync(NSAction action)
|
|
{
|
|
if (action == null)
|
|
{
|
|
throw new ArgumentNullException("action");
|
|
}
|
|
dispatch_sync_f(handle, (IntPtr)GCHandle.Alloc(Tuple.Create(action, this)), static_dispatch);
|
|
}
|
|
|
|
[DllImport("libc")]
|
|
private static extern IntPtr dispatch_queue_create(string label, IntPtr attr);
|
|
|
|
[DllImport("libc")]
|
|
private static extern void dispatch_async_f(IntPtr queue, IntPtr context, dispatch_callback_t dispatch);
|
|
|
|
[DllImport("libc")]
|
|
private static extern void dispatch_sync_f(IntPtr queue, IntPtr context, dispatch_callback_t dispatch);
|
|
|
|
[DllImport("libc")]
|
|
private static extern IntPtr dispatch_get_current_queue();
|
|
|
|
[DllImport("libc")]
|
|
private static extern IntPtr dispatch_get_global_queue(IntPtr priority, IntPtr flags);
|
|
|
|
[DllImport("libc")]
|
|
private static extern IntPtr dispatch_get_main_queue();
|
|
|
|
[DllImport("libc")]
|
|
private static extern IntPtr dispatch_queue_get_label(IntPtr queue);
|
|
|
|
[DllImport("libc")]
|
|
private static extern IntPtr dispatch_main();
|
|
|
|
public static void MainIteration()
|
|
{
|
|
dispatch_main();
|
|
}
|
|
}
|
|
}
|