Commits

Tuukka Norri committed 5abb9da

Thread safety, DTrace probes, encapsulation, OS compatibility
- Snow Leopard is now required for development and Leopard for deployment.
- Added new warning flags.
- Moved code in BXPGFunctionExpressionEvaluator.mm and BXDataModelCompiler.m to work around -Wundeclared-selector.
- Moved non-PostgreSQL specific DTrace probes to BXProbes.d.
- Oids are now stored into unsigned long type NSNumbers.
- Also removed the PGTS provider and renamed the probes.
- Fixed BXCFHostCompatibility.h so that it won't try to import iPhone specific header on Mac OS X.
- Made some constant qualifiers more clear.
- Made some methods safer by returning an immutable object.
- Wrote classes for encapsulating functionality in CFNetwork and SystemConfiguration and replaced the corresponding code in PGTSConnection and PGTSConnector. The classes use a CFRunLoop in a thread specific to the framework.
- Moved the class that uses AppKit-specific notifications to BaseTenAppKit. It still gets used if the framework is linked.
- Wrote documentation for various internal classes and marked the documentation \internal.
- Renamed various private methods for conformance with company guidelines.
- Wrote a class for serializing access to a socket. On Leopard, it uses a CFSocket and creates an observer to the thread in which it receives the -install message. On Snow Leopard, it uses a serial dispatch queue and Berkeley sockets.
- Added synchronization to some methods to make them thread safe.
- Changed PGTSConnectionMonitor so that it's no longer tied to PGTSConnection. Also renamed it to BXConnectionMonitor.
- Removed AppKit as a weak framework. Instead, declared only specific symbols as weak.

Comments (0)

Files changed (71)

BaseTen.xcodeproj/project.pbxproj

 		5329E7F9119F48BC000EC6ED /* pcre.h in Headers */ = {isa = PBXBuildFile; fileRef = 53C4E26B1194C757003FB842 /* pcre.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		5331CB5B0DEDA843003AF2A9 /* BXPGReconnectionRecoveryAttempter.h in Headers */ = {isa = PBXBuildFile; fileRef = 5331CB570DEDA843003AF2A9 /* BXPGReconnectionRecoveryAttempter.h */; };
 		5331CB5C0DEDA843003AF2A9 /* BXPGReconnectionRecoveryAttempter.m in Sources */ = {isa = PBXBuildFile; fileRef = 5331CB580DEDA843003AF2A9 /* BXPGReconnectionRecoveryAttempter.m */; };
+		5334324511A881F200B71D24 /* BXConnectionMonitor.h in Headers */ = {isa = PBXBuildFile; fileRef = 5334324311A881F200B71D24 /* BXConnectionMonitor.h */; };
+		5334324611A881F200B71D24 /* BXConnectionMonitor.m in Sources */ = {isa = PBXBuildFile; fileRef = 5334324411A881F200B71D24 /* BXConnectionMonitor.m */; };
 		53372E2A119AD74D0006F0A3 /* BXHostResolver.m in Sources */ = {isa = PBXBuildFile; fileRef = 53372E29119AD74D0006F0A3 /* BXHostResolver.m */; };
 		53372E2C119AD77C0006F0A3 /* BXHostResolver.h in Headers */ = {isa = PBXBuildFile; fileRef = 53372E2B119AD77C0006F0A3 /* BXHostResolver.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		5338E5540E5EE69E0045B6D7 /* BXPGInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 530132E109D460230037C485 /* BXPGInterface.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		5348B84A0F575EE100B2655E /* BXDatabaseObjectModelStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 535736CA0F333CCD00DB3D0B /* BXDatabaseObjectModelStorage.m */; };
 		534A14AF0F0FBBE6002A9F68 /* BaseTenModifications.sql.m4 in Resources */ = {isa = PBXBuildFile; fileRef = 534A14AE0F0FBBE6002A9F68 /* BaseTenModifications.sql.m4 */; };
 		534BE4680F34F7130098951C /* BXForeignKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 5328FBD40C4580CD006DE171 /* BXForeignKey.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		534E3C7D11A77088002D49C8 /* BXSocketReachabilityObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 534E3C7B11A77088002D49C8 /* BXSocketReachabilityObserver.h */; };
+		534E3C7E11A77088002D49C8 /* BXSocketReachabilityObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 534E3C7C11A77088002D49C8 /* BXSocketReachabilityObserver.m */; };
 		5350CC380EFBE66500EBC328 /* PGTSCollections.h in Headers */ = {isa = PBXBuildFile; fileRef = 5350CC360EFBE66500EBC328 /* PGTSCollections.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		5350CC390EFBE66500EBC328 /* PGTSCollections.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5350CC370EFBE66500EBC328 /* PGTSCollections.mm */; };
 		53526E0A0E5D70EB00B67550 /* BXPredicateVisitor.h in Headers */ = {isa = PBXBuildFile; fileRef = 53526E080E5D70EB00B67550 /* BXPredicateVisitor.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		5354F8840F004F9300422613 /* PGTSOids.m in Sources */ = {isa = PBXBuildFile; fileRef = 5354F8820F004F9300422613 /* PGTSOids.m */; };
 		5354F91E0F00511100422613 /* PGTSDeleteRule.h in Headers */ = {isa = PBXBuildFile; fileRef = 5354F91C0F00511100422613 /* PGTSDeleteRule.h */; };
 		5354F91F0F00511100422613 /* PGTSDeleteRule.m in Sources */ = {isa = PBXBuildFile; fileRef = 5354F91D0F00511100422613 /* PGTSDeleteRule.m */; };
-		5354F9410F00537200422613 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5354F9400F00537200422613 /* AppKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
+		5355C08911A8725700C5DEAF /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5355C08811A8725700C5DEAF /* CoreServices.framework */; };
 		5356277D0E6E7D1F002EA3FD /* BXPGInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 530132E209D460230037C485 /* BXPGInterface.m */; };
 		535661D10F025DD800920008 /* NSURL+BaseTenAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 535661CB0F025DD800920008 /* NSURL+BaseTenAdditions.m */; };
 		535661D20F025DD800920008 /* NSURL+BaseTenAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 535661CC0F025DD800920008 /* NSURL+BaseTenAdditions.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		53666CE70E1CD8D20028DBEA /* PGTSCertificateVerificationDelegateProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 53666CA80E1CD8D20028DBEA /* PGTSCertificateVerificationDelegateProtocol.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		53666CE90E1CD8D20028DBEA /* PGTSConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 53666CAA0E1CD8D20028DBEA /* PGTSConnection.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		53666CEA0E1CD8D20028DBEA /* PGTSConnection.mm in Sources */ = {isa = PBXBuildFile; fileRef = 53666CAB0E1CD8D20028DBEA /* PGTSConnection.mm */; };
-		53666CED0E1CD8D20028DBEA /* PGTSConnectionMonitor.h in Headers */ = {isa = PBXBuildFile; fileRef = 53666CAE0E1CD8D20028DBEA /* PGTSConnectionMonitor.h */; };
-		53666CEE0E1CD8D20028DBEA /* PGTSConnectionMonitor.m in Sources */ = {isa = PBXBuildFile; fileRef = 53666CAF0E1CD8D20028DBEA /* PGTSConnectionMonitor.m */; };
 		53666CF00E1CD8D20028DBEA /* PGTSConnectionPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 53666CB10E1CD8D20028DBEA /* PGTSConnectionPrivate.h */; };
 		53666CF10E1CD8D20028DBEA /* PGTSConnector.h in Headers */ = {isa = PBXBuildFile; fileRef = 53666CB20E1CD8D20028DBEA /* PGTSConnector.h */; };
 		53666CF20E1CD8D20028DBEA /* PGTSConnector.m in Sources */ = {isa = PBXBuildFile; fileRef = 53666CB30E1CD8D20028DBEA /* PGTSConnector.m */; };
 		536891C60F30A42600AAC65D /* BXPGForeignKeyDescription.mm in Sources */ = {isa = PBXBuildFile; fileRef = 536891C40F30A42600AAC65D /* BXPGForeignKeyDescription.mm */; };
 		536891C70F30A42600AAC65D /* BXPGForeignKeyDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 536891C50F30A42600AAC65D /* BXPGForeignKeyDescription.h */; };
 		536C9D600EFD94D10041422F /* BXEnumerate.h in Headers */ = {isa = PBXBuildFile; fileRef = 536C9D5F0EFD94D10041422F /* BXEnumerate.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		53776B9A11A7595C009F1A8E /* BXIOKitSystemEventNotifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 53776B9811A7595C009F1A8E /* BXIOKitSystemEventNotifier.m */; };
+		53776BA011A75B7F009F1A8E /* BXIOKitSystemEventNotifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 53776B9F11A75B7F009F1A8E /* BXIOKitSystemEventNotifier.h */; };
+		53776BA711A75DB3009F1A8E /* BXSystemEventNotifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 53776BA511A75DB3009F1A8E /* BXSystemEventNotifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		53776BA811A75DB3009F1A8E /* BXSystemEventNotifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 53776BA611A75DB3009F1A8E /* BXSystemEventNotifier.m */; };
 		537920580E3F519000423965 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D2F7E79907B2D74100F64583 /* CoreData.framework */; };
 		537A23B10E8404FA002AAE95 /* BXPGKeyPathExpressionValueType.h in Headers */ = {isa = PBXBuildFile; fileRef = 537A23AF0E8404FA002AAE95 /* BXPGKeyPathExpressionValueType.h */; };
 		537A23B20E8404FA002AAE95 /* BXPGKeyPathExpressionValueType.m in Sources */ = {isa = PBXBuildFile; fileRef = 537A23B00E8404FA002AAE95 /* BXPGKeyPathExpressionValueType.m */; };
 		53877EAE0E27667B0097C35F /* PGTSConstantValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 53877EAC0E27667B0097C35F /* PGTSConstantValue.m */; };
 		53877EEB0E2773E30097C35F /* NSRelationshipDescription+BXPGAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 53877EE90E2773E30097C35F /* NSRelationshipDescription+BXPGAdditions.h */; };
 		53877EEC0E2773E30097C35F /* NSRelationshipDescription+BXPGAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 53877EEA0E2773E30097C35F /* NSRelationshipDescription+BXPGAdditions.m */; };
+		538E031C11A4A5F700C3447F /* BXSocketDescriptor.h in Headers */ = {isa = PBXBuildFile; fileRef = 538E031A11A4A5F700C3447F /* BXSocketDescriptor.h */; };
+		538E031D11A4A5F700C3447F /* BXSocketDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 538E031B11A4A5F700C3447F /* BXSocketDescriptor.m */; };
+		538E032011A4A61F00C3447F /* BXRunLoopSocketDesciptor.h in Headers */ = {isa = PBXBuildFile; fileRef = 538E031E11A4A61F00C3447F /* BXRunLoopSocketDesciptor.h */; };
+		538E032111A4A61F00C3447F /* BXRunLoopSocketDesciptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 538E031F11A4A61F00C3447F /* BXRunLoopSocketDesciptor.m */; };
+		538E032411A4A63100C3447F /* BXDispatchSocketDescriptor.h in Headers */ = {isa = PBXBuildFile; fileRef = 538E032211A4A63100C3447F /* BXDispatchSocketDescriptor.h */; };
+		538E032511A4A63100C3447F /* BXDispatchSocketDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 538E032311A4A63100C3447F /* BXDispatchSocketDescriptor.m */; };
 		538FA0250F576278005EBFAC /* BXOpenSSLCompatibility.h in Headers */ = {isa = PBXBuildFile; fileRef = 538FA0240F576278005EBFAC /* BXOpenSSLCompatibility.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		5390DE590E32B788003980BE /* BXPGCurrentCompatVersion.m.m4 in Sources */ = {isa = PBXBuildFile; fileRef = 5390DE580E32B788003980BE /* BXPGCurrentCompatVersion.m.m4 */; };
 		53915F9E0E3FD22D0098B419 /* libpq_additions.h in Headers */ = {isa = PBXBuildFile; fileRef = 53915F9C0E3FD22D0098B419 /* libpq_additions.h */; };
 		533229E40A024C2500BDB151 /* BXEntityDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = BXEntityDescription.h; path = Sources/BXEntityDescription.h; sourceTree = "<group>"; };
 		533307E20A2283AD00EE9280 /* BXObjectStatusInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = BXObjectStatusInfo.h; path = Sources/BXObjectStatusInfo.h; sourceTree = "<group>"; };
 		533307E30A2283AD00EE9280 /* BXObjectStatusInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BXObjectStatusInfo.m; path = Sources/BXObjectStatusInfo.m; sourceTree = "<group>"; };
+		5334324311A881F200B71D24 /* BXConnectionMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXConnectionMonitor.h; path = Sources/BXConnectionMonitor.h; sourceTree = "<group>"; };
+		5334324411A881F200B71D24 /* BXConnectionMonitor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BXConnectionMonitor.m; path = Sources/BXConnectionMonitor.m; sourceTree = "<group>"; };
 		53372E29119AD74D0006F0A3 /* BXHostResolver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BXHostResolver.m; path = Sources/BXHostResolver.m; sourceTree = "<group>"; };
 		53372E2B119AD77C0006F0A3 /* BXHostResolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXHostResolver.h; path = Sources/BXHostResolver.h; sourceTree = "<group>"; };
 		5338E5C80E62CEAE0045B6D7 /* BXPGSQLFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXPGSQLFunction.h; path = Sources/BXPGSQLFunction.h; sourceTree = "<group>"; };
 		533BAACA0F2C000A0030CD05 /* PGTSTableDescription.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PGTSTableDescription.mm; path = Sources/PGTSTableDescription.mm; sourceTree = "<group>"; };
 		5347BB510B37F78000D963E7 /* BXDatabaseObjectIDPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = BXDatabaseObjectIDPrivate.h; path = Sources/BXDatabaseObjectIDPrivate.h; sourceTree = "<group>"; };
 		534A14AE0F0FBBE6002A9F68 /* BaseTenModifications.sql.m4 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = BaseTenModifications.sql.m4; path = Resources/BaseTenModifications.sql.m4; sourceTree = "<group>"; };
+		534E3C7B11A77088002D49C8 /* BXSocketReachabilityObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXSocketReachabilityObserver.h; path = Sources/BXSocketReachabilityObserver.h; sourceTree = "<group>"; };
+		534E3C7C11A77088002D49C8 /* BXSocketReachabilityObserver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BXSocketReachabilityObserver.m; path = Sources/BXSocketReachabilityObserver.m; sourceTree = "<group>"; };
 		534EE22F0E53213300B079B0 /* libBaseTen.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libBaseTen.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		5350CC360EFBE66500EBC328 /* PGTSCollections.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PGTSCollections.h; path = Sources/PGTSCollections.h; sourceTree = "<group>"; };
 		5350CC370EFBE66500EBC328 /* PGTSCollections.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PGTSCollections.mm; path = Sources/PGTSCollections.mm; sourceTree = "<group>"; };
 		5354F8820F004F9300422613 /* PGTSOids.m */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; name = PGTSOids.m; path = Sources/PGTSOids.m; sourceTree = "<group>"; };
 		5354F91C0F00511100422613 /* PGTSDeleteRule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PGTSDeleteRule.h; path = Sources/PGTSDeleteRule.h; sourceTree = "<group>"; };
 		5354F91D0F00511100422613 /* PGTSDeleteRule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PGTSDeleteRule.m; path = Sources/PGTSDeleteRule.m; sourceTree = "<group>"; };
-		5354F9400F00537200422613 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
+		5355C08811A8725700C5DEAF /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = /System/Library/Frameworks/CoreServices.framework; sourceTree = "<absolute>"; };
 		535661CB0F025DD800920008 /* NSURL+BaseTenAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSURL+BaseTenAdditions.m"; path = "Sources/NSURL+BaseTenAdditions.m"; sourceTree = "<group>"; };
 		535661CC0F025DD800920008 /* NSURL+BaseTenAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSURL+BaseTenAdditions.h"; path = "Sources/NSURL+BaseTenAdditions.h"; sourceTree = "<group>"; };
 		535661CD0F025DD800920008 /* NSArray+BaseTenAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSArray+BaseTenAdditions.h"; path = "Sources/NSArray+BaseTenAdditions.h"; sourceTree = "<group>"; };
 		53666CA80E1CD8D20028DBEA /* PGTSCertificateVerificationDelegateProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PGTSCertificateVerificationDelegateProtocol.h; path = Sources/PGTSCertificateVerificationDelegateProtocol.h; sourceTree = "<group>"; };
 		53666CAA0E1CD8D20028DBEA /* PGTSConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PGTSConnection.h; path = Sources/PGTSConnection.h; sourceTree = "<group>"; };
 		53666CAB0E1CD8D20028DBEA /* PGTSConnection.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PGTSConnection.mm; path = Sources/PGTSConnection.mm; sourceTree = "<group>"; };
-		53666CAE0E1CD8D20028DBEA /* PGTSConnectionMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PGTSConnectionMonitor.h; path = Sources/PGTSConnectionMonitor.h; sourceTree = "<group>"; };
-		53666CAF0E1CD8D20028DBEA /* PGTSConnectionMonitor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PGTSConnectionMonitor.m; path = Sources/PGTSConnectionMonitor.m; sourceTree = "<group>"; };
 		53666CB10E1CD8D20028DBEA /* PGTSConnectionPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PGTSConnectionPrivate.h; path = Sources/PGTSConnectionPrivate.h; sourceTree = "<group>"; };
 		53666CB20E1CD8D20028DBEA /* PGTSConnector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PGTSConnector.h; path = Sources/PGTSConnector.h; sourceTree = "<group>"; };
 		53666CB30E1CD8D20028DBEA /* PGTSConnector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PGTSConnector.m; path = Sources/PGTSConnector.m; sourceTree = "<group>"; };
 		536891C50F30A42600AAC65D /* BXPGForeignKeyDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXPGForeignKeyDescription.h; path = Sources/BXPGForeignKeyDescription.h; sourceTree = "<group>"; };
 		536892570F30B9E800AAC65D /* BXForeignKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BXForeignKey.m; path = Sources/BXForeignKey.m; sourceTree = "<group>"; };
 		536C9D5F0EFD94D10041422F /* BXEnumerate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXEnumerate.h; path = Sources/BXEnumerate.h; sourceTree = "<group>"; };
+		53776B9811A7595C009F1A8E /* BXIOKitSystemEventNotifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BXIOKitSystemEventNotifier.m; path = Sources/BXIOKitSystemEventNotifier.m; sourceTree = "<group>"; };
+		53776B9F11A75B7F009F1A8E /* BXIOKitSystemEventNotifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXIOKitSystemEventNotifier.h; path = Sources/BXIOKitSystemEventNotifier.h; sourceTree = "<group>"; };
+		53776BA511A75DB3009F1A8E /* BXSystemEventNotifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXSystemEventNotifier.h; path = Sources/BXSystemEventNotifier.h; sourceTree = "<group>"; };
+		53776BA611A75DB3009F1A8E /* BXSystemEventNotifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BXSystemEventNotifier.m; path = Sources/BXSystemEventNotifier.m; sourceTree = "<group>"; };
 		537A23570E83B8DC002AAE95 /* BXSubqueryExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXSubqueryExpression.h; path = Sources/BXSubqueryExpression.h; sourceTree = "<group>"; };
 		537A23580E83B8DC002AAE95 /* BXSubqueryExpression.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BXSubqueryExpression.m; path = Sources/BXSubqueryExpression.m; sourceTree = "<group>"; };
 		537A23AF0E8404FA002AAE95 /* BXPGKeyPathExpressionValueType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXPGKeyPathExpressionValueType.h; path = Sources/BXPGKeyPathExpressionValueType.h; sourceTree = "<group>"; };
 		53877EE90E2773E30097C35F /* NSRelationshipDescription+BXPGAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSRelationshipDescription+BXPGAdditions.h"; path = "Sources/NSRelationshipDescription+BXPGAdditions.h"; sourceTree = "<group>"; };
 		53877EEA0E2773E30097C35F /* NSRelationshipDescription+BXPGAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSRelationshipDescription+BXPGAdditions.m"; path = "Sources/NSRelationshipDescription+BXPGAdditions.m"; sourceTree = "<group>"; };
 		5389E1A20C464107002714B8 /* BXRelationshipDescriptionPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXRelationshipDescriptionPrivate.h; path = Sources/BXRelationshipDescriptionPrivate.h; sourceTree = "<group>"; };
+		538E031A11A4A5F700C3447F /* BXSocketDescriptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXSocketDescriptor.h; path = Sources/BXSocketDescriptor.h; sourceTree = "<group>"; };
+		538E031B11A4A5F700C3447F /* BXSocketDescriptor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BXSocketDescriptor.m; path = Sources/BXSocketDescriptor.m; sourceTree = "<group>"; };
+		538E031E11A4A61F00C3447F /* BXRunLoopSocketDesciptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXRunLoopSocketDesciptor.h; path = Sources/BXRunLoopSocketDesciptor.h; sourceTree = "<group>"; };
+		538E031F11A4A61F00C3447F /* BXRunLoopSocketDesciptor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BXRunLoopSocketDesciptor.m; path = Sources/BXRunLoopSocketDesciptor.m; sourceTree = "<group>"; };
+		538E032211A4A63100C3447F /* BXDispatchSocketDescriptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXDispatchSocketDescriptor.h; path = Sources/BXDispatchSocketDescriptor.h; sourceTree = "<group>"; };
+		538E032311A4A63100C3447F /* BXDispatchSocketDescriptor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BXDispatchSocketDescriptor.m; path = Sources/BXDispatchSocketDescriptor.m; sourceTree = "<group>"; };
 		538FA0240F576278005EBFAC /* BXOpenSSLCompatibility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXOpenSSLCompatibility.h; path = Sources/BXOpenSSLCompatibility.h; sourceTree = "<group>"; };
 		5390DE580E32B788003980BE /* BXPGCurrentCompatVersion.m.m4 */ = {isa = PBXFileReference; explicitFileType = sourcecode; fileEncoding = 4; name = BXPGCurrentCompatVersion.m.m4; path = Sources/BXPGCurrentCompatVersion.m.m4; sourceTree = "<group>"; };
 		53915F9C0E3FD22D0098B419 /* libpq_additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = libpq_additions.h; path = Sources/libpq_additions.h; sourceTree = "<group>"; };
 				538679880DE31C1D000C9A78 /* libstdc++.6.dylib in Frameworks */,
 				537920580E3F519000423965 /* CoreData.framework in Frameworks */,
 				53D69A880EAE072A00C4C22D /* SystemConfiguration.framework in Frameworks */,
-				5354F9410F00537200422613 /* AppKit.framework in Frameworks */,
 				535B3E1E1038146500A5FB7E /* libpcre.a in Frameworks */,
+				5355C08911A8725700C5DEAF /* CoreServices.framework in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 				53DBE8010B666C3B00C3D20A /* libcrypto.dylib */,
 				53DBE8120B666C7900C3D20A /* libssl.dylib */,
 				538679870DE31C1D000C9A78 /* libstdc++.6.dylib */,
+				D2F7E79907B2D74100F64583 /* CoreData.framework */,
+				5355C08811A8725700C5DEAF /* CoreServices.framework */,
 				0867D69BFE84028FC02AAC07 /* Foundation.framework */,
-				5354F9400F00537200422613 /* AppKit.framework */,
-				D2F7E79907B2D74100F64583 /* CoreData.framework */,
+				538678D30DE31BA0000C9A78 /* IOKit.framework */,
 				531266E40B68F9CA00637EDA /* Security.framework */,
-				538678D30DE31BA0000C9A78 /* IOKit.framework */,
 				53D69A870EAE072A00C4C22D /* SystemConfiguration.framework */,
 				53E11A250A791A8D00D0107C /* ExceptionHandling.framework */,
 				53EFE9E00BA96444008666B7 /* BaseTenAppKit.xcodeproj */,
 			name = Relationships;
 			sourceTree = "<group>";
 		};
+		533433B411A8AEA800B71D24 /* Network */ = {
+			isa = PBXGroup;
+			children = (
+				53372E2B119AD77C0006F0A3 /* BXHostResolver.h */,
+				53372E29119AD74D0006F0A3 /* BXHostResolver.m */,
+				5334324311A881F200B71D24 /* BXConnectionMonitor.h */,
+				5334324411A881F200B71D24 /* BXConnectionMonitor.m */,
+				534E3C7B11A77088002D49C8 /* BXSocketReachabilityObserver.h */,
+				534E3C7C11A77088002D49C8 /* BXSocketReachabilityObserver.m */,
+				538E032711A4A72300C3447F /* Socket descriptor */,
+			);
+			name = Network;
+			sourceTree = "<group>";
+		};
+		534E3C5F11A76F49002D49C8 /* Foundation additions */ = {
+			isa = PBXGroup;
+			children = (
+				53666CC20E1CD8D20028DBEA /* PGTSHOM.h */,
+				53666CC30E1CD8D20028DBEA /* PGTSHOM.m */,
+				535661CC0F025DD800920008 /* NSURL+BaseTenAdditions.h */,
+				535661CB0F025DD800920008 /* NSURL+BaseTenAdditions.m */,
+				535661CD0F025DD800920008 /* NSArray+BaseTenAdditions.h */,
+				535661CE0F025DD800920008 /* NSArray+BaseTenAdditions.m */,
+				530A69811199A5BA00ED63FD /* NSDictionary+BaseTenAdditions.h */,
+				530A69821199A5BA00ED63FD /* NSDictionary+BaseTenAdditions.m */,
+				535661D00F025DD800920008 /* NSPredicate+BaseTenAdditions.h */,
+				535661CF0F025DD800920008 /* NSPredicate+BaseTenAdditions.m */,
+				538334C30F03F4DF0040368E /* NSString+PGTSAdditions.h */,
+				538334C40F03F4DF0040368E /* NSString+PGTSAdditions.m */,
+				5354F7DC0F00417400422613 /* BXURLEncoding.h */,
+				5354F7DD0F00417400422613 /* BXURLEncoding.m */,
+			);
+			name = "Foundation additions";
+			sourceTree = "<group>";
+		};
+		534E3C6211A76F81002D49C8 /* Unneeded */ = {
+			isa = PBXGroup;
+			children = (
+				537A23570E83B8DC002AAE95 /* BXSubqueryExpression.h */,
+				537A23580E83B8DC002AAE95 /* BXSubqueryExpression.m */,
+				53A59B230E34EB570026D7E1 /* BXWeakNotification.h */,
+				53A59B240E34EB570026D7E1 /* BXWeakNotification.m */,
+			);
+			name = Unneeded;
+			sourceTree = "<group>";
+		};
 		535738400F33695000DB3D0B /* Object model */ = {
 			isa = PBXGroup;
 			children = (
 		53666C800E1CD8580028DBEA /* Utility */ = {
 			isa = PBXGroup;
 			children = (
+				533433B411A8AEA800B71D24 /* Network */,
+				53776B9B11A75964009F1A8E /* System event notifier */,
+				534E3C5F11A76F49002D49C8 /* Foundation additions */,
 				538FA0240F576278005EBFAC /* BXOpenSSLCompatibility.h */,
 				53C4C3F31192EC10003FB842 /* BXCFHostCompatibility.h */,
 				5354F87A0F004A6600422613 /* BXExport.h */,
 				53015A830FBEF18800E52C1E /* BXArraySize.h */,
 				53ED2E8C0E1AB7CB0095BE8B /* BXLogger.h */,
 				5364EF5B0E1B940A003D3DB6 /* BXLogger.m */,
-				53A59B230E34EB570026D7E1 /* BXWeakNotification.h */,
-				53A59B240E34EB570026D7E1 /* BXWeakNotification.m */,
 				539ACEC60E3B3FF7006602B5 /* BXDelegateProxy.h */,
 				539ACEC70E3B3FF7006602B5 /* BXDelegateProxy.m */,
 				53680C0C0E59922C00A53B26 /* BXKeyPathParser.h */,
 				53680C0D0E59922C00A53B26 /* BXKeyPathParser.m */,
-				5354F7DC0F00417400422613 /* BXURLEncoding.h */,
-				5354F7DD0F00417400422613 /* BXURLEncoding.m */,
 				53BFE53B0FAF2EFA0004533F /* BXError.h */,
 				53BFE53C0FAF2EFA0004533F /* BXError.m */,
 				5339AB910A7542EC00994B1A /* BXException.h */,
 				5339AB920A7542EC00994B1A /* BXException.m */,
-				53372E2B119AD77C0006F0A3 /* BXHostResolver.h */,
-				53372E29119AD74D0006F0A3 /* BXHostResolver.m */,
 				5329E7F7119F4878000EC6ED /* BXRegularExpressions.h */,
 				5329E7F5119F4845000EC6ED /* BXRegularExpressions.m */,
-				53666CC20E1CD8D20028DBEA /* PGTSHOM.h */,
-				53666CC30E1CD8D20028DBEA /* PGTSHOM.m */,
 				53937B650EFD097700510DBD /* PGTSInvocationRecorder.h */,
 				53937B660EFD097700510DBD /* PGTSInvocationRecorder.m */,
 				5350CC360EFBE66500EBC328 /* PGTSCollections.h */,
 				5354F8820F004F9300422613 /* PGTSOids.m */,
 				5354F91C0F00511100422613 /* PGTSDeleteRule.h */,
 				5354F91D0F00511100422613 /* PGTSDeleteRule.m */,
-				535661CC0F025DD800920008 /* NSURL+BaseTenAdditions.h */,
-				535661CB0F025DD800920008 /* NSURL+BaseTenAdditions.m */,
-				535661CD0F025DD800920008 /* NSArray+BaseTenAdditions.h */,
-				535661CE0F025DD800920008 /* NSArray+BaseTenAdditions.m */,
-				530A69811199A5BA00ED63FD /* NSDictionary+BaseTenAdditions.h */,
-				530A69821199A5BA00ED63FD /* NSDictionary+BaseTenAdditions.m */,
-				535661D00F025DD800920008 /* NSPredicate+BaseTenAdditions.h */,
-				535661CF0F025DD800920008 /* NSPredicate+BaseTenAdditions.m */,
-				538334C30F03F4DF0040368E /* NSString+PGTSAdditions.h */,
-				538334C40F03F4DF0040368E /* NSString+PGTSAdditions.m */,
-				537A23570E83B8DC002AAE95 /* BXSubqueryExpression.h */,
-				537A23580E83B8DC002AAE95 /* BXSubqueryExpression.m */,
+				534E3C6211A76F81002D49C8 /* Unneeded */,
 				536C9E8D0EFDAFF20041422F /* Remember to remove */,
 			);
 			name = Utility;
 		53666D850E1CDFF80028DBEA /* Connection */ = {
 			isa = PBXGroup;
 			children = (
-				53666CC60E1CD8D20028DBEA /* PGTSNotification.h */,
-				53666CC70E1CD8D20028DBEA /* PGTSNotification.m */,
+				53666CAA0E1CD8D20028DBEA /* PGTSConnection.h */,
+				53666CB10E1CD8D20028DBEA /* PGTSConnectionPrivate.h */,
+				53666CAB0E1CD8D20028DBEA /* PGTSConnection.mm */,
 				53666CB20E1CD8D20028DBEA /* PGTSConnector.h */,
 				53666CB30E1CD8D20028DBEA /* PGTSConnector.m */,
 				530A6A541199B9CA00ED63FD /* PGTSSynchronousConnector.h */,
 				530A6A551199B9CA00ED63FD /* PGTSSynchronousConnector.m */,
 				530A6A521199B9CA00ED63FD /* PGTSAsynchronousConnector.h */,
 				530A6A531199B9CA00ED63FD /* PGTSAsynchronousConnector.m */,
-				53666CAA0E1CD8D20028DBEA /* PGTSConnection.h */,
-				53666CB10E1CD8D20028DBEA /* PGTSConnectionPrivate.h */,
-				53666CAB0E1CD8D20028DBEA /* PGTSConnection.mm */,
-				53666CAE0E1CD8D20028DBEA /* PGTSConnectionMonitor.h */,
-				53666CAF0E1CD8D20028DBEA /* PGTSConnectionMonitor.m */,
 			);
 			name = Connection;
 			sourceTree = "<group>";
 				53666CA80E1CD8D20028DBEA /* PGTSCertificateVerificationDelegateProtocol.h */,
 				53666CB40E1CD8D20028DBEA /* PGTSConstants.h */,
 				53666CB50E1CD8D20028DBEA /* PGTSConstants.m */,
+				53666CC60E1CD8D20028DBEA /* PGTSNotification.h */,
+				53666CC70E1CD8D20028DBEA /* PGTSNotification.m */,
 				53915F9C0E3FD22D0098B419 /* libpq_additions.h */,
 				53915F9D0E3FD22D0098B419 /* libpq_additions.c */,
 			);
 			name = "Remember to remove";
 			sourceTree = "<group>";
 		};
+		53776B9B11A75964009F1A8E /* System event notifier */ = {
+			isa = PBXGroup;
+			children = (
+				53776BA511A75DB3009F1A8E /* BXSystemEventNotifier.h */,
+				53776BA611A75DB3009F1A8E /* BXSystemEventNotifier.m */,
+				53776B9F11A75B7F009F1A8E /* BXIOKitSystemEventNotifier.h */,
+				53776B9811A7595C009F1A8E /* BXIOKitSystemEventNotifier.m */,
+			);
+			name = "System event notifier";
+			sourceTree = "<group>";
+		};
 		537A23C00E84055F002AAE95 /* Expression value types */ = {
 			isa = PBXGroup;
 			children = (
 			name = "Automatically-updating containers";
 			sourceTree = "<group>";
 		};
+		538E032711A4A72300C3447F /* Socket descriptor */ = {
+			isa = PBXGroup;
+			children = (
+				538E031A11A4A5F700C3447F /* BXSocketDescriptor.h */,
+				538E031B11A4A5F700C3447F /* BXSocketDescriptor.m */,
+				538E031E11A4A61F00C3447F /* BXRunLoopSocketDesciptor.h */,
+				538E031F11A4A61F00C3447F /* BXRunLoopSocketDesciptor.m */,
+				538E032211A4A63100C3447F /* BXDispatchSocketDescriptor.h */,
+				538E032311A4A63100C3447F /* BXDispatchSocketDescriptor.m */,
+			);
+			name = "Socket descriptor";
+			sourceTree = "<group>";
+		};
 		539758B50E1EB25F0042120A /* SQL Schema Generation */ = {
 			isa = PBXGroup;
 			children = (
 				53666CE50E1CD8D20028DBEA /* PGTSCertificateVerificationDelegate.h in Headers */,
 				53666CE70E1CD8D20028DBEA /* PGTSCertificateVerificationDelegateProtocol.h in Headers */,
 				53666CE90E1CD8D20028DBEA /* PGTSConnection.h in Headers */,
-				53666CED0E1CD8D20028DBEA /* PGTSConnectionMonitor.h in Headers */,
 				53666CF00E1CD8D20028DBEA /* PGTSConnectionPrivate.h in Headers */,
 				53666CF10E1CD8D20028DBEA /* PGTSConnector.h in Headers */,
 				53666CF30E1CD8D20028DBEA /* PGTSConstants.h in Headers */,
 				53372E2C119AD77C0006F0A3 /* BXHostResolver.h in Headers */,
 				5329E7F8119F4878000EC6ED /* BXRegularExpressions.h in Headers */,
 				5329E7F9119F48BC000EC6ED /* pcre.h in Headers */,
+				538E031C11A4A5F700C3447F /* BXSocketDescriptor.h in Headers */,
+				538E032011A4A61F00C3447F /* BXRunLoopSocketDesciptor.h in Headers */,
+				538E032411A4A63100C3447F /* BXDispatchSocketDescriptor.h in Headers */,
+				53776BA011A75B7F009F1A8E /* BXIOKitSystemEventNotifier.h in Headers */,
+				53776BA711A75DB3009F1A8E /* BXSystemEventNotifier.h in Headers */,
+				534E3C7D11A77088002D49C8 /* BXSocketReachabilityObserver.h in Headers */,
+				5334324511A881F200B71D24 /* BXConnectionMonitor.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 				53666CE40E1CD8D20028DBEA /* PGTSAdditions.m in Sources */,
 				53666CE60E1CD8D20028DBEA /* PGTSCertificateVerificationDelegate.m in Sources */,
 				53666CEA0E1CD8D20028DBEA /* PGTSConnection.mm in Sources */,
-				53666CEE0E1CD8D20028DBEA /* PGTSConnectionMonitor.m in Sources */,
 				53666CF20E1CD8D20028DBEA /* PGTSConnector.m in Sources */,
 				53666CF40E1CD8D20028DBEA /* PGTSConstants.m in Sources */,
 				53666CFE0E1CD8D20028DBEA /* PGTSFoundationObjects.m in Sources */,
 				530A6A591199B9CA00ED63FD /* PGTSSynchronousConnector.m in Sources */,
 				53372E2A119AD74D0006F0A3 /* BXHostResolver.m in Sources */,
 				5329E7F6119F4845000EC6ED /* BXRegularExpressions.m in Sources */,
+				538E031D11A4A5F700C3447F /* BXSocketDescriptor.m in Sources */,
+				538E032111A4A61F00C3447F /* BXRunLoopSocketDesciptor.m in Sources */,
+				538E032511A4A63100C3447F /* BXDispatchSocketDescriptor.m in Sources */,
+				53776B9A11A7595C009F1A8E /* BXIOKitSystemEventNotifier.m in Sources */,
+				53776BA811A75DB3009F1A8E /* BXSystemEventNotifier.m in Sources */,
+				534E3C7E11A77088002D49C8 /* BXSocketReachabilityObserver.m in Sources */,
+				5334324611A881F200B71D24 /* BXConnectionMonitor.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

BaseTenAppKit/BaseTenAppKit.xcodeproj/project.pbxproj

 		5354447D0D634D9C002A6C47 /* BXNetServiceConnector.m in Sources */ = {isa = PBXBuildFile; fileRef = 532D60E00B944D8C0028E90B /* BXNetServiceConnector.m */; };
 		535444800D634D9C002A6C47 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
 		535444820D634D9C002A6C47 /* SecurityInterface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 531650C30B72040700785454 /* SecurityInterface.framework */; };
+		5355C15311A8744700C5DEAF /* BXAppKitSystemEventNotifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 5355C15111A8744700C5DEAF /* BXAppKitSystemEventNotifier.h */; };
+		5355C15411A8744700C5DEAF /* BXAppKitSystemEventNotifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 5355C15211A8744700C5DEAF /* BXAppKitSystemEventNotifier.m */; };
 		53ED303F0E1ACBA80095BE8B /* BaseTen.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5354443E0D634CA4002A6C47 /* BaseTen.framework */; };
 		53F137CD0EB074C400D0F517 /* WaitForNetworkWindow.nib in Resources */ = {isa = PBXBuildFile; fileRef = 53F137CB0EB074C400D0F517 /* WaitForNetworkWindow.nib */; };
 /* End PBXBuildFile section */
 		5354444C0D634D63002A6C47 /* release-non-gc.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = "release-non-gc.xcconfig"; path = "xcconfig/release-non-gc.xcconfig"; sourceTree = "<group>"; };
 		5354444D0D634D63002A6C47 /* common.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = common.xcconfig; path = xcconfig/common.xcconfig; sourceTree = "<group>"; };
 		535444870D634D9C002A6C47 /* BaseTenAppKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BaseTenAppKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		5355C15111A8744700C5DEAF /* BXAppKitSystemEventNotifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXAppKitSystemEventNotifier.h; path = Sources/BXAppKitSystemEventNotifier.h; sourceTree = "<group>"; };
+		5355C15211A8744700C5DEAF /* BXAppKitSystemEventNotifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BXAppKitSystemEventNotifier.m; path = Sources/BXAppKitSystemEventNotifier.m; sourceTree = "<group>"; };
 		5364C8C90A222FA600AD8AAF /* BXObjectStatusToColorTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXObjectStatusToColorTransformer.h; path = Sources/BXObjectStatusToColorTransformer.h; sourceTree = "<group>"; };
 		5364C8CA0A222FA600AD8AAF /* BXObjectStatusToColorTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BXObjectStatusToColorTransformer.m; path = Sources/BXObjectStatusToColorTransformer.m; sourceTree = "<group>"; };
 		53726D830A30E4A30086BB60 /* BXObjectStatusToEditableTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXObjectStatusToEditableTransformer.h; path = Sources/BXObjectStatusToEditableTransformer.h; sourceTree = "<group>"; };
 			children = (
 				53D0D1590B6F896200D2D101 /* BXDatabaseContextAdditions.h */,
 				53D0D15A0B6F896200D2D101 /* BXDatabaseContextAdditions.m */,
+				5355C15111A8744700C5DEAF /* BXAppKitSystemEventNotifier.h */,
+				5355C15211A8744700C5DEAF /* BXAppKitSystemEventNotifier.m */,
 				531060190B905E44009329AD /* NSController Subclasses */,
 				5310601A0B905E59009329AD /* Connection views and panels */,
 				53726DAD0A30E8FD0086BB60 /* Transformers */,
 				53174ED40F52073600551EBC /* BXConnectByHostnameViewController.h in Headers */,
 				53174F000F5209E300551EBC /* BXHostPanel.h in Headers */,
 				53174F670F52182700551EBC /* BXConnectionViewController.h in Headers */,
+				5355C15311A8744700C5DEAF /* BXAppKitSystemEventNotifier.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 				53174EFF0F5209E300551EBC /* BXHostPanel.m in Sources */,
 				53174F680F52182700551EBC /* BXConnectionViewController.m in Sources */,
 				5302F39F0F536C4500105ECD /* BXAuthenticationPanel.m in Sources */,
+				5355C15411A8744700C5DEAF /* BXAppKitSystemEventNotifier.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

BaseTenAppKit/Sources/BXAppKitSystemEventNotifier.h

+//
+// BXAppKitSystemEventNotifier.h
+// BaseTen
+//
+// Copyright (C) 2010 Marko Karppinen & Co. LLC.
+//
+// Before using this software, please review the available licensing options
+// by visiting http://www.karppinen.fi/baseten/licensing/ or by contacting
+// us at sales@karppinen.fi. Without an additional license, this software
+// may be distributed only in compliance with the GNU General Public License.
+//
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License, version 2.0,
+// as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// $Id$
+//
+
+#import <BaseTen/BXSystemEventNotifier.h>
+
+
+BX_EXPORT Class BXAppKitSystemEventNotifierClass;
+@interface BXAppKitSystemEventNotifier : BXSystemEventNotifier
+{
+}
+@end

BaseTenAppKit/Sources/BXAppKitSystemEventNotifier.m

+//
+// BXAppKitSystemEventNotifier.m
+// BaseTen
+//
+// Copyright (C) 2008-2010 Marko Karppinen & Co. LLC.
+//
+// Before using this software, please review the available licensing options
+// by visiting http://www.karppinen.fi/baseten/licensing/ or by contacting
+// us at sales@karppinen.fi. Without an additional license, this software
+// may be distributed only in compliance with the GNU General Public License.
+//
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License, version 2.0,
+// as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// $Id$
+//
+
+#import "BXAppKitSystemEventNotifier.h"
+#import <AppKit/AppKit.h>
+
+
+static void __attribute__((constructor))
+Constructor ()
+{
+	BXAppKitSystemEventNotifierClass = [BXAppKitSystemEventNotifier class];
+}
+
+
+
+@implementation BXAppKitSystemEventNotifier
+- (void) _applicationWillTerminate: (NSNotification *) notification
+{
+	[self processWillExit];
+}
+
+
+- (void) _workspaceWillSleep: (NSNotification *) notification
+{
+	[self systemWillSleep];
+}
+
+
+- (void) _workspaceDidWake: (NSNotification *) notification
+{
+	[self systemDidWake];
+}
+
+
++ (id) copyNotifier
+{
+	return [[self alloc] init];
+}
+
+
+- (id) init
+{
+	if ((self = [super init]))
+	{
+		NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
+		[nc addObserver: self 
+			   selector: @selector (_applicationWillTerminate:)
+				   name: NSApplicationWillTerminateNotification 
+				 object: NSApp];
+		
+		nc = [[NSWorkspace sharedWorkspace] notificationCenter];
+		[nc addObserver: self 
+			   selector: @selector (_workspaceWillSleep:) 
+				   name: NSWorkspaceWillSleepNotification 
+				 object: nil];
+		[nc addObserver: self 
+			   selector: @selector (_workspaceDidWake:) 
+				   name: NSWorkspaceDidWakeNotification 
+				 object: nil];
+	}
+	return self;
+}
+
+
+- (void) dealloc
+{
+	[[NSNotificationCenter defaultCenter] removeObserver: self];
+	[[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver: self];
+	
+	[super dealloc];
+}
+@end

BaseTenAppKit/Sources/BXDatabaseContextAdditions.m

 
 
 @implementation BXDatabaseContext (BaseTenAppKitAdditions)
-
 - (void) awakeFromNib
 {
 	[(BXDelegateProxy *) mDelegateProxy setDelegateForBXDelegateProxy: delegate];

BaseTenAppKit/xcconfig/common.xcconfig

-#include "../../common-xcconfig/10.4.xcconfig"
+#include "../../common-xcconfig/10.5.xcconfig"
 #include "../../common-xcconfig/common.xcconfig"
 #include "../../common-xcconfig/framework.xcconfig"
 

Sources/BXCFHostCompatibility.h

 
 #import <TargetConditionals.h>
 
-#ifdef TARGET_OS_IPHONE
+#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
 #import <CFNetwork/CFHost.h>
 #else
 #import <CoreFoundation/CoreFoundation.h>

Sources/BXConnectionMonitor.h

+//
+// BXConnectionMonitor.h
+// BaseTen
+//
+// Copyright (C) 2008-2010 Marko Karppinen & Co. LLC.
+//
+// Before using this software, please review the available licensing options
+// by visiting http://www.karppinen.fi/baseten/licensing/ or by contacting
+// us at sales@karppinen.fi. Without an additional license, this software
+// may be distributed only in compliance with the GNU General Public License.
+//
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License, version 2.0,
+// as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// $Id$
+//
+
+#import <Foundation/Foundation.h>
+#import <BaseTen/BXSocketReachabilityObserver.h>
+#import <SystemConfiguration/SystemConfiguration.h>
+@class BXConnectionMonitor;
+@class BXSystemEventNotifier;
+@class BXConnectionMonitorThread;
+
+
+
+@protocol BXConnectionMonitorClient <NSObject>
+- (int) socketForConnectionMonitor: (BXConnectionMonitor *) monitor;
+- (void) connectionMonitorProcessWillExit: (BXConnectionMonitor *) monitor;
+- (void) connectionMonitorSystemWillSleep: (BXConnectionMonitor *) monitor;
+- (void) connectionMonitorSystemDidWake: (BXConnectionMonitor *) monitor;
+- (void) connectionMonitor: (BXConnectionMonitor *) monitor
+	  networkStatusChanged: (SCNetworkConnectionFlags) flags;
+@end
+
+
+
+@interface BXConnectionMonitor : NSObject 
+{
+	CFMutableDictionaryRef mConnections;
+	BXSystemEventNotifier *mSystemEventNotifier;
+	BXConnectionMonitorThread *mMonitorThread;
+}
++ (id) sharedInstance;
+
+- (void) clientDidStartConnectionAttempt: (id <BXConnectionMonitorClient>) connection;
+- (void) clientDidFailConnectionAttempt: (id <BXConnectionMonitorClient>) connection;
+- (void) clientDidConnect: (id <BXConnectionMonitorClient>) connection;
+- (void) clientWillDisconnect: (id <BXConnectionMonitorClient>) connection;
+@end
+
+
+
+@interface BXConnectionMonitor (BXSocketReachabilityObserverDelegate) <BXSocketReachabilityObserverDelegate>
+@end

Sources/BXConnectionMonitor.m

+//
+// BXConnectionMonitor.m
+// BaseTen
+//
+// Copyright (C) 2008-2010 Marko Karppinen & Co. LLC.
+//
+// Before using this software, please review the available licensing options
+// by visiting http://www.karppinen.fi/baseten/licensing/ or by contacting
+// us at sales@karppinen.fi. Without an additional license, this software
+// may be distributed only in compliance with the GNU General Public License.
+//
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License, version 2.0,
+// as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// $Id$
+//
+
+#import "BXConnectionMonitor.h"
+#import "BXSocketReachabilityObserver.h"
+#import "BXSystemEventNotifier.h"
+#import "BXArraySize.h"
+#import "BXLogger.h"
+#import "BXEnumerate.h"
+#import <libkern/OSAtomic.h>
+
+
+
+@interface BXConnectionMonitorThread : NSThread
+{
+	CFRunLoopRef mRunLoop;
+}
+@end
+
+
+
+static NSArray*
+DictionaryKeys (CFDictionaryRef dict)
+{
+	NSArray *retval = nil;
+	@synchronized ((id) dict)
+	{
+		retval = [(id) dict allKeys];
+	}
+	return retval;
+}
+
+
+
+@implementation BXConnectionMonitorThread
+- (void) main
+{
+	mRunLoop = CFRunLoopGetCurrent ();
+	
+	NSPort *port = [NSPort port];
+	[port scheduleInRunLoop: [NSRunLoop currentRunLoop] forMode: NSDefaultRunLoopMode];
+	
+	while (1)
+	{
+		NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+		SInt32 res = CFRunLoopRunInMode (kCFRunLoopDefaultMode, 0, false);
+		[pool drain];
+
+		if (kCFRunLoopRunStopped == res || kCFRunLoopRunFinished == res)
+			break;
+	}
+	
+	mRunLoop = NULL;
+}
+
+
+- (CFRunLoopRef) runLoop
+{
+	return mRunLoop;
+}
+@end
+
+
+
+/**
+ * \internal
+ * \brief A façade for various event monitors.
+ * \note Instances of this class may be used from multiple threads after creation.
+ *       However, in-order execution isn't enforced for -clientDidConnect: and
+ *       -clientWillDisconnect:.
+ * \ingroup basetenutility
+ */
+@implementation BXConnectionMonitor
+- (void) _scheduleObserver: (BXSocketReachabilityObserver *) observer
+{
+	[observer setRunLoop: [mMonitorThread runLoop]];
+	[observer install];
+}
+
+
+- (void) _scheduleSystemEventNotifier: (BXSystemEventNotifier *) notifier
+{
+	[notifier install];
+}
+
+
+- (void) _processWillExit: (NSNotification *) notification
+{
+	for (id <BXConnectionMonitorClient> connection in DictionaryKeys (mConnections))
+		[connection connectionMonitorProcessWillExit: self];
+}
+
+
+- (void) _systemWillSleep: (NSNotification *) notification
+{
+	for (id <BXConnectionMonitorClient> connection in DictionaryKeys (mConnections))
+		[connection connectionMonitorSystemWillSleep: self];
+}
+
+
+- (void) _systemDidWake: (NSNotification *) notification
+{
+	for (id <BXConnectionMonitorClient> connection in DictionaryKeys (mConnections))
+		[connection connectionMonitorSystemDidWake: self];
+}
+
+
++ (id) sharedInstance
+{
+	__strong static id sharedInstance = nil;
+	@synchronized (self)
+	{
+		if (! sharedInstance)
+		{
+			sharedInstance = [[BXConnectionMonitor alloc] init];
+		}
+	}
+	return sharedInstance;
+}
+
+
+- (id) init
+{
+	if ((self = [super init]))
+	{
+		{
+			mSystemEventNotifier = [BXSystemEventNotifier copyNotifier];
+			NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+			SEL const callbacks [] = {
+				@selector (_processWillExit:),
+				@selector (_systemWillSleep:),
+				@selector (_systemDidWake:)
+			};
+			NSString * const notifications [] = {
+				kBXSystemEventNotifierProcessWillExitNotification,
+				kBXSystemEventNotifierSystemWillSleepNotification,
+				kBXSystemEventNotifierSystemDidWakeNotification
+			};
+			
+			unsigned int count = BXArraySize (callbacks);
+			Expect (BXArraySize (notifications) == count);
+			for (unsigned int i = 0; i < count; i++)
+				[nc addObserver: self selector: callbacks [i] name: notifications [i] object: mSystemEventNotifier];
+		}
+		
+		mConnections = CFDictionaryCreateMutable (kCFAllocatorDefault, 0, 
+												  &kCFTypeDictionaryKeyCallBacks,
+												  &kCFTypeDictionaryValueCallBacks);
+		mMonitorThread = [[BXConnectionMonitorThread alloc] init];
+		[mMonitorThread setName: @"org.basetenframework.ConnectionMonitorThread"];
+		[mMonitorThread start];
+		
+		OSMemoryBarrier (); // Make sure that the variables get written.
+		[self performSelector: @selector (_scheduleSystemEventNotifier:)
+					 onThread: mMonitorThread 
+				   withObject: mSystemEventNotifier
+				waitUntilDone: NO];
+	}
+	return self;
+}
+
+
+- (void) dealloc
+{
+	[[NSNotificationCenter defaultCenter] removeObserver: self];
+	[mSystemEventNotifier release];
+	
+	CFRunLoopRef runLoop = [mMonitorThread runLoop];
+	if (runLoop)
+		CFRunLoopStop ([mMonitorThread runLoop]);
+	
+	[mMonitorThread release];
+	
+	if (mConnections)
+		CFRelease (mConnections);
+	
+	[super dealloc];
+}
+
+
+- (void) finalize
+{
+	CFRunLoopRef runLoop = [mMonitorThread runLoop];
+	if (runLoop)
+		CFRunLoopStop ([mMonitorThread runLoop]);
+	
+	[mSystemEventNotifier invalidate];
+	
+	if (mConnections)
+		CFRelease (mConnections);
+
+	[super finalize];
+}
+
+
+- (void) clientDidStartConnectionAttempt: (id <BXConnectionMonitorClient>) connection
+{
+	@synchronized ((id) mConnections)
+	{
+		CFDictionarySetValue (mConnections, connection, kCFNull);
+	}
+}
+
+
+- (void) clientDidFailConnectionAttempt: (id <BXConnectionMonitorClient>) connection
+{
+	@synchronized ((id) mConnections)
+	{
+		CFDictionaryRemoveValue (mConnections, connection);
+	}
+}
+
+
+- (void) clientDidConnect: (id <BXConnectionMonitorClient>) connection
+{
+	int socket = [connection socketForConnectionMonitor: self];
+	BXSocketReachabilityObserver *observer = [BXSocketReachabilityObserver copyObserverWithSocket: socket];
+	
+	if (observer)
+	{
+		[observer setDelegate: self];
+		[observer setUserInfo: connection];
+		
+		[self performSelector: @selector (_scheduleObserver:) 
+					 onThread: mMonitorThread
+				   withObject: observer
+				waitUntilDone: NO];
+		
+		@synchronized ((id) mConnections)
+		{
+			CFDictionarySetValue (mConnections, connection, observer);
+		}
+		
+		[observer release];
+	}
+}
+
+
+- (void) clientWillDisconnect: (id <BXConnectionMonitorClient>) connection
+{
+	BXSocketReachabilityObserver *observer = nil;
+	@synchronized ((id) mConnections)
+	{
+		observer = (id) CFDictionaryGetValue (mConnections, connection);
+		[observer retain];
+		CFDictionaryRemoveValue (mConnections, connection);
+	}
+	
+	if ((id) kCFNull != observer)
+		[observer invalidate];
+	
+	[observer release];
+}
+@end
+
+
+
+@implementation BXConnectionMonitor (BXSocketReachabilityObserverDelegate)
+- (void) socketReachabilityObserver: (BXSocketReachabilityObserver *) observer 
+			   networkStatusChanged: (SCNetworkConnectionFlags) flags
+{
+	[(id <BXConnectionMonitorClient>) [observer userInfo] connectionMonitor: self networkStatusChanged: flags];
+}
+@end

Sources/BXDataModelCompiler.m

 #import "BXArraySize.h"
 
 
+
 @implementation BXDataModelCompiler
 + (NSString *) momcPath
 {
 	return momcPath;
 }
 
+
 - (void) dealloc
 {
 	[mModelURL release];
 	[super dealloc];
 }
 
+
 - (void) setDelegate: (id <BXDataModelCompilerDelegate>) anObject
 {
 	mDelegate = anObject;
 }
 
+
 - (void) setModelURL: (NSURL *) aFileURL
 {
 	if (mModelURL != aFileURL)
 	}
 }
 
+
 - (void) setCompiledModelURL: (NSURL *) aFileURL
 {
 	if (mCompiledModelURL != aFileURL)
 	}
 }
 
+
 - (NSURL *) compiledModelURL
 {
 	return mCompiledModelURL;
 }
 
+
+- (void) waitForCompletion
+{
+	[mMomcTask waitUntilExit];
+}
+
+
+- (void) momcTaskFinished: (NSNotification *) notification
+{
+	[mDelegate dataModelCompiler: self finished: [mMomcTask terminationStatus] errorOutput: [mErrorPipe fileHandleForReading]];
+	
+	[[NSNotificationCenter defaultCenter] removeObserver: self];
+	[mMomcTask release];
+	mMomcTask = nil;
+	[mErrorPipe release];
+	mErrorPipe = nil;
+}
+
+
 - (void) compileDataModel
 {	
 	NSString* sourcePath = [mModelURL path];
 	if (pathFormat)
 		free (pathFormat);
 }
-
-- (void) waitForCompletion
-{
-	[mMomcTask waitUntilExit];
-}
-
-- (void) momcTaskFinished: (NSNotification *) notification
-{
-	[mDelegate dataModelCompiler: self finished: [mMomcTask terminationStatus] errorOutput: [mErrorPipe fileHandleForReading]];
-	
-	[[NSNotificationCenter defaultCenter] removeObserver: self];
-	[mMomcTask release];
-	mMomcTask = nil;
-	[mErrorPipe release];
-	mErrorPipe = nil;
-}
 @end

Sources/BXDatabaseContext.m

 				}
 				else
 				{
-					BXAssertValueReturn ([currentKey isKindOfClass: [BXPropertyDescription class]],
+					BXAssertValueReturn ([currentKey isKindOfClass: [BXPropertyDescription class]], nil,
 										 @"Expected %@ to be either a string or a property description.", currentKey);
 				}
 				

Sources/BXDatabaseContextDelegateDefaultImplementation.m

 // $Id$
 //
 
-#if (TARGET_OS_MAC)
-#import <AppKit/AppKit.h>
-#endif
-
 #import "BXDatabaseContext.h"
 #import "BXDatabaseContextDelegateDefaultImplementation.h"
 #import "BXException.h"
 #import "BXLogger.h"
 
+#if (TARGET_OS_MAC)
+#import <AppKit/AppKit.h>
+#endif
+id NSApp WEAK_IMPORT_ATTRIBUTE;
+
+
 
 @implementation BXDatabaseContextDelegateDefaultImplementation
 - (void) databaseContext: (BXDatabaseContext *) context 

Sources/BXDatabaseObject.m

 	{
 		enum BXDatabaseObjectKeyType keyType = [self keyType: aKey];
 		BXAssertLog (kBXDatabaseObjectUnknownKey != keyType, 
-					 @"Key %@ wasn't found in entity %@. (Called from an instance of %@.)", 
-					 aKey, [self entity], [self class]);
+					 @"Key '%@' wasn't found in entity '%@'. (Called from an instance of %@.)", 
+					 aKey, [[self entity] entityURI], [self class]);
 		switch (keyType)
 		{
 			case kBXDatabaseObjectPrimaryKey:

Sources/BXDelegateProxy.m

 #import "BXDelegateProxy.h"
 
 
+
+/** 
+ * \internal
+ * \brief A delegate proxy for cases where a default implementation is needed.
+ *
+ * \note This class should be thread safe after it has been instantiated
+ *       as it only uses NSProxy's methods that are expected to be thread safe.
+ * \ingroup basetenutility
+ */
 @implementation BXDelegateProxy
+/**
+ * \brief Create the proxy.
+ * \param anObject The object that contains the default implementations.
+ * \note  This method is not thread safe.
+ */
 - (id) initWithDelegateDefaultImplementation: (id) anObject
 {
 	mDelegateDefaultImplementation = [anObject retain];
 	return self;
 }
 
+
 - (void) dealloc
 {
 	[mDelegateDefaultImplementation release];
 	[super dealloc];
 }
 
+
+/**
+ * \brief Set the partial delegate.
+ * \param anObject The object that contains the primary implementations.
+ * \note  This method is not thread safe.
+ */
 - (void) setDelegateForBXDelegateProxy: (id) anObject
 {
 	mDelegate = anObject;
 }
 
+
 - (NSMethodSignature *) methodSignatureForSelector: (SEL) aSelector
 {
 	NSMethodSignature* retval = [mDelegate methodSignatureForSelector: aSelector];
 	return retval;
 }
 
+
 - (void) forwardInvocation: (NSInvocation *) invocation
 {
 	SEL selector = [invocation selector];

Sources/BXDispatchSocketDescriptor.h

+//
+// BXDispatchSocketDescriptor.h
+// BaseTen
+//
+// Copyright (C) 2010 Marko Karppinen & Co. LLC.
+//
+// Before using this software, please review the available licensing options
+// by visiting http://www.karppinen.fi/baseten/licensing/ or by contacting
+// us at sales@karppinen.fi. Without an additional license, this software
+// may be distributed only in compliance with the GNU General Public License.
+//
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License, version 2.0,
+// as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// $Id$
+//
+
+#import <BaseTen/BXSocketDescriptor.h>
+
+
+@interface BXDispatchSocketDescriptor : BXSocketDescriptor
+{
+	dispatch_queue_t mQueue;
+	dispatch_source_t mSocketSource;
+	int mSocket;
+}
+@end

Sources/BXDispatchSocketDescriptor.m

+//
+// BXDispatchSocketDescriptor.m
+// BaseTen
+//
+// Copyright (C) 2010 Marko Karppinen & Co. LLC.
+//
+// Before using this software, please review the available licensing options
+// by visiting http://www.karppinen.fi/baseten/licensing/ or by contacting
+// us at sales@karppinen.fi. Without an additional license, this software
+// may be distributed only in compliance with the GNU General Public License.
+//
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License, version 2.0,
+// as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// $Id$
+//
+
+#import "BXDispatchSocketDescriptor.h"
+#import <libkern/OSAtomic.h>
+
+
+@implementation BXDispatchSocketDescriptor
++ (int32_t) nextQueueIndex
+{
+    // No barrier needed since we are only incrementing a counter.
+	static volatile int32_t idx = 0;
+	return OSAtomicIncrement32 (&idx);
+}
+
+
+- (id) initWithSocket: (int) socket
+{
+	if ((self = [super init]))
+	{
+		mSocket = socket;
+	}
+	return self;
+}
+
+
+- (void) dealloc
+{
+	[self invalidate];
+	[super dealloc];
+}
+
+
+- (void) install
+{
+	NSString *delegateClassName = [[mDelegate class] description];
+	
+	char *identifier = NULL;
+	asprintf (&identifier, "org.basetenframework.BXDispatchSocketDescriptor.%d.%s", 
+			  [[self class] nextQueueIndex], [delegateClassName UTF8String]);
+	if (identifier)
+	{
+		mQueue = dispatch_queue_create (identifier, NULL);
+		mSocketSource = dispatch_source_create (DISPATCH_SOURCE_TYPE_READ, mSocket, 0, mQueue);
+		
+		dispatch_source_set_event_handler (mSocketSource, ^{
+			unsigned long estimated = dispatch_source_get_data (mSocketSource);			
+			[mDelegate socketReadyForReading: mSocket estimatedSize: estimated];
+		});
+		
+		// No cancellation handler because libpq manages the socket.
+		
+		dispatch_resume (mSocketSource);
+		free (identifier);
+	}
+	
+	[delegateClassName self];	
+}
+
+
+- (void) lock: (id) userInfo
+{
+	[userInfo retain];
+	dispatch_async (mQueue, ^{
+		[mDelegate socketLocked: mSocket userInfo: userInfo];
+		[userInfo release];
+	});
+}
+
+
+- (void) lockAndWait: (id) userInfo
+{
+	if ([self isLocked])
+		[mDelegate socketLocked: mSocket userInfo: userInfo];
+	else
+	{
+		dispatch_sync (mQueue, ^{
+			[mDelegate socketLocked: mSocket userInfo: userInfo];
+		});
+	}
+}
+
+
+- (BOOL) isLocked
+{
+	return dispatch_get_current_queue () == mQueue;
+}
+
+
+- (void) invalidate
+{
+	if (mSocketSource)
+	{
+		dispatch_source_cancel (mSocketSource);
+		dispatch_release (mSocketSource);
+		mSocketSource = NULL;
+	}
+	
+	if (mQueue)
+	{
+		dispatch_release (mQueue);
+		mQueue = NULL;
+	}
+}
+@end

Sources/BXEntityDescription.h

 }
 
 - (NSURL *) databaseURI;
+- (NSURL *) entityURI;
 - (NSString *) schemaName;
 - (BOOL) isEqual: (BXEntityDescription *) desc;
 - (NSUInteger) hash;

Sources/BXEntityDescription.m

     return [[mDatabaseURI retain] autorelease];
 }
 
+
+- (NSURL *) entityURI
+{
+	NSURL *URI = [NSURL URLWithString: [NSString stringWithFormat: @"/%@/%@", mSchemaName, mName] 
+						relativeToURL: [self databaseURI]];
+	return [URI absoluteURL];
+}
+
+
 - (id) initWithCoder: (NSCoder *) decoder
 {
     NSString* name = [decoder decodeObjectForKey: @"name"];

Sources/BXException.m

 {
     NSMutableDictionary* userInfo = [NSMutableDictionary dictionaryWithDictionary: [self userInfo]];
     [userInfo setObject: self forKey: kBXErrorKey];
+	userInfo = [[userInfo copy] autorelease];
     return [BXException exceptionWithName: name 
 								   reason: [self localizedFailureReason]
 								 userInfo: userInfo];

Sources/BXHostResolver.m

 
 
 
-@interface BXHostResolver (PrivateMethods)
-- (void) setNodeName: (NSString *) nodeName;
-- (void) setAddresses: (NSArray *) addresses;
+@interface BXHostResolver ()
+- (void) _setNodeName: (NSString *) nodeName;
+- (void) _setAddresses: (NSArray *) addresses;
 
-- (NSError *) errorForStreamError: (const CFStreamError *) streamError;
+- (NSError *) _errorForStreamError: (const CFStreamError *) streamError;
 
-- (void) reachabilityCheckDidComplete: (SCNetworkConnectionFlags) flags;
-- (void) hostCheckDidComplete: (const CFStreamError *) streamError;
+- (void) _reachabilityCheckDidComplete: (SCNetworkConnectionFlags) flags;
+- (void) _hostCheckDidComplete: (const CFStreamError *) streamError;
 
-- (void) removeReachability;
-- (void) removeHost;
+- (void) _removeReachability;
+- (void) _removeHost;
 @end
 
 
 static void
 ReachabilityCallback (SCNetworkReachabilityRef target, SCNetworkConnectionFlags flags, void *info)
 {
-	[(id) info reachabilityCheckDidComplete: flags];
+	[(id) info _reachabilityCheckDidComplete: flags];
 }
 
 
 static void 
 HostCallback (CFHostRef theHost, CFHostInfoType typeInfo, const CFStreamError *error, void *info)
 {
-	[(id) info hostCheckDidComplete: error];
+	[(id) info _hostCheckDidComplete: error];
 }
 
 
 
+/**
+ * \internal
+ * \brief A façade for CFHost that also tests reachability.
+ * \note Instances of this class can safely be used from only one thread at a time.
+ */
 @implementation BXHostResolver
-+ (BOOL) getAddrinfo: (struct addrinfo **) outAddrinfo forIPAddress: (NSString *) host
+/**
+ * \brief Test whether a given address is numeric.
+ * \note This method is thread safe.
+ */
++ (BOOL) getAddrinfo: (struct addrinfo **) outAddrinfo forIPAddress: (NSString *) node
 {
 	ExpectR (outAddrinfo, NO);
-	ExpectR (0 < [host length], NO);
+	ExpectR (0 < [node length], NO);
 	
 	struct addrinfo hints = {
 		AI_NUMERICHOST,
 		NULL,
 		NULL
 	};
-	int status = getaddrinfo ([host UTF8String], NULL, &hints, outAddrinfo);
+	int status = getaddrinfo ([node UTF8String], NULL, &hints, outAddrinfo);
+	[node self]; //For GC
 	return (0 == status ? YES : NO);
 }
 
 
 - (void) dealloc
 {	
-	[self removeReachability];
-	[self removeHost];
+	[self _removeReachability];
+	[self _removeHost];
 	
 	if (mRunLoop)
 		CFRelease (mRunLoop);
 
 - (void) finalize
 {
-	[self removeReachability];
-	[self removeHost];
+	[self _removeReachability];
+	[self _removeHost];
 
 	if (mRunLoop)
 		CFRelease (mRunLoop);
 
 - (void) cancelResolution
 {
-	[self removeReachability];
-	[self removeHost];
+	[self _removeReachability];
+	[self _removeHost];
 }
 
 
-- (void) removeReachability
+- (void) _removeReachability
 {
 	if (mReachability)
 	{
 }
 
 
-- (void) removeHost
+- (void) _removeHost
 {
 	if (mHost)
 	{
 }
 
 
+/**
+ * \brief Resolve the given host.
+ */
 - (void) resolveHost: (NSString *) host
 {	
 	ExpectV (mRunLoop);
 	ExpectV (host);
 	ExpectV ([host characterAtIndex: 0] != '/');	
 	
-	[self removeReachability];
-	[self removeHost];
+	[self _removeReachability];
+	[self _removeHost];
 	bzero (&mHostError, sizeof (mHostError));
 
-	[self setNodeName: host];
+	[self _setNodeName: host];
 	SCNetworkReachabilityContext ctx = {
 		0,
 		self,
 	if ([[self class] getAddrinfo: &addrinfo forIPAddress: host])
 	{
 		NSArray *addresses = CopySockaddrArrayFromAddrinfo (addrinfo);
-		[self setAddresses: addresses];
+		[self _setAddresses: addresses];
 		[addresses release];
 		
 		mReachability = SCNetworkReachabilityCreateWithAddress (kCFAllocatorDefault, addrinfo->ai_addr);
 		status = SCNetworkReachabilityGetFlags (mReachability, &flags);
 		ExpectL (status)
 		
-		[self reachabilityCheckDidComplete: flags];
+		[self _reachabilityCheckDidComplete: flags];
 	}
 	else
 	{
 }
 
 
-- (void) reachabilityCheckDidComplete: (SCNetworkConnectionFlags) actual
+- (void) _reachabilityCheckDidComplete: (SCNetworkConnectionFlags) actual
 {
 	// We use the old type name, since the new one only appeared in 10.6.
 	
-	[self removeReachability];
+	[self _removeReachability];
 	bzero (&mHostError, sizeof (mHostError));
 	
 	if (mAddresses)
 			// doesn't provide us with good error messages, we settle with a generic one.
 			if (NULL != &kCFStreamErrorDomainSystemConfiguration)
 				mHostError.domain = kCFStreamErrorDomainSystemConfiguration;
-			[mDelegate hostResolverDidFail: self error: [self errorForStreamError: &mHostError]];
+			[mDelegate hostResolverDidFail: self error: [self _errorForStreamError: &mHostError]];
 		}
 	}
 	else
 		CFHostScheduleWithRunLoop (mHost, mRunLoop, (CFStringRef) mRunLoopMode);
 		
 		if (! CFHostStartInfoResolution (mHost, kCFHostAddresses, &mHostError))
-			[self hostCheckDidComplete: &mHostError];
+			[self _hostCheckDidComplete: &mHostError];
 	}
 }
 
 
-- (void) hostCheckDidComplete: (const CFStreamError *) streamError
+- (void) _hostCheckDidComplete: (const CFStreamError *) streamError
 {	
 	if (streamError && streamError->domain)
 	{
-		NSError *error = [self errorForStreamError: streamError];
+		NSError *error = [self _errorForStreamError: streamError];
 		[mDelegate hostResolverDidFail: self error: error];
 	}
 	else
 		[mDelegate hostResolverDidSucceed: self addresses: (id) CFHostGetAddressing (mHost, &status)];
 	}
 	
-	[self removeHost];
+	[self _removeHost];
 }
 
 
-- (NSError *) errorForStreamError: (const CFStreamError *) streamError
+- (NSError *) _errorForStreamError: (const CFStreamError *) streamError
 {
-	// In case the domain field hasn't been set, return a generic error.
 	NSError* retval = nil;
 	if (streamError)
 	{
 		}
 		else
 		{
+			// In case the domain field hasn't been set, return a generic error.
 			messageFormat = @"The server %@ wasn't found.";
 		}
 		NSString* message = [NSString stringWithFormat: messageFormat, mNodeName, reason];
 	}
 	return retval;
 }
-@end
 
 
-
-@implementation BXHostResolver (Accessors)
-- (void) setNodeName: (NSString *) nodeName
+- (void) _setNodeName: (NSString *) nodeName
 {
 	if (nodeName != mNodeName)
 	{
 }
 
 
-- (void) setAddresses: (NSArray *) addresses
+- (void) _setAddresses: (NSArray *) addresses
 {
 	if (addresses != mAddresses)
 	{
 		mAddresses = [addresses retain];
 	}
 }
+@end
 
 
+
+@implementation BXHostResolver (Accessors)
 - (NSString *) runLoopMode;
 {
 	return mRunLoopMode;
 {
 	if (mode != mRunLoopMode)
 	{
-		[self removeHost];
+		[self _removeHost];
 		
 		[mRunLoopMode release];
 		mRunLoopMode = [mode retain];
 {
 	if (runLoop != mRunLoop)
 	{
-		[self removeHost];
+		[self _removeHost];
 		
 		if (mRunLoop)
 			CFRelease (mRunLoop);

Sources/BXIOKitSystemEventNotifier.h

+//
+// BXIOKitSystemEventNotifier.h
+// BaseTen
+//
+// Copyright (C) 2010 Marko Karppinen & Co. LLC.
+//
+// Before using this software, please review the available licensing options
+// by visiting http://www.karppinen.fi/baseten/licensing/ or by contacting
+// us at sales@karppinen.fi. Without an additional license, this software
+// may be distributed only in compliance with the GNU General Public License.
+//
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License, version 2.0,
+// as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// $Id$
+//
+
+#import <BaseTen/BXSystemEventNotifier.h>
+#import <IOKit/pwr_mgt/IOPMLib.h>
+#import <IOKit/IOMessage.h>
+
+
+@interface BXIOKitSystemEventNotifier : BXSystemEventNotifier
+{
+	CFRunLoopRef mRunLoop;
+	CFRunLoopSourceRef mRunLoopSource;
+	IONotificationPortRef mIONotificationPort;
+	io_object_t mIONotifier;
+	io_connect_t mIOPowerSession;
+}
+- (void) invalidate;
+- (io_connect_t) IOPowerSession;
+@end

Sources/BXIOKitSystemEventNotifier.m

+//
+// BXIOKitSystemEventNotifier.m
+// BaseTen
+//
+// Copyright (C) 2008-2010 Marko Karppinen & Co. LLC.
+//
+// Before using this software, please review the available licensing options
+// by visiting http://www.karppinen.fi/baseten/licensing/ or by contacting
+// us at sales@karppinen.fi. Without an additional license, this software
+// may be distributed only in compliance with the GNU General Public License.
+//
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License, version 2.0,
+// as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// $Id$
+//
+
+#import "BXIOKitSystemEventNotifier.h"
+#import "BXLogger.h"
+
+
+static CFMutableSetRef stInstances = NULL;
+
+
+static void
+DispatchProcessWillExit (const void *notifierPtr, void *ctx)
+{
+	[(id) notifierPtr processWillExit];
+}
+
+
+static void
+ProcessWillExit ()
+{
+	@synchronized ([BXIOKitSystemEventNotifier class])
+	{
+		CFSetApplyFunction (stInstances, &DispatchProcessWillExit, NULL);
+		CFRelease (stInstances);
+	}
+}
+
+
+static void
+WorkspaceWillSleep (void *refCon, io_service_t service, natural_t messageType, void *messageArgument)
+{
+	
+	BXIOKitSystemEventNotifier *notifier = (id) refCon;
+    switch (messageType)
+    {
+        case kIOMessageCanSystemSleep:
+        case kIOMessageSystemWillSleep:
+		{
+			[notifier systemWillSleep];
+            IOAllowPowerChange ([notifier IOPowerSession], (long) messageArgument);
+            break;
+		}
+			
+		case kIOMessageSystemHasPoweredOn:
+		{
+			[notifier systemDidWake];
+			break;
+		}
+			
+        default:
+            break;
+    }
+
+}
+
+
+@implementation BXIOKitSystemEventNotifier
+- (void) _setRunLoopSource: (CFRunLoopSourceRef) source 
+					  port: (IONotificationPortRef) port
+				  notifier: (io_object_t) notifier
+				   session: (io_connect_t) session
+{
+	mRunLoopSource = source;
+	CFRetain (source);
+	
+	mIONotificationPort = port;
+	mIONotifier = notifier;
+	mIOPowerSession = session;	
+}
+
+
+- (id) _init
+{
+	if ((self = [super init]))
+	{
+	}
+	return self;
+}
+
+
+- (id) init
+{
+	[self doesNotRecognizeSelector: _cmd];
+	return nil;
+}
+
+
++ (id) copyNotifier
+{
+	id retval = [[self alloc] _init];
+	
+	io_object_t ioNotifier = 0;
+	IONotificationPortRef ioNotificationPort = NULL;
+	io_connect_t ioPowerSession = IORegisterForSystemPower (retval, &ioNotificationPort, &WorkspaceWillSleep, &ioNotifier);
+	if (MACH_PORT_NULL == ioPowerSession)
+		goto bail;
+	
+	CFRunLoopSourceRef source = IONotificationPortGetRunLoopSource (ioNotificationPort);
+	if (! source)
+		goto bail;
+	
+	[retval _setRunLoopSource: source port: ioNotificationPort notifier: ioNotifier session: ioPowerSession];
+	return retval;
+	
+bail:
+	[retval release];
+	return nil;
+}
+
+
+- (void) install
+{
+	ExpectV (! mRunLoop);
+	ExpectV (mRunLoopSource);
+	ExpectV (MACH_PORT_NULL != mIOPowerSession);
+	
+	mRunLoop = CFRunLoopGetCurrent ();
+	CFRetain (mRunLoop);
+	
+	CFRunLoopAddSource (mRunLoop, mRunLoopSource, kCFRunLoopCommonModes);
+	
+	@synchronized ([self class])
+	{
+		static BOOL tooLate = NO;
+		if (! tooLate)
+		{
+			tooLate = YES;
+			
+			CFSetCallBacks callbacks = {
+				0,
+				NULL,
+				NULL,
+				NULL,
+				NULL,
+				NULL
+			};
+			stInstances = CFSetCreateMutable (kCFAllocatorDefault, 0, &callbacks);
+			
+			atexit (&ProcessWillExit);
+		}
+		CFSetAddValue (stInstances, self);
+	}	
+}
+
+
+- (void) invalidate
+{
+	@synchronized ([self class])
+	{
+		CFSetRemoveValue (stInstances, self);
+	}
+	
+	if (mRunLoop && mRunLoopSource)
+		CFRunLoopRemoveSource (mRunLoop, mRunLoopSource, kCFRunLoopCommonModes);
+	
+	if (mRunLoopSource)
+	{
+		CFRelease (mRunLoopSource);
+		mRunLoopSource = NULL;
+	}
+	
+	if (mRunLoop)
+	{
+		CFRelease (mRunLoop);
+		mRunLoop = NULL;
+	}
+	
+	if (MACH_PORT_NULL != mIOPowerSession)
+	{
+		IODeregisterForSystemPower (&mIONotifier);
+		IONotificationPortDestroy (mIONotificationPort);
+		mIOPowerSession = MACH_PORT_NULL;
+	}
+}
+
+
+- (io_connect_t) IOPowerSession
+{
+	return mIOPowerSession;
+}
+
+
+- (void) dealloc
+{	
+	[self invalidate];
+	[super dealloc];
+}
+
+
+- (void) finalize
+{
+	[self invalidate];
+	[super finalize];
+}
+@end

Sources/BXKeyPathParser.m

 
 /**
  * \internal
- * A parser for key paths.
+ * \brief A parser for key paths.
  * Accepts some malformed key paths but NSPredicate and other classes probably notice them, when
  * they get re-used.
+ * \not This function is thread safe.
  */
 NSArray* 
 BXKeyPathComponents (NSString* keyPath)
 	
 	if (! [retval count])
 		retval = nil;
-	return retval;
+	return [[retval copy] autorelease];