Search code examples
c++objective-cmacossystem-configuration

What are the function-pointer fields of an SCDynamicStoreContext for?


SCDynamicStoreContext is defined like this (version 0):

typedef struct {
      CFIndex        version;
      void *         info;
      const void *   (*retain)(const void *info);
      void           (*release)(const void *info);
      CFStringRef    (*copyDescription)(const void *info);
} SCDynamicStoreContext;

Various examples that I have seen of how to initialize an SCDynamicStoreContext (including one from Apple) all set the retain, release, and copyDescription fields to NULL, but I am wondering what these fields are for.

What are the implications of not passing a retain and release function when, for example, the info object is an NSObject?

What is the copyDescription function used for?


Solution

  • The lifetime of the SCDynamicStore object created by, for example, SCDynamicStoreCreate() is indeterminate. It will live until it is fully released. So long as it lives, it may call the supplied callback. When it does, it will pass the info pointer provided in the context. If you don't take steps to make sure that that pointer remains valid for as long as the dynamic store object lives, then the info pointer may become invalid. Your callback could cause a crash or misbehave if it accesses the info pointer after it has become invalid.

    The retain and release function pointers of the context allow the framework to give you a means to know how long that the info pointer must remain valid. It obviously must be valid (or NULL) at the time that the dynamic store is created. Furthermore, it must remain valid so long as any calls to the retain function have not been balanced by a corresponding call to the release function.

    If you don't provide retain and release functions, then either the info pointer must remain valid in perpetuity or for at least as long as the dynamic store object does, and you're responsible for ensuring that. That can be somewhat difficult because you don't always know what other APIs will retain the dynamic store object. It will definitely be kept alive so long as its run loop source is scheduled on a run loop, although removing the source from all run loops does not necessarily guarantee that it will be fully released at that moment.

    The copyDescription function is a means to enhance debugging output. For example, under certain circumstances, the framework may write a log message. It will try to describe the dynamic store object that encountered the circumstances. To do that in a manner which makes most sense to you the client, it can include a description of the info from the context. If it doesn't have a copyDescription function, the best it can do is record the pointer value. If it does, then it can write whatever description is provided by that function.

    Not coincidentally, the signatures of the three function pointers match those of CFRetain(), CFRelease(), and CFCopyDescription(). So, if info is a Core Foundation object or a Cocoa object (since NSObject is toll-free bridged to CFTypeRef), then you can supply those functions in the context and everything behaves as you'd expect.