1 Reply
      Latest reply on May 20, 2020 1:47 AM by eskimo
      techqueries123 Level 1 Level 1 (0 points)

        Hello,

         

            I have the below program in Objective-C++ for IOPSNotificationCreateRunLoopSource.

            But, I am not able to receive power source change events without the  infinite do {  } while(!done) loop in startThread() function.

            Please suggest a way to get rind of the infinite loop to receive power source change events.

         

        #import "PowerSourceInfoWorker.h"
        @implementation PowerSourceInfoWorker

        -(void) dealloc {
             [self stopThread];
             [super dealloc];
        }

         

        -(void) startThread {
        BOOL done = NO;
        do {
              runLoopSource = (CFRunLoopSourceRef)IOPSNotificationCreateRunLoopSource(powerSourceChange, self);
              if(runLoopSource) {
                   NSLog(@"Waiting for power source change........ ");
                   CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode);
              }
              int result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, YES);
              done = (result == kCFRunLoopRunStopped) || (result == kCFRunLoopRunFinished);
        } while (!done);
        }

        -(void) stopThread {
             if(runLoopSource) {
                  CFRunLoopSourceInvalidate(runLoopSource);
                  CFRelease(runLoopSource);
             }
        }

        void powerSourceChange(void* context) {
             NSLog(@"Power Source has changed");
        }

        int main(int argc, const char * argv[]) {
            NSLog(@"Power Source Change detection");

            PowerSourceInfoWorker *psiWorker = [[PowerSourceInfoWorker alloc]init];

            NSLog(@"before startThread");
            [psiWorker startThread];
        }
        @end

        • Re: IOPSNotificationCreateRunLoopSource query
          eskimo Apple Staff Apple Staff (13,905 points)

          I’m not entirely sure why your code doesn’t work but pasted in below you’ll find some code that does.  When I run it on my machine (10.15.4) I see the following:

          2020-05-20 09:45:26…[68499:3100242] will start
          2020-05-20 09:45:26…[68499:3100242] did start
          2020-05-20 09:45:26…[68499:3100242] will wait for 10.0
          2020-05-20 09:45:33…[68499:3100242] did receive power callback
          2020-05-20 09:45:33…[68499:3100242] will wait for 3.8
          2020-05-20 09:45:36…[68499:3100242] did receive power callback
          2020-05-20 09:45:36…[68499:3100242] will wait for 0.8
          2020-05-20 09:45:36…[68499:3100242] will stop
          2020-05-20 09:45:36…[68499:3100242] did stop

          I’m on a laptop, and I triggered the power callbacks by plugging and unplugging the power supply.

          Share and Enjoy

          Quinn “The Eskimo!”
          Apple Developer Relations, Developer Technical Support, Core OS/Hardware
          let myEmail = "eskimo" + "1" + "@apple.com"


          @import Foundation;
          @import IOKit.ps;
          
          @interface Main: NSObject
          
          @end
          
          @interface Main ()
          
          @property (nonatomic, strong, readwrite, nullable) CFRunLoopSourceRef source __attribute__ (( NSObject ));
          
          @end
          
          @implementation Main
          
          - (void)start {
              NSLog(@"will start");
              assert(self.source == nil);
              CFRunLoopSourceRef source = IOPSNotificationCreateRunLoopSource(
                  myPowerSourceCallbackType,
                  (__bridge void *) self
              );
              self.source = source;
              CFRelease(source);
              CFRunLoopRef current = CFRunLoopGetCurrent();
              CFRunLoopAddSource(current, self.source, kCFRunLoopDefaultMode);
              NSLog(@"did start");
          }
          
          - (void)didReceivePowerCallback {
              NSLog(@"did receive power callback");
          }
          
          static void myPowerSourceCallbackType(void * context) {
              Main * obj = (__bridge Main *) context;
              [obj didReceivePowerCallback];
          }
          
          - (void)stop {
              NSLog(@"will stop");
              if (self.source == nil) {
                  NSLog(@"ignoring redundant stop");
                  return;
              }
              CFRunLoopSourceInvalidate(self.source);
              self.source = nil;
              NSLog(@"did stop");
          }
          
          - (void)runUntil:(NSDate *)deadline {
              do {
                  NSTimeInterval delay = [deadline timeIntervalSinceNow];
                  if (delay <= 0.0) {
                      break;
                  }
                  NSLog(@"will wait for %.1f", delay);
                  CFRunLoopRunInMode(kCFRunLoopDefaultMode, delay, true);
              } while (YES);
          }
          
          @end
          
          int main(int argc, char **argv) {
              #pragma unused(argc)
              #pragma unused(argv)
              Main * main = [[Main alloc] init];
              [main start];
              [main runUntil:[NSDate dateWithTimeIntervalSinceNow:10.0]];
              [main stop];
              return EXIT_SUCCESS;
          }