6
6
using System . Collections . Generic ;
7
7
using System . IO ;
8
8
using System . Threading ;
9
+ using System . Threading . Tasks ;
9
10
using System . Reflection ;
10
11
11
12
namespace DBus
@@ -42,9 +43,11 @@ public class Connection
42
43
public delegate void MonitorEventHandler ( Message msg ) ;
43
44
public MonitorEventHandler Monitors ; // subscribe yourself to this list of observers if you want to get notified about each incoming message
44
45
46
+ private ManualResetEventSlim iterateEvent = MakeNewEventToNextIterate ( ) ;
47
+ private readonly object iterateLocker = new object ( ) ;
48
+
45
49
protected Connection ( )
46
50
{
47
-
48
51
}
49
52
50
53
internal Connection ( Transport transport )
@@ -183,11 +186,12 @@ internal uint GenerateSerial ()
183
186
184
187
internal Message SendWithReplyAndBlock ( Message msg , bool keepFDs )
185
188
{
186
- PendingCall pending = SendWithReply ( msg , keepFDs ) ;
187
- return pending . Reply ;
189
+ using ( PendingCall pending = SendWithPendingReply ( msg , keepFDs ) ) {
190
+ return pending . Reply ;
191
+ }
188
192
}
189
193
190
- internal PendingCall SendWithReply ( Message msg , bool keepFDs )
194
+ internal PendingCall SendWithPendingReply ( Message msg , bool keepFDs )
191
195
{
192
196
msg . ReplyExpected = true ;
193
197
@@ -232,10 +236,30 @@ internal void DispatchSignals ()
232
236
233
237
public void Iterate ( )
234
238
{
235
- Message msg = transport . ReadMessage ( ) ;
239
+ Iterate ( new CancellationToken ( false ) ) ;
240
+ }
241
+
242
+ Task Task = null ;
243
+ object TaskLock = new object ( ) ;
236
244
237
- HandleMessage ( msg ) ;
238
- DispatchSignals ( ) ;
245
+ public void Iterate ( CancellationToken stopWaitToken )
246
+ {
247
+ lock ( TaskLock ) {
248
+ if ( Task == null || Task . IsCompleted ) {
249
+ Task = Task . Run ( ( ) => {
250
+ var msg = transport . ReadMessage ( ) ;
251
+ HandleMessage ( msg ) ;
252
+ DispatchSignals ( ) ;
253
+ } ) ;
254
+ }
255
+ }
256
+
257
+ Task . Wait ( stopWaitToken ) ;
258
+ }
259
+
260
+ private static ManualResetEventSlim MakeNewEventToNextIterate ( )
261
+ {
262
+ return new ManualResetEventSlim ( true ) ;
239
263
}
240
264
241
265
internal virtual void HandleMessage ( Message msg )
@@ -251,21 +275,19 @@ internal virtual void HandleMessage (Message msg)
251
275
try {
252
276
253
277
//TODO: Restrict messages to Local ObjectPath?
254
-
255
278
{
256
- object field_value = msg . Header [ FieldCode . ReplySerial ] ;
279
+ object field_value = msg . Header [ FieldCode . ReplySerial ] ;
257
280
if ( field_value != null ) {
258
281
uint reply_serial = ( uint ) field_value ;
259
- PendingCall pending ;
260
282
261
283
lock ( pendingCalls ) {
284
+ PendingCall pending ;
262
285
if ( pendingCalls . TryGetValue ( reply_serial , out pending ) ) {
263
- if ( pendingCalls . Remove ( reply_serial ) ) {
264
- pending . Reply = msg ;
265
- if ( pending . KeepFDs )
266
- cleanupFDs = false ; // caller is responsible for closing FDs
267
- }
268
-
286
+ if ( ! pendingCalls . Remove ( reply_serial ) )
287
+ return ;
288
+ pending . Reply = msg ;
289
+ if ( pending . KeepFDs )
290
+ cleanupFDs = false ; // caller is responsible for closing FDs
269
291
return ;
270
292
}
271
293
}
@@ -391,17 +413,19 @@ internal void HandleMethodCall (MessageContainer method_call)
391
413
//this is messy and inefficient
392
414
List < string > linkNodes = new List < string > ( ) ;
393
415
int depth = method_call . Path . Decomposed . Length ;
394
- foreach ( ObjectPath pth in registeredObjects . Keys ) {
395
- if ( pth . Value == ( method_call . Path . Value ) ) {
396
- ExportObject exo = ( ExportObject ) registeredObjects [ pth ] ;
397
- exo . WriteIntrospect ( intro ) ;
398
- } else {
399
- for ( ObjectPath cur = pth ; cur != null ; cur = cur . Parent ) {
400
- if ( cur . Value == method_call . Path . Value ) {
401
- string linkNode = pth . Decomposed [ depth ] ;
402
- if ( ! linkNodes . Contains ( linkNode ) ) {
403
- intro . WriteNode ( linkNode ) ;
404
- linkNodes . Add ( linkNode ) ;
416
+ lock ( registeredObjects ) {
417
+ foreach ( ObjectPath pth in registeredObjects . Keys ) {
418
+ if ( pth . Value == ( method_call . Path . Value ) ) {
419
+ ExportObject exo = ( ExportObject ) registeredObjects [ pth ] ;
420
+ exo . WriteIntrospect ( intro ) ;
421
+ } else {
422
+ for ( ObjectPath cur = pth ; cur != null ; cur = cur . Parent ) {
423
+ if ( cur . Value == method_call . Path . Value ) {
424
+ string linkNode = pth . Decomposed [ depth ] ;
425
+ if ( ! linkNodes . Contains ( linkNode ) ) {
426
+ intro . WriteNode ( linkNode ) ;
427
+ linkNodes . Add ( linkNode ) ;
428
+ }
405
429
}
406
430
}
407
431
}
@@ -415,12 +439,14 @@ internal void HandleMethodCall (MessageContainer method_call)
415
439
return ;
416
440
}
417
441
418
- BusObject bo ;
419
- if ( registeredObjects . TryGetValue ( method_call . Path , out bo ) ) {
420
- ExportObject eo = ( ExportObject ) bo ;
421
- eo . HandleMethodCall ( method_call ) ;
422
- } else {
423
- MaybeSendUnknownMethodError ( method_call ) ;
442
+ lock ( registeredObjects ) {
443
+ BusObject bo ;
444
+ if ( registeredObjects . TryGetValue ( method_call . Path , out bo ) ) {
445
+ ExportObject eo = ( ExportObject ) bo ;
446
+ eo . HandleMethodCall ( method_call ) ;
447
+ } else {
448
+ MaybeSendUnknownMethodError ( method_call ) ;
449
+ }
424
450
}
425
451
}
426
452
@@ -459,17 +485,19 @@ public void Register (ObjectPath path, object obj)
459
485
eo . Registered = true ;
460
486
461
487
//TODO: implement some kind of tree data structure or internal object hierarchy. right now we are ignoring the name and putting all object paths in one namespace, which is bad
462
- registeredObjects [ path ] = eo ;
488
+ lock ( registeredObjects )
489
+ registeredObjects [ path ] = eo ;
463
490
}
464
491
465
492
public object Unregister ( ObjectPath path )
466
493
{
467
494
BusObject bo ;
468
495
469
- if ( ! registeredObjects . TryGetValue ( path , out bo ) )
470
- throw new Exception ( "Cannot unregister " + path + " as it isn't registered" ) ;
471
-
472
- registeredObjects . Remove ( path ) ;
496
+ lock ( registeredObjects ) {
497
+ if ( ! registeredObjects . TryGetValue ( path , out bo ) )
498
+ throw new Exception ( "Cannot unregister " + path + " as it isn't registered" ) ;
499
+ registeredObjects . Remove ( path ) ;
500
+ }
473
501
474
502
ExportObject eo = ( ExportObject ) bo ;
475
503
eo . Registered = false ;
0 commit comments