@@ -10,106 +10,19 @@ namespace Files.Helpers
10
10
{
11
11
public class BulkConcurrentObservableCollection < T > : INotifyCollectionChanged , INotifyPropertyChanged , ICollection < T > , IList < T > , ICollection , IList
12
12
{
13
- private volatile bool isBulkOperationStarted ;
14
- private volatile int readerCount ;
15
- private volatile bool needSnapshot ;
16
- private readonly SemaphoreSlim writerLock = new SemaphoreSlim ( 1 , 1 ) ;
17
- private readonly SemaphoreSlim mutex = new SemaphoreSlim ( 1 , 1 ) ;
18
- private readonly SemaphoreSlim snapshotLock = new SemaphoreSlim ( 1 , 1 ) ;
13
+ private bool isBulkOperationStarted ;
14
+ private readonly object syncRoot = new object ( ) ;
19
15
private readonly List < T > collection = new List < T > ( ) ;
20
- private List < T > snapshot = new List < T > ( ) ;
21
16
22
- private void Write ( Action writeFunc )
23
- {
24
- writerLock . Wait ( ) ;
25
- try
26
- {
27
- writeFunc ( ) ;
28
- }
29
- finally
30
- {
31
- writerLock . Release ( ) ;
32
- snapshotLock . Wait ( ) ;
33
- needSnapshot = true ;
34
- snapshotLock . Release ( ) ;
35
- }
36
- }
37
-
38
- private U Write < U > ( Func < U > writeFunc )
39
- {
40
- writerLock . Wait ( ) ;
41
- try
42
- {
43
- return writeFunc ( ) ;
44
- }
45
- finally
46
- {
47
- writerLock . Release ( ) ;
48
- snapshotLock . Wait ( ) ;
49
- needSnapshot = true ;
50
- snapshotLock . Release ( ) ;
51
- }
52
- }
53
-
54
- private void Read ( Action readFunc )
55
- {
56
- mutex . Wait ( ) ;
57
- readerCount ++ ;
58
- if ( readerCount == 1 )
59
- {
60
- writerLock . Wait ( ) ;
61
- }
62
- mutex . Release ( ) ;
63
- try
64
- {
65
- readFunc ( ) ;
66
- }
67
- finally
68
- {
69
- mutex . Wait ( ) ;
70
- readerCount -- ;
71
- if ( readerCount == 0 )
72
- {
73
- writerLock . Release ( ) ;
74
- }
75
- mutex . Release ( ) ;
76
- }
77
- }
78
-
79
- private U Read < U > ( Func < U > readFunc )
80
- {
81
- mutex . Wait ( ) ;
82
- readerCount ++ ;
83
- if ( readerCount == 1 )
84
- {
85
- writerLock . Wait ( ) ;
86
- }
87
- mutex . Release ( ) ;
88
- try
89
- {
90
- return readFunc ( ) ;
91
- }
92
- finally
93
- {
94
- mutex . Wait ( ) ;
95
- readerCount -- ;
96
- if ( readerCount == 0 )
97
- {
98
- writerLock . Release ( ) ;
99
- }
100
- mutex . Release ( ) ;
101
- }
102
- }
103
-
104
- public int Count => Read ( ( ) => collection . Count ) ;
17
+ public int Count => collection . Count ;
105
18
106
19
public bool IsReadOnly => false ;
107
20
108
21
public bool IsFixedSize => false ;
109
22
110
- public bool IsSynchronized => false ;
23
+ public bool IsSynchronized => true ;
111
24
112
- public object SyncRoot => throw new NotImplementedException ( ) ;
25
+ public object SyncRoot => syncRoot ;
113
26
114
27
object IList . this [ int index ]
115
28
{
@@ -125,15 +38,11 @@ object IList.this[int index]
125
38
126
39
public T this [ int index ]
127
40
{
128
- get => Read ( ( ) => collection [ index ] ) ;
41
+ get => collection [ index ] ;
129
42
set
130
43
{
131
- var item = Write ( ( ) =>
132
- {
133
- var item = collection [ index ] ;
134
- collection [ index ] = value ;
135
- return item ;
136
- } ) ;
44
+ var item = collection [ index ] ;
45
+ collection [ index ] = value ;
137
46
OnCollectionChanged ( new NotifyCollectionChangedEventArgs ( NotifyCollectionChangedAction . Replace , value , item ) ) ;
138
47
}
139
48
}
@@ -163,43 +72,50 @@ public void EndBulkOperation()
163
72
164
73
public void Add ( T item )
165
74
{
166
- Write ( ( ) => collection . Add ( item ) ) ;
75
+ lock ( syncRoot )
76
+ {
77
+ collection . Add ( item ) ;
78
+ }
79
+
167
80
OnCollectionChanged ( new NotifyCollectionChangedEventArgs ( NotifyCollectionChangedAction . Add , item ) ) ;
168
81
}
169
82
170
83
public void Clear ( )
171
84
{
172
- Write ( ( ) => collection . Clear ( ) ) ;
85
+ lock ( syncRoot )
86
+ {
87
+ collection . Clear ( ) ;
88
+ }
89
+
173
90
OnCollectionChanged ( new NotifyCollectionChangedEventArgs ( NotifyCollectionChangedAction . Reset ) ) ;
174
91
}
175
92
176
93
public bool Contains ( T item )
177
94
{
178
- return Read ( ( ) => collection . Contains ( item ) ) ;
95
+ return collection . Contains ( item ) ;
179
96
}
180
97
181
98
public void CopyTo ( T [ ] array , int arrayIndex )
182
99
{
183
- Read ( ( ) => collection . CopyTo ( array , arrayIndex ) ) ;
100
+ collection . CopyTo ( array , arrayIndex ) ;
184
101
}
185
102
186
103
public bool Remove ( T item )
187
104
{
188
- var result = Write ( ( ) => collection . Remove ( item ) ) ;
105
+ bool result ;
106
+
107
+ lock ( syncRoot )
108
+ {
109
+ result = collection . Remove ( item ) ;
110
+ }
111
+
189
112
OnCollectionChanged ( new NotifyCollectionChangedEventArgs ( NotifyCollectionChangedAction . Remove , item ) ) ;
190
113
return result ;
191
114
}
192
115
193
116
public IEnumerator < T > GetEnumerator ( )
194
117
{
195
- snapshotLock . Wait ( ) ;
196
- if ( needSnapshot )
197
- {
198
- snapshot = Read ( ( ) => collection . ToList ( ) ) ;
199
- needSnapshot = false ;
200
- }
201
- snapshotLock . Release ( ) ;
202
- return snapshot . GetEnumerator ( ) ;
118
+ return collection . GetEnumerator ( ) ;
203
119
}
204
120
205
121
IEnumerator IEnumerable . GetEnumerator ( )
@@ -209,23 +125,28 @@ IEnumerator IEnumerable.GetEnumerator()
209
125
210
126
public int IndexOf ( T item )
211
127
{
212
- return Read ( ( ) => collection . IndexOf ( item ) ) ;
128
+ return collection . IndexOf ( item ) ;
213
129
}
214
130
215
131
public void Insert ( int index , T item )
216
132
{
217
- Write ( ( ) => collection . Insert ( index , item ) ) ;
133
+ lock ( syncRoot )
134
+ {
135
+ collection . Insert ( index , item ) ;
136
+ }
137
+
218
138
OnCollectionChanged ( new NotifyCollectionChangedEventArgs ( NotifyCollectionChangedAction . Add , item ) ) ;
219
139
}
220
140
221
141
public void RemoveAt ( int index )
222
142
{
223
- var item = Write ( ( ) =>
143
+ var item = collection [ index ] ;
144
+
145
+ lock ( syncRoot )
224
146
{
225
- var item = collection [ index ] ;
226
147
collection . RemoveAt ( index ) ;
227
- return item ;
228
- } ) ;
148
+ }
149
+
229
150
OnCollectionChanged ( new NotifyCollectionChangedEventArgs ( NotifyCollectionChangedAction . Remove , item ) ) ;
230
151
}
231
152
@@ -235,7 +156,12 @@ public void AddRange(IEnumerable<T> items)
235
156
{
236
157
return ;
237
158
}
238
- Write ( ( ) => collection . AddRange ( items ) ) ;
159
+
160
+ lock ( syncRoot )
161
+ {
162
+ collection . AddRange ( items ) ;
163
+ }
164
+
239
165
OnCollectionChanged ( new NotifyCollectionChangedEventArgs ( NotifyCollectionChangedAction . Add , items . ToList ( ) ) ) ;
240
166
}
241
167
@@ -245,50 +171,62 @@ public void InsertRange(int index, IEnumerable<T> items)
245
171
{
246
172
return ;
247
173
}
248
- Write ( ( ) => collection . InsertRange ( index , items ) ) ;
174
+
175
+ lock ( syncRoot )
176
+ {
177
+ collection . InsertRange ( index , items ) ;
178
+ }
179
+
249
180
OnCollectionChanged ( new NotifyCollectionChangedEventArgs ( NotifyCollectionChangedAction . Add , items . ToList ( ) , index ) ) ;
250
181
}
251
182
252
183
public void RemoveRange ( int index , int count )
253
184
{
254
- if ( count = = 0 )
185
+ if ( count < = 0 )
255
186
{
256
187
return ;
257
188
}
258
- var items = Write ( ( ) =>
189
+
190
+ var items = collection . Skip ( index ) . Take ( count ) . ToList ( ) ;
191
+
192
+ lock ( syncRoot )
259
193
{
260
- var items = collection . Skip ( index ) . Take ( count ) . ToList ( ) ;
261
194
collection . RemoveRange ( index , count ) ;
262
- return items ;
263
- } ) ;
195
+ }
196
+
264
197
OnCollectionChanged ( new NotifyCollectionChangedEventArgs ( NotifyCollectionChangedAction . Remove , items ) ) ;
265
198
}
266
199
267
200
public void ReplaceRange ( int index , IEnumerable < T > items )
268
201
{
269
202
var count = items . Count ( ) ;
203
+
270
204
if ( count == 0 )
271
205
{
272
206
return ;
273
207
}
274
- var ( newItems , oldItems ) = Write ( ( ) =>
208
+
209
+ var oldItems = collection . Skip ( index ) . Take ( count ) . ToList ( ) ;
210
+ var newItems = items . ToList ( ) ;
211
+
212
+ lock ( syncRoot )
275
213
{
276
- var oldItems = collection . Skip ( index ) . Take ( count ) . ToList ( ) ;
277
- var newItems = items . ToList ( ) ;
278
214
collection . InsertRange ( index , newItems ) ;
279
215
collection . RemoveRange ( index + count , count ) ;
280
- return ( newItems , oldItems ) ;
281
- } ) ;
216
+ }
217
+
282
218
OnCollectionChanged ( new NotifyCollectionChangedEventArgs ( NotifyCollectionChangedAction . Replace , newItems , oldItems ) ) ;
283
219
}
284
220
285
221
int IList . Add ( object value )
286
222
{
287
- var index = Write ( ( ) =>
223
+ int index ;
224
+
225
+ lock ( syncRoot )
288
226
{
289
- collection . Add ( ( T ) value ) ;
290
- return collection . Count ;
291
- } ) ;
227
+ index = ( ( IList ) collection ) . Add ( ( T ) value ) ;
228
+ }
229
+
292
230
OnCollectionChanged ( new NotifyCollectionChangedEventArgs ( NotifyCollectionChangedAction . Add , value ) ) ;
293
231
return index ;
294
232
}
0 commit comments