Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2287 - 1
#if !MONO && !PocketPC
2
#define UseFastResourceLock
3
#endif
4
 
5
namespace GMap.NET.Internals
6
{
7
    using System;
8
    using System.Threading;
9
#if !MONO
10
    using System.Runtime.InteropServices;
11
#endif
12
 
13
    /// <summary>
14
    /// custom ReaderWriterLock
15
    /// in Vista and later uses integrated Slim Reader/Writer (SRW) Lock
16
    /// http://msdn.microsoft.com/en-us/library/aa904937(VS.85).aspx
17
    /// http://msdn.microsoft.com/en-us/magazine/cc163405.aspx#S2
18
    /// </summary>
19
    public sealed class FastReaderWriterLock : IDisposable
20
    {
21
#if !MONO && !PocketPC
22
        private static class NativeMethods
23
        {
24
            // Methods
25
            [DllImport("Kernel32", ExactSpelling = true)]
26
            internal static extern void AcquireSRWLockExclusive(ref IntPtr srw);
27
            [DllImport("Kernel32", ExactSpelling = true)]
28
            internal static extern void AcquireSRWLockShared(ref IntPtr srw);
29
            [DllImport("Kernel32", ExactSpelling = true)]
30
            internal static extern void InitializeSRWLock(out IntPtr srw);
31
            [DllImport("Kernel32", ExactSpelling = true)]
32
            internal static extern void ReleaseSRWLockExclusive(ref IntPtr srw);
33
            [DllImport("Kernel32", ExactSpelling = true)]
34
            internal static extern void ReleaseSRWLockShared(ref IntPtr srw);
35
        }
36
 
37
        IntPtr LockSRW = IntPtr.Zero;
38
 
39
        public FastReaderWriterLock()
40
        {
41
            if (UseNativeSRWLock)
42
            {
43
                NativeMethods.InitializeSRWLock(out this.LockSRW);
44
            }
45
            else
46
            {
47
#if UseFastResourceLock
48
                pLock = new FastResourceLock();
49
#endif
50
            }
51
        }
52
 
53
#if UseFastResourceLock
54
        ~FastReaderWriterLock()
55
        {
56
            Dispose(false);
57
        }
58
 
59
        void Dispose(bool disposing)
60
        {
61
            if (pLock != null)
62
            {
63
                pLock.Dispose();
64
                pLock = null;
65
            }
66
        }
67
 
68
        FastResourceLock pLock;
69
#endif
70
 
71
      static readonly bool UseNativeSRWLock = Stuff.IsRunningOnVistaOrLater() && IntPtr.Size == 4; // works only in 32-bit mode, any ideas on native 64-bit support? 
72
 
73
#endif
74
 
75
#if !UseFastResourceLock
76
       Int32 busy = 0;
77
       Int32 readCount = 0;
78
#endif
79
 
80
        public void AcquireReaderLock()
81
        {
82
#if !MONO && !PocketPC
83
            if (UseNativeSRWLock)
84
            {
85
                NativeMethods.AcquireSRWLockShared(ref LockSRW);
86
            }
87
            else
88
#endif
89
            {
90
#if UseFastResourceLock
91
            pLock.AcquireShared();
92
#else
93
            Thread.BeginCriticalRegion();
94
 
95
            while(Interlocked.CompareExchange(ref busy, 1, 0) != 0)
96
            {
97
               Thread.Sleep(1);
98
            }
99
 
100
            Interlocked.Increment(ref readCount);
101
 
102
            // somehow this fix deadlock on heavy reads
103
            Thread.Sleep(0);
104
            Thread.Sleep(0);
105
            Thread.Sleep(0);
106
            Thread.Sleep(0);
107
            Thread.Sleep(0);
108
            Thread.Sleep(0);
109
            Thread.Sleep(0);
110
 
111
            Interlocked.Exchange(ref busy, 0);
112
#endif
113
            }
114
        }
115
 
116
        public void ReleaseReaderLock()
117
        {
118
#if !MONO && !PocketPC
119
            if (UseNativeSRWLock)
120
            {
121
                NativeMethods.ReleaseSRWLockShared(ref LockSRW);
122
            }
123
            else
124
#endif
125
            {
126
#if UseFastResourceLock
127
                pLock.ReleaseShared();
128
#else
129
            Interlocked.Decrement(ref readCount);
130
            Thread.EndCriticalRegion();
131
#endif
132
            }
133
        }
134
 
135
        public void AcquireWriterLock()
136
        {
137
#if !MONO && !PocketPC
138
            if (UseNativeSRWLock)
139
            {
140
                NativeMethods.AcquireSRWLockExclusive(ref LockSRW);
141
            }
142
            else
143
#endif
144
            {
145
#if UseFastResourceLock
146
                pLock.AcquireExclusive();
147
#else
148
            Thread.BeginCriticalRegion();
149
 
150
            while(Interlocked.CompareExchange(ref busy, 1, 0) != 0)
151
            {
152
               Thread.Sleep(1);
153
            }
154
 
155
            while(Interlocked.CompareExchange(ref readCount, 0, 0) != 0)
156
            {
157
               Thread.Sleep(1);
158
            }
159
#endif
160
            }
161
        }
162
 
163
        public void ReleaseWriterLock()
164
        {
165
#if !MONO && !PocketPC
166
            if (UseNativeSRWLock)
167
            {
168
                NativeMethods.ReleaseSRWLockExclusive(ref LockSRW);
169
            }
170
            else
171
#endif
172
            {
173
#if UseFastResourceLock
174
                pLock.ReleaseExclusive();
175
#else
176
            Interlocked.Exchange(ref busy, 0);
177
            Thread.EndCriticalRegion();
178
#endif
179
            }
180
        }
181
 
182
        #region IDisposable Members
183
 
184
        public void Dispose()
185
        {
186
#if UseFastResourceLock
187
            this.Dispose(true);
188
            GC.SuppressFinalize(this);
189
#endif
190
        }
191
 
192
        #endregion
193
    }
194
}