@@ -451,39 +451,64 @@ func (o *ObservableImpl) BufferWithTime(timespan Duration, opts ...Option) Obser
451
451
}
452
452
453
453
f := func (ctx context.Context , next chan Item , option Option , opts ... Option ) {
454
- defer close (next )
455
454
observe := o .Observe (opts ... )
456
455
buffer := make ([]interface {}, 0 )
456
+ stop := make (chan struct {})
457
+ mutex := sync.Mutex {}
458
+
459
+ checkBuffer := func () {
460
+ mutex .Lock ()
461
+ if len (buffer ) != 0 {
462
+ if ! Of (buffer ).SendContext (ctx , next ) {
463
+ mutex .Unlock ()
464
+ return
465
+ }
466
+ buffer = make ([]interface {}, 0 )
467
+ }
468
+ mutex .Unlock ()
469
+ }
470
+
471
+ go func () {
472
+ defer close (next )
473
+ duration := timespan .duration ()
474
+ for {
475
+ select {
476
+ case <- stop :
477
+ checkBuffer ()
478
+ return
479
+ case <- ctx .Done ():
480
+ return
481
+ case <- time .After (duration ):
482
+ checkBuffer ()
483
+ }
484
+ }
485
+ }()
457
486
458
487
for {
459
488
select {
460
489
case <- ctx .Done ():
490
+ close (stop )
461
491
return
462
492
case item , ok := <- observe :
463
493
if ! ok {
464
- if len (buffer ) != 0 {
465
- Of (buffer ).SendContext (ctx , next )
466
- }
494
+ close (stop )
467
495
return
468
496
}
469
497
if item .Error () {
470
498
item .SendContext (ctx , next )
471
499
if option .getErrorStrategy () == StopOnError {
500
+ close (stop )
472
501
return
473
502
}
474
503
} else {
504
+ mutex .Lock ()
475
505
buffer = append (buffer , item .V )
476
- }
477
- case <- time .After (timespan .duration ()):
478
- if len (buffer ) != 0 {
479
- if ! Of (buffer ).SendContext (ctx , next ) {
480
- return
481
- }
482
- buffer = make ([]interface {}, 0 )
506
+ mutex .Unlock ()
483
507
}
484
508
}
485
509
}
486
510
}
511
+
487
512
return customObservableOperator (f , opts ... )
488
513
}
489
514
@@ -498,42 +523,69 @@ func (o *ObservableImpl) BufferWithTimeOrCount(timespan Duration, count int, opt
498
523
}
499
524
500
525
f := func (ctx context.Context , next chan Item , option Option , opts ... Option ) {
501
- defer close (next )
502
526
observe := o .Observe (opts ... )
503
527
buffer := make ([]interface {}, 0 )
528
+ stop := make (chan struct {})
529
+ send := make (chan struct {})
530
+ mutex := sync.Mutex {}
531
+
532
+ checkBuffer := func () {
533
+ mutex .Lock ()
534
+ if len (buffer ) != 0 {
535
+ if ! Of (buffer ).SendContext (ctx , next ) {
536
+ mutex .Unlock ()
537
+ return
538
+ }
539
+ buffer = make ([]interface {}, 0 )
540
+ }
541
+ mutex .Unlock ()
542
+ }
543
+
544
+ go func () {
545
+ defer close (next )
546
+ duration := timespan .duration ()
547
+ for {
548
+ select {
549
+ case <- send :
550
+ checkBuffer ()
551
+ case <- stop :
552
+ checkBuffer ()
553
+ return
554
+ case <- ctx .Done ():
555
+ return
556
+ case <- time .After (duration ):
557
+ checkBuffer ()
558
+ }
559
+ }
560
+ }()
504
561
505
562
for {
506
563
select {
507
564
case <- ctx .Done ():
508
565
return
509
566
case item , ok := <- observe :
510
567
if ! ok {
511
- if len (buffer ) != 0 {
512
- Of (buffer ).SendContext (ctx , next )
513
- }
568
+ close (stop )
569
+ close (send )
514
570
return
515
571
}
516
572
if item .Error () {
517
573
item .SendContext (ctx , next )
518
574
if option .getErrorStrategy () == StopOnError {
575
+ close (stop )
576
+ close (send )
519
577
return
520
578
}
521
579
} else {
580
+ mutex .Lock ()
522
581
buffer = append (buffer , item .V )
523
582
if len (buffer ) == count {
524
- if ! Of ( buffer ). SendContext ( ctx , next ) {
525
- return
526
- }
527
- buffer = make ([] interface {}, 0 )
583
+ mutex . Unlock ()
584
+ send <- struct {}{}
585
+ } else {
586
+ mutex . Unlock ( )
528
587
}
529
588
}
530
- case <- time .After (timespan .duration ()):
531
- if len (buffer ) != 0 {
532
- if ! Of (buffer ).SendContext (ctx , next ) {
533
- return
534
- }
535
- buffer = make ([]interface {}, 0 )
536
- }
537
589
}
538
590
}
539
591
}
@@ -2676,47 +2728,77 @@ func (o *ObservableImpl) WindowWithTime(timespan Duration, opts ...Option) Obser
2676
2728
}
2677
2729
2678
2730
f := func (ctx context.Context , next chan Item , option Option , opts ... Option ) {
2679
- defer close (next )
2680
2731
observe := o .Observe (opts ... )
2681
2732
ch := option .buildChannel ()
2733
+ done := make (chan struct {})
2682
2734
empty := true
2735
+ mutex := sync.Mutex {}
2683
2736
if ! Of (FromChannel (ch )).SendContext (ctx , next ) {
2684
2737
return
2685
2738
}
2686
2739
2740
+ go func () {
2741
+ defer func () {
2742
+ mutex .Lock ()
2743
+ close (ch )
2744
+ mutex .Unlock ()
2745
+ }()
2746
+ defer close (next )
2747
+ for {
2748
+ select {
2749
+ case <- ctx .Done ():
2750
+ return
2751
+ case <- done :
2752
+ return
2753
+ case <- time .After (timespan .duration ()):
2754
+ mutex .Lock ()
2755
+ if empty {
2756
+ mutex .Unlock ()
2757
+ continue
2758
+ }
2759
+ close (ch )
2760
+ empty = true
2761
+ ch = option .buildChannel ()
2762
+ if ! Of (FromChannel (ch )).SendContext (ctx , next ) {
2763
+ close (done )
2764
+ return
2765
+ }
2766
+ mutex .Unlock ()
2767
+ }
2768
+ }
2769
+ }()
2770
+
2687
2771
for {
2688
2772
select {
2689
2773
case <- ctx .Done ():
2690
- close (ch )
2774
+ return
2775
+ case <- done :
2691
2776
return
2692
2777
case item , ok := <- observe :
2693
2778
if ! ok {
2694
- close (ch )
2779
+ close (done )
2695
2780
return
2696
2781
}
2697
2782
if item .Error () {
2783
+ mutex .Lock ()
2698
2784
if ! item .SendContext (ctx , ch ) {
2785
+ mutex .Unlock ()
2786
+ close (done )
2699
2787
return
2700
2788
}
2789
+ mutex .Unlock ()
2701
2790
if option .getErrorStrategy () == StopOnError {
2702
- close (ch )
2791
+ close (done )
2703
2792
return
2704
2793
}
2705
2794
}
2795
+ mutex .Lock ()
2706
2796
if ! item .SendContext (ctx , ch ) {
2797
+ mutex .Unlock ()
2707
2798
return
2708
2799
}
2709
2800
empty = false
2710
- case <- time .After (timespan .duration ()):
2711
- if empty {
2712
- continue
2713
- }
2714
- close (ch )
2715
- ch = option .buildChannel ()
2716
- empty = true
2717
- if ! Of (FromChannel (ch )).SendContext (ctx , next ) {
2718
- return
2719
- }
2801
+ mutex .Unlock ()
2720
2802
}
2721
2803
}
2722
2804
}
@@ -2735,55 +2817,87 @@ func (o *ObservableImpl) WindowWithTimeOrCount(timespan Duration, count int, opt
2735
2817
}
2736
2818
2737
2819
f := func (ctx context.Context , next chan Item , option Option , opts ... Option ) {
2738
- defer close (next )
2739
2820
observe := o .Observe (opts ... )
2740
2821
ch := option .buildChannel ()
2822
+ done := make (chan struct {})
2823
+ mutex := sync.Mutex {}
2741
2824
iCount := 0
2742
2825
if ! Of (FromChannel (ch )).SendContext (ctx , next ) {
2743
2826
return
2744
2827
}
2745
2828
2829
+ go func () {
2830
+ defer func () {
2831
+ mutex .Lock ()
2832
+ close (ch )
2833
+ mutex .Unlock ()
2834
+ }()
2835
+ defer close (next )
2836
+ for {
2837
+ select {
2838
+ case <- ctx .Done ():
2839
+ return
2840
+ case <- done :
2841
+ return
2842
+ case <- time .After (timespan .duration ()):
2843
+ mutex .Lock ()
2844
+ if iCount == 0 {
2845
+ mutex .Unlock ()
2846
+ continue
2847
+ }
2848
+ close (ch )
2849
+ iCount = 0
2850
+ ch = option .buildChannel ()
2851
+ if ! Of (FromChannel (ch )).SendContext (ctx , next ) {
2852
+ close (done )
2853
+ return
2854
+ }
2855
+ mutex .Unlock ()
2856
+ }
2857
+ }
2858
+ }()
2859
+
2746
2860
for {
2747
2861
select {
2748
2862
case <- ctx .Done ():
2749
- close (ch )
2863
+ return
2864
+ case <- done :
2750
2865
return
2751
2866
case item , ok := <- observe :
2752
2867
if ! ok {
2753
- close (ch )
2868
+ close (done )
2754
2869
return
2755
2870
}
2756
2871
if item .Error () {
2872
+ mutex .Lock ()
2757
2873
if ! item .SendContext (ctx , ch ) {
2874
+ mutex .Unlock ()
2875
+ close (done )
2758
2876
return
2759
2877
}
2878
+ mutex .Unlock ()
2760
2879
if option .getErrorStrategy () == StopOnError {
2761
- close (ch )
2880
+ close (done )
2762
2881
return
2763
2882
}
2764
2883
}
2884
+ mutex .Lock ()
2765
2885
if ! item .SendContext (ctx , ch ) {
2886
+ mutex .Unlock ()
2766
2887
return
2767
2888
}
2768
2889
iCount ++
2769
2890
if iCount == count {
2770
2891
close (ch )
2771
- ch = option .buildChannel ()
2772
2892
iCount = 0
2893
+ ch = option .buildChannel ()
2773
2894
if ! Of (FromChannel (ch )).SendContext (ctx , next ) {
2895
+ mutex .Unlock ()
2896
+ close (done )
2774
2897
return
2775
2898
}
2776
2899
}
2777
- case <- time .After (timespan .duration ()):
2778
- if iCount == 0 {
2779
- continue
2780
- }
2781
- close (ch )
2782
- ch = option .buildChannel ()
2783
- iCount = 0
2784
- if ! Of (FromChannel (ch )).SendContext (ctx , next ) {
2785
- return
2786
- }
2900
+ mutex .Unlock ()
2787
2901
}
2788
2902
}
2789
2903
}
0 commit comments