ObjFW  Diff

Differences From Artifact [b99d9d1539]:

To Artifact [692cbbd5b1]:

  • File src/OFRunLoop.m — part of check-in [d16ad96cbd] at 2018-12-07 01:33:47 on branch trunk — OFStream: Use a delegate for async operations

    The target / selector approach had several drawbacks:

    * It was inconvenient to use, as for every read or write, a target,
    selector and context would need to be specified.
    * It lacked any kind of type-safety and would not even warn about using
    a callback method with the wrong number of parameters.
    * It encouraged using a different callback method for each read or
    write call, which results in code that is hard to follow and also
    slower (as it needs to recreate the async operation with a new
    callback every time). (user: js, size: 28736) [annotate] [blame] [check-ins using]


70
71
72
73
74
75
76


77
78
79
80
81
82
83
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85







+
+







}
@end

#ifdef OF_HAVE_SOCKETS
@interface OFRunLoop_QueueItem: OFObject
{
@public
	id _delegate;
	/* TODO: Remove once everything is moved to using delegates */
	id _target;
	SEL _selector;
	id _context;
}

- (bool)handleObject: (id)object;
@end
296
297
298
299
300
301
302

303
304
305
306
307
308
309
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312







+







- (bool)handleObject: (id)object
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)dealloc
{
	[_delegate release];
	[_target release];
	[_context release];

	[super dealloc];
}
@end

322
323
324
325
326
327
328




329
330
331









332
333

334

335
336
337
338
339
340
341
325
326
327
328
329
330
331
332
333
334
335



336
337
338
339
340
341
342
343
344
345

346

347
348
349
350
351
352
353
354







+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+

-
+
-
+







	}

# ifdef OF_HAVE_BLOCKS
	if (_block != NULL)
		return _block(object, _buffer, length, exception);
	else {
# endif
		if (exception == nil) {
			if (![_delegate respondsToSelector:
			    @selector(stream:didReadIntoBuffer:length:)])
				return false;
		bool (*func)(id, SEL, OFStream *, void *, size_t, id, id) =
		    (bool (*)(id, SEL, OFStream *, void *, size_t, id, id))
		    [_target methodForSelector: _selector];

			return [_delegate stream: object
			       didReadIntoBuffer: _buffer
					  length: length];
		} else {
			if ([_delegate respondsToSelector:
			    @selector(stream:didFailWithException:)])
				[_delegate	  stream: object
				    didFailWithException: exception];

		return func(_target, _selector, object, _buffer, length,
			return false;
		    _context, exception);
		}
# ifdef OF_HAVE_BLOCKS
	}
# endif
}

# ifdef OF_HAVE_BLOCKS
- (void)dealloc
372
373
374
375
376
377
378
379

380
381



382


383

384
385

386
387
388










389
390
391
392
393
394
395
385
386
387
388
389
390
391

392


393
394
395
396
397
398

399


400
401


402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418







-
+
-
-
+
+
+

+
+
-
+
-
-
+

-
-
+
+
+
+
+
+
+
+
+
+







		if (!_block(object, _buffer, _readLength, exception))
			return false;

		_readLength = 0;
		return true;
	} else {
# endif
		bool (*func)(id, SEL, OFStream *, void *, size_t, id, id) =
		if (exception == nil) {
		    (bool (*)(id, SEL, OFStream *, void *, size_t, id, id))
		    [_target methodForSelector: _selector];
			if (![_delegate respondsToSelector:
			    @selector(stream:didReadIntoBuffer:length:)])
				return false;

			if (![_delegate stream: object
			     didReadIntoBuffer: _buffer
		if (!func(_target, _selector, object, _buffer, _readLength,
					length: _readLength])
		    _context, exception))
			return false;
				return false;

		_readLength = 0;
		return true;
			_readLength = 0;
			return true;
		} else {
			if ([_delegate respondsToSelector:
			    @selector(stream:didFailWithException:)])
				[_delegate	  stream: object
				    didFailWithException: exception];

			return false;
		}
# ifdef OF_HAVE_BLOCKS
	}
# endif
}

# ifdef OF_HAVE_BLOCKS
- (void)dealloc
418
419
420
421
422
423
424




425
426
427








428
429

430

431
432
433
434
435
436
437
441
442
443
444
445
446
447
448
449
450
451



452
453
454
455
456
457
458
459
460

461

462
463
464
465
466
467
468
469







+
+
+
+
-
-
-
+
+
+
+
+
+
+
+

-
+
-
+







		return true;

# ifdef OF_HAVE_BLOCKS
	if (_block != NULL)
		return _block(object, line, exception);
	else {
# endif
		if (exception == nil) {
			if (![_delegate respondsToSelector:
			    @selector(stream:didReadLine:)])
				return false;
		bool (*func)(id, SEL, OFStream *, OFString *, id, id) =
		    (bool (*)(id, SEL, OFStream *, OFString *, id, id))
		    [_target methodForSelector: _selector];

			return [_delegate stream: object
				     didReadLine: line];
		} else {
			if ([_delegate respondsToSelector:
			    @selector(stream:didFailWithException:)])
				[_delegate	  stream: object
				    didFailWithException: exception];

		return func(_target, _selector, object, line, _context,
			return false;
		    exception);
		}
# ifdef OF_HAVE_BLOCKS
	}
# endif
}

# ifdef OF_HAVE_BLOCKS
- (void)dealloc
469
470
471
472
473
474
475
476
477
478




479
480
481



482
483
484


485
486
487










488
489
490
491
492
493
494
501
502
503
504
505
506
507



508
509
510
511
512


513
514
515
516


517
518
519


520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536







-
-
-
+
+
+
+

-
-
+
+
+

-
-
+
+

-
-
+
+
+
+
+
+
+
+
+
+







		if (_length == 0)
			return false;

		_writtenLength = 0;
		return true;
	} else {
# endif
		bool (*func)(id, SEL, OFStream *, const void *, size_t, id,
		    id) = (bool (*)(id, SEL, OFStream *, const void *, size_t,
		    id, id))[_target methodForSelector: _selector];
		if (exception == nil) {
			if (![_delegate respondsToSelector:
			    @selector(stream:didWriteBuffer:length:)])
				return false;

		_length = func(_target, _selector, object, &_buffer,
		    _writtenLength, _context, exception);
			_length = [_delegate stream: object
				     didWriteBuffer: &_buffer
					     length: _length];

		if (_length == 0)
			return false;
			if (_length == 0)
				return false;

		_writtenLength = 0;
		return true;
			_writtenLength = 0;
			return true;
		} else {
			if ([_delegate respondsToSelector:
			    @selector(stream:didFailWithException:)])
				[_delegate	  stream: object
				    didFailWithException: exception];

			return false;
		}
# ifdef OF_HAVE_BLOCKS
	}
# endif
}

# ifdef OF_HAVE_BLOCKS
- (void)dealloc
724
725
726
727
728
729
730
731

732
733
734
735
736
737

738
739
740
741
742
743
744
745
746
747
748
749

750
751
752
753
754
755

756
757
758
759
760
761
762
763
764
765
766

767
768
769
770
771
772

773
774
775
776
777
778
779
780
781
782
783

784
785
786
787
788
789

790
791
792
793
794
795
796
797
766
767
768
769
770
771
772

773


774
775


776

777
778
779
780
781
782
783
784
785
786

787


788
789


790

791
792
793
794
795
796
797
798
799

800


801
802


803

804
805
806
807
808
809
810
811
812

813


814
815


816

817
818
819
820
821
822
823







-
+
-
-


-
-
+
-










-
+
-
-


-
-
+
-









-
+
-
-


-
-
+
-









-
+
-
-


-
-
+
-







	objc_autoreleasePoolPop(pool);

+ (void)of_addAsyncReadForStream: (OFStream <OFReadyForReadingObserving> *)
				      stream
			  buffer: (void *)buffer
			  length: (size_t)length
			    mode: (of_run_loop_mode_t)mode
			  target: (id)target
			delegate: (id <OFStreamDelegate>)delegate
			selector: (SEL)selector
			 context: (id)context
{
	ADD_READ(OFRunLoop_ReadQueueItem, stream, mode, {
		queueItem->_target = [target retain];
		queueItem->_selector = selector;
		queueItem->_delegate = [delegate retain];
		queueItem->_context = [context retain];
		queueItem->_buffer = buffer;
		queueItem->_length = length;
	})
}

+ (void)of_addAsyncReadForStream: (OFStream <OFReadyForReadingObserving> *)
				      stream
			  buffer: (void *)buffer
		     exactLength: (size_t)exactLength
			    mode: (of_run_loop_mode_t)mode
			  target: (id)target
			delegate: (id <OFStreamDelegate>)delegate
			selector: (SEL)selector
			 context: (id)context
{
	ADD_READ(OFRunLoop_ExactReadQueueItem, stream, mode, {
		queueItem->_target = [target retain];
		queueItem->_selector = selector;
		queueItem->_delegate = [delegate retain];
		queueItem->_context = [context retain];
		queueItem->_buffer = buffer;
		queueItem->_exactLength = exactLength;
	})
}

+ (void)of_addAsyncReadLineForStream: (OFStream <OFReadyForReadingObserving> *)
					  stream
			    encoding: (of_string_encoding_t)encoding
				mode: (of_run_loop_mode_t)mode
			      target: (id)target
			    delegate: (id <OFStreamDelegate>)delegate
			    selector: (SEL)selector
			     context: (id)context
{
	ADD_READ(OFRunLoop_ReadLineQueueItem, stream, mode, {
		queueItem->_target = [target retain];
		queueItem->_selector = selector;
		queueItem->_delegate = [delegate retain];
		queueItem->_context = [context retain];
		queueItem->_encoding = encoding;
	})
}

+ (void)of_addAsyncWriteForStream: (OFStream <OFReadyForWritingObserving> *)
				       stream
			   buffer: (const void *)buffer
			   length: (size_t)length
			     mode: (of_run_loop_mode_t)mode
			   target: (id)target
			 delegate: (id <OFStreamDelegate>)delegate
			 selector: (SEL)selector
			  context: (id)context
{
	ADD_WRITE(OFRunLoop_WriteQueueItem, stream, mode, {
		queueItem->_target = [target retain];
		queueItem->_selector = selector;
		queueItem->_delegate = [delegate retain];
		queueItem->_context = [context retain];
		queueItem->_buffer = buffer;
		queueItem->_length = length;
	})
}

+ (void)of_addAsyncConnectForTCPSocket: (OFTCPSocket *)stream
				  mode: (of_run_loop_mode_t)mode