aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/ThirdParty/SmartThreadPool/EventWaitHandle.cs
blob: b7983cd72abda6c19c071bd290f6d7b2ee3bacee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#if (_WINDOWS_CE)

using System;
using System.Runtime.InteropServices;
using System.Threading;

namespace Amib.Threading.Internal
{
    /// <summary>
    /// EventWaitHandle class
    /// In WindowsCE this class doesn't exist and I needed the WaitAll and WaitAny implementation.
    /// So I wrote this class to implement these two methods with some of their overloads.
    /// It uses the WaitForMultipleObjects API to do the WaitAll and WaitAny.
    /// Note that this class doesn't even inherit from WaitHandle!
    /// </summary>
    public class STPEventWaitHandle
    {
        #region Public Constants

        public const int WaitTimeout = Timeout.Infinite;

        #endregion

        #region Private External Constants

        private const Int32 WAIT_FAILED = -1;
        private const Int32 WAIT_TIMEOUT = 0x102;
        private const UInt32 INFINITE = 0xFFFFFFFF;

        #endregion

        #region WaitAll and WaitAny

        internal static bool WaitOne(WaitHandle waitHandle, int millisecondsTimeout, bool exitContext)
        {
            return waitHandle.WaitOne(millisecondsTimeout, exitContext);
        }

        private static IntPtr[] PrepareNativeHandles(WaitHandle[] waitHandles)
        {
            IntPtr[] nativeHandles = new IntPtr[waitHandles.Length];
            for (int i = 0; i < waitHandles.Length; i++)
            {
                nativeHandles[i] = waitHandles[i].Handle;
            }
            return nativeHandles;
        }

        public static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
        {
            uint timeout = millisecondsTimeout < 0 ? INFINITE : (uint)millisecondsTimeout;

            IntPtr[] nativeHandles = PrepareNativeHandles(waitHandles);

            int result = WaitForMultipleObjects((uint)waitHandles.Length, nativeHandles, true, timeout);

            if (result == WAIT_TIMEOUT || result == WAIT_FAILED)
            {
                return false;
            }

            return true;
        }


        public static int WaitAny(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
        {
            uint timeout = millisecondsTimeout < 0 ? INFINITE : (uint)millisecondsTimeout;

            IntPtr[] nativeHandles = PrepareNativeHandles(waitHandles);

            int result = WaitForMultipleObjects((uint)waitHandles.Length, nativeHandles, false, timeout);

            if (result >= 0 && result < waitHandles.Length)
            {
                return result;
            }

            return -1;
        }

        public static int WaitAny(WaitHandle[] waitHandles)
        {
            return WaitAny(waitHandles, Timeout.Infinite, false);
        }

        public static int WaitAny(WaitHandle[] waitHandles, TimeSpan timeout, bool exitContext)
        {
            int millisecondsTimeout = (int)timeout.TotalMilliseconds;

            return WaitAny(waitHandles, millisecondsTimeout, false);
        }

        #endregion

        #region External methods

        [DllImport("coredll.dll", SetLastError = true)]
        public static extern int WaitForMultipleObjects(uint nCount, IntPtr[] lpHandles, bool fWaitAll, uint dwMilliseconds);

        #endregion
    }
}
#endif