Skip to content

Commit

Permalink
Create a new run loop observer for a nested loop if it's being starte…
Browse files Browse the repository at this point in the history
…d from an observer callback (#15425)

Co-authored-by: Nikita Tsukanov <kekekeks@Nikitas-MacBook-Pro.local>
  • Loading branch information
2 people authored and grokys committed Jun 12, 2024
1 parent 6471650 commit d719dd2
Showing 1 changed file with 68 additions and 23 deletions.
91 changes: 68 additions & 23 deletions native/Avalonia.Native/src/OSX/platformthreading.mm
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,39 @@ virtual void Cancel() override
// interval—on the order of decades or more"
static double distantFutureInterval = (double)50*365*24*3600;



@implementation ObserverStateHolder : NSObject
{
@public bool InsideCallback;
}
@end

@implementation ObserverHolder : NSObject
{
@public CFRunLoopObserverRef Observer;
@public ObserverStateHolder* State;
}

- (ObserverHolder*) init
{
self = [super init];
self->State = [ObserverStateHolder new];
return self;
}

- (void) dealloc
{
if(Observer != nil)
{
CFRunLoopObserverInvalidate(Observer);
CFRelease(Observer);
Observer = nil;
}
}

@end

@interface Signaler : NSObject
-(void) setEvents:(IAvnPlatformThreadingInterfaceEvents*) events;
-(void) updateTimer:(int)ms;
Expand All @@ -66,7 +99,7 @@ @implementation Signaler
bool _wakeupDelegateSent;
bool _signaled;
bool _backgroundProcessingRequested;
CFRunLoopObserverRef _observer;
@public ObserverHolder* Observer;
CFRunLoopTimerRef _timer;
}

Expand All @@ -83,15 +116,19 @@ - (void) checkSignaled
}
}

- (Signaler*) init
- (ObserverHolder*) createObserver
{
_observer = CFRunLoopObserverCreateWithHandler(nil,
ObserverHolder* holder = [ObserverHolder new];
ObserverStateHolder* state = holder->State;

holder->Observer = CFRunLoopObserverCreateWithHandler(nil,
kCFRunLoopBeforeSources
| kCFRunLoopAfterWaiting
| kCFRunLoopBeforeWaiting
,
true, 0,
^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
state->InsideCallback = true;
if(activity == kCFRunLoopBeforeWaiting)
{
bool triggerProcessing;
Expand All @@ -103,10 +140,15 @@ - (Signaler*) init
self->_events->ReadyForBackgroundProcessing();
}
[self checkSignaled];
state->InsideCallback = false;
});
CFRunLoopAddObserver(CFRunLoopGetMain(), _observer, kCFRunLoopCommonModes);


CFRunLoopAddObserver(CFRunLoopGetMain(), holder->Observer, kCFRunLoopCommonModes);
return holder;
}

- (Signaler*) init
{
Observer = [self createObserver];
_timer = CFRunLoopTimerCreateWithHandler(nil, CFAbsoluteTimeGetCurrent() + distantFutureInterval, distantFutureInterval, 0, 0, ^(CFRunLoopTimerRef timer) {
self->_events->Timer();
});
Expand All @@ -118,12 +160,7 @@ - (Signaler*) init

- (void) destroyObserver
{
if(_observer != nil)
{
CFRunLoopObserverInvalidate(_observer);
CFRelease(_observer);
_observer = nil;
}
Observer = nil;

if(_timer != nil)
{
Expand Down Expand Up @@ -182,12 +219,13 @@ - (void) requestBackgroundProcessing
private:
ComPtr<IAvnPlatformThreadingInterfaceEvents> _events;
Signaler* _signaler;
CFRunLoopObserverRef _observer = nil;
ObserverHolder* _currentObserver;
public:
FORWARD_IUNKNOWN()
PlatformThreadingInterface()
{
_signaler = [Signaler new];
_currentObserver = _signaler->Observer;
};

~PlatformThreadingInterface()
Expand Down Expand Up @@ -228,18 +266,25 @@ void RunLoop(IAvnLoopCancellation *cancel) override
}
else
{
while(!can->Cancelled)
{
@autoreleasepool
@autoreleasepool {
auto previousObserver = _currentObserver;
if(_currentObserver->State->InsideCallback)
_currentObserver = [_signaler createObserver];

while(!can->Cancelled)
{
NSEvent* ev = [NSApp
nextEventMatchingMask:NSEventMaskAny
untilDate: [NSDate dateWithTimeIntervalSinceNow:1]
inMode:NSDefaultRunLoopMode
dequeue:true];
if(ev != NULL)
[NSApp sendEvent:ev];
@autoreleasepool
{
NSEvent* ev = [NSApp
nextEventMatchingMask:NSEventMaskAny
untilDate: [NSDate dateWithTimeIntervalSinceNow:1]
inMode:NSDefaultRunLoopMode
dequeue:true];
if(ev != NULL)
[NSApp sendEvent:ev];
}
}
_currentObserver = previousObserver;
}
}
};
Expand Down

0 comments on commit d719dd2

Please sign in to comment.