internal static extern void FSEventStreamUnscheduleFromRunLoop(
     SafeEventStreamHandle   streamRef,
     CFRunLoopRef            runLoop,
     SafeCreateHandle        runLoopMode);
 /// <summary>
 /// Creates a new EventStream to listen to events from the core OS (such as File System events).
 /// </summary>
 /// <param name="cb">A callback instance that will be called for every event batch.</param>
 /// <param name="pathsToWatch">A CFArray of the path(s) to watch for events.</param>
 /// <param name="sinceWhen">
 /// The start point to receive events from. This can be to retrieve historical events or only new events. 
 /// To get historical events, pass in the corresponding ID of the event you want to start from.
 /// To get only new events, pass in kFSEventStreamEventIdSinceNow.
 /// </param>
 /// <param name="latency">Coalescing period to wait before sending events.</param>
 /// <param name="flags">Flags to say what kind of events should be sent through this stream.</param>
 /// <returns>On success, returns a valid SafeCreateHandle to an FSEventStream object; otherwise, returns an invalid SafeCreateHandle</returns>
 internal static SafeEventStreamHandle FSEventStreamCreate(
     FSEventStreamCallback       cb,
     SafeCreateHandle            pathsToWatch,
     FSEventStreamEventId        sinceWhen,
     CFTimeInterval              latency,
     FSEventStreamCreateFlags    flags)
 {
     return FSEventStreamCreate(IntPtr.Zero, cb, IntPtr.Zero, pathsToWatch, sinceWhen, latency, flags);
 }
        private static unsafe void CreateAndStartRunLoop()
        {
            Debug.Assert(s_dynamicStoreRef == null);

            var storeContext = new Interop.SystemConfiguration.SCDynamicStoreContext();
            using (SafeCreateHandle storeName = Interop.CoreFoundation.CFStringCreateWithCString("NetworkAddressChange.OSX"))
            {
                s_dynamicStoreRef = Interop.SystemConfiguration.SCDynamicStoreCreate(
                    storeName.DangerousGetHandle(),
                    s_storeCallback,
                    &storeContext);
            }

            // Notification key string parts. We want to match notification keys
            // for any kind of IP address change, addition, or removal.
            using (SafeCreateHandle dynamicStoreDomainStateString = Interop.CoreFoundation.CFStringCreateWithCString("State:"))
            using (SafeCreateHandle compAnyRegexString = Interop.CoreFoundation.CFStringCreateWithCString("[^/]+"))
            using (SafeCreateHandle entNetIpv4String = Interop.CoreFoundation.CFStringCreateWithCString("IPv4"))
            using (SafeCreateHandle entNetIpv6String = Interop.CoreFoundation.CFStringCreateWithCString("IPv6"))
            {
                if (dynamicStoreDomainStateString.IsInvalid || compAnyRegexString.IsInvalid
                    || entNetIpv4String.IsInvalid || entNetIpv6String.IsInvalid)
                {
                    s_dynamicStoreRef.Dispose();
                    s_dynamicStoreRef = null;
                    throw new NetworkInformationException(SR.net_PInvokeError);
                }

                using (SafeCreateHandle ipv4Pattern = Interop.SystemConfiguration.SCDynamicStoreKeyCreateNetworkServiceEntity(
                        dynamicStoreDomainStateString.DangerousGetHandle(),
                        compAnyRegexString.DangerousGetHandle(),
                        entNetIpv4String.DangerousGetHandle()))
                using (SafeCreateHandle ipv6Pattern = Interop.SystemConfiguration.SCDynamicStoreKeyCreateNetworkServiceEntity(
                        dynamicStoreDomainStateString.DangerousGetHandle(),
                        compAnyRegexString.DangerousGetHandle(),
                        entNetIpv6String.DangerousGetHandle()))
                using (SafeCreateHandle patterns = Interop.CoreFoundation.CFArrayCreate(
                        new CFStringRef[2]
                        {
                            ipv4Pattern.DangerousGetHandle(),
                            ipv6Pattern.DangerousGetHandle()
                        }, 2))
                {
                    // Try to register our pattern strings with the dynamic store instance.
                    if (patterns.IsInvalid || !Interop.SystemConfiguration.SCDynamicStoreSetNotificationKeys(
                                                s_dynamicStoreRef.DangerousGetHandle(),
                                                IntPtr.Zero,
                                                patterns.DangerousGetHandle()))
                    {
                        s_dynamicStoreRef.Dispose();
                        s_dynamicStoreRef = null;
                        throw new NetworkInformationException(SR.net_PInvokeError);
                    }

                    // Create a "RunLoopSource" that can be added to our listener thread's RunLoop.
                    s_runLoopSource = Interop.SystemConfiguration.SCDynamicStoreCreateRunLoopSource(
                        s_dynamicStoreRef.DangerousGetHandle(),
                        IntPtr.Zero);
                }
            }
            s_runLoopThread = new Thread(RunLoopThreadStart);
            s_runLoopThread.Start();
            s_runLoopStartedEvent.WaitOne(); // Wait for the new thread to finish initialization.
        }
 private static extern SafeEventStreamHandle FSEventStreamCreate(
     IntPtr                      allocator,
     FSEventStreamCallback       cb,
     IntPtr                      context,
     SafeCreateHandle            pathsToWatch,
     FSEventStreamEventId        sinceWhen,
     CFTimeInterval              latency,
     FSEventStreamCreateFlags    flags);
        private static void RunLoopThreadStart()
        {
            Debug.Assert(s_runLoop == IntPtr.Zero);

            s_runLoop = Interop.RunLoop.CFRunLoopGetCurrent();
            Interop.RunLoop.CFRunLoopAddSource(
                s_runLoop,
                s_runLoopSource.DangerousGetHandle(),
                Interop.RunLoop.kCFRunLoopDefaultMode.DangerousGetHandle());

            s_runLoopStartedEvent.Set();
            Interop.RunLoop.CFRunLoopRun();

            Interop.RunLoop.CFRunLoopRemoveSource(
                s_runLoop,
                s_runLoopSource.DangerousGetHandle(),
                Interop.RunLoop.kCFRunLoopDefaultMode.DangerousGetHandle());

            s_runLoop = IntPtr.Zero;

            s_runLoopSource.Dispose();
            s_runLoopSource = null;

            s_dynamicStoreRef.Dispose();
            s_dynamicStoreRef = null;

            s_runLoopEndedEvent.Set();
        }