diff --git a/.gitignore b/.gitignore index e944e9f..e777a46 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # Xcode Add Xcode project to allow Carthage. #*.xcodeproj #*.xcworkspace +Concurrency.xcodeproj/xcshareddata/xcschemes/Concurrency-Package.xcscheme ## Build generated build/ @@ -35,3 +36,4 @@ Packages/ Package.pins Package.resolved .build/ +.DS_Store diff --git a/.travis.yml b/.travis.yml index c1b3470..d600172 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,10 @@ language: objective-c -osx_image: xcode9 +osx_image: xcode11.2 env: - ACTION=test PLATFORM=Mac DESTINATION='platform=OS X' - - ACTION=test PLATFORM=iOS DESTINATION='platform=iOS Simulator,name=iPhone 7' - - ACTION=test PLATFORM=tvOS DESTINATION='platform=tvOS Simulator,name=Apple TV 1080p' + - ACTION=test PLATFORM=iOS DESTINATION='platform=iOS Simulator,name=iPhone XS' + - ACTION=test PLATFORM=tvOS DESTINATION='platform=tvOS Simulator,name=Apple TV 4K' script: - swift test diff --git a/Concurrency.xcodeproj/GeneratedModuleMap/ObjCBridges/module.modulemap b/Concurrency.xcodeproj/GeneratedModuleMap/ObjCBridges/module.modulemap new file mode 100644 index 0000000..b341525 --- /dev/null +++ b/Concurrency.xcodeproj/GeneratedModuleMap/ObjCBridges/module.modulemap @@ -0,0 +1,4 @@ +module ObjCBridges { + umbrella "/Users/yiw/Uber/GitHub/swift-concurrency/Sources/ObjCBridges/include" + export * +} diff --git a/Concurrency.xcodeproj/ObjCBridges_Info.plist b/Concurrency.xcodeproj/ObjCBridges_Info.plist new file mode 100644 index 0000000..57ada9f --- /dev/null +++ b/Concurrency.xcodeproj/ObjCBridges_Info.plist @@ -0,0 +1,25 @@ + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/Concurrency.xcodeproj/project.pbxproj b/Concurrency.xcodeproj/project.pbxproj index 793f5e2..b1c01df 100644 --- a/Concurrency.xcodeproj/project.pbxproj +++ b/Concurrency.xcodeproj/project.pbxproj @@ -1,416 +1,952 @@ // !$*UTF8*$! { - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 41B94843210A4744007E59C8 /* SerialSequenceExecutor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41B9483F210A4744007E59C8 /* SerialSequenceExecutor.swift */; }; - 41B94844210A4744007E59C8 /* SequenceExecutor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41B94840210A4744007E59C8 /* SequenceExecutor.swift */; }; - 41B94845210A4744007E59C8 /* ConcurrentSequenceExecutor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41B94841210A4744007E59C8 /* ConcurrentSequenceExecutor.swift */; }; - 41B94846210A4744007E59C8 /* Task.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41B94842210A4744007E59C8 /* Task.swift */; }; - 41B94849210A4756007E59C8 /* ConcurrentSequenceExecutorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41B94848210A4756007E59C8 /* ConcurrentSequenceExecutorTests.swift */; }; - OBJ_27 /* AtomicBool.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_9 /* AtomicBool.swift */; }; - OBJ_28 /* AtomicInt.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_10 /* AtomicInt.swift */; }; - OBJ_29 /* AtomicReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_11 /* AtomicReference.swift */; }; - OBJ_30 /* CountDownLatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_12 /* CountDownLatch.swift */; }; - OBJ_48 /* AtomicBoolTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_15 /* AtomicBoolTests.swift */; }; - OBJ_49 /* AtomicIntTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_16 /* AtomicIntTests.swift */; }; - OBJ_50 /* AtomicReferenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_17 /* AtomicReferenceTests.swift */; }; - OBJ_51 /* CountDownLatchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_18 /* CountDownLatchTests.swift */; }; - OBJ_53 /* Concurrency.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "Concurrency::Concurrency::Product" /* Concurrency.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 412CDD2D20B88EAB00AF5890 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = OBJ_1 /* Project object */; - proxyType = 1; - remoteGlobalIDString = "Concurrency::Concurrency"; - remoteInfo = Concurrency; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 41B9483F210A4744007E59C8 /* SerialSequenceExecutor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SerialSequenceExecutor.swift; sourceTree = ""; }; - 41B94840210A4744007E59C8 /* SequenceExecutor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SequenceExecutor.swift; sourceTree = ""; }; - 41B94841210A4744007E59C8 /* ConcurrentSequenceExecutor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConcurrentSequenceExecutor.swift; sourceTree = ""; }; - 41B94842210A4744007E59C8 /* Task.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Task.swift; sourceTree = ""; }; - 41B94848210A4756007E59C8 /* ConcurrentSequenceExecutorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConcurrentSequenceExecutorTests.swift; sourceTree = ""; }; - "Concurrency::Concurrency::Product" /* Concurrency.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Concurrency.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - "Concurrency::ConcurrencyTests::Product" /* ConcurrencyTests.xctest */ = {isa = PBXFileReference; lastKnownFileType = file; path = ConcurrencyTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - OBJ_10 /* AtomicInt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AtomicInt.swift; sourceTree = ""; }; - OBJ_11 /* AtomicReference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AtomicReference.swift; sourceTree = ""; }; - OBJ_12 /* CountDownLatch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CountDownLatch.swift; sourceTree = ""; }; - OBJ_15 /* AtomicBoolTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AtomicBoolTests.swift; sourceTree = ""; }; - OBJ_16 /* AtomicIntTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AtomicIntTests.swift; sourceTree = ""; }; - OBJ_17 /* AtomicReferenceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AtomicReferenceTests.swift; sourceTree = ""; }; - OBJ_18 /* CountDownLatchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CountDownLatchTests.swift; sourceTree = ""; }; - OBJ_6 /* Package.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; - OBJ_9 /* AtomicBool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AtomicBool.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - OBJ_31 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - OBJ_52 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 0; - files = ( - OBJ_53 /* Concurrency.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 41B9483E210A4744007E59C8 /* Executor */ = { - isa = PBXGroup; - children = ( - 41B9483F210A4744007E59C8 /* SerialSequenceExecutor.swift */, - 41B94840210A4744007E59C8 /* SequenceExecutor.swift */, - 41B94841210A4744007E59C8 /* ConcurrentSequenceExecutor.swift */, - 41B94842210A4744007E59C8 /* Task.swift */, - ); - path = Executor; - sourceTree = ""; - }; - 41B94847210A4756007E59C8 /* Executor */ = { - isa = PBXGroup; - children = ( - 41B94848210A4756007E59C8 /* ConcurrentSequenceExecutorTests.swift */, - ); - path = Executor; - sourceTree = ""; - }; - OBJ_13 /* Tests */ = { - isa = PBXGroup; - children = ( - OBJ_14 /* ConcurrencyTests */, - ); - name = Tests; - sourceTree = SOURCE_ROOT; - }; - OBJ_14 /* ConcurrencyTests */ = { - isa = PBXGroup; - children = ( - 41B94847210A4756007E59C8 /* Executor */, - OBJ_15 /* AtomicBoolTests.swift */, - OBJ_16 /* AtomicIntTests.swift */, - OBJ_17 /* AtomicReferenceTests.swift */, - OBJ_18 /* CountDownLatchTests.swift */, - ); - name = ConcurrencyTests; - path = Tests/ConcurrencyTests; - sourceTree = SOURCE_ROOT; - }; - OBJ_19 /* Products */ = { - isa = PBXGroup; - children = ( - "Concurrency::ConcurrencyTests::Product" /* ConcurrencyTests.xctest */, - "Concurrency::Concurrency::Product" /* Concurrency.framework */, - ); - name = Products; - sourceTree = BUILT_PRODUCTS_DIR; - }; - OBJ_5 = { - isa = PBXGroup; - children = ( - OBJ_6 /* Package.swift */, - OBJ_7 /* Sources */, - OBJ_13 /* Tests */, - OBJ_19 /* Products */, - ); - sourceTree = ""; - }; - OBJ_7 /* Sources */ = { - isa = PBXGroup; - children = ( - OBJ_8 /* Concurrency */, - ); - name = Sources; - sourceTree = SOURCE_ROOT; - }; - OBJ_8 /* Concurrency */ = { - isa = PBXGroup; - children = ( - 41B9483E210A4744007E59C8 /* Executor */, - OBJ_9 /* AtomicBool.swift */, - OBJ_10 /* AtomicInt.swift */, - OBJ_11 /* AtomicReference.swift */, - OBJ_12 /* CountDownLatch.swift */, - ); - name = Concurrency; - path = Sources/Concurrency; - sourceTree = SOURCE_ROOT; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - "Concurrency::Concurrency" /* Concurrency */ = { - isa = PBXNativeTarget; - buildConfigurationList = OBJ_23 /* Build configuration list for PBXNativeTarget "Concurrency" */; - buildPhases = ( - OBJ_26 /* Sources */, - OBJ_31 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Concurrency; - productName = Concurrency; - productReference = "Concurrency::Concurrency::Product" /* Concurrency.framework */; - productType = "com.apple.product-type.framework"; - }; - "Concurrency::ConcurrencyTests" /* ConcurrencyTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = OBJ_44 /* Build configuration list for PBXNativeTarget "ConcurrencyTests" */; - buildPhases = ( - OBJ_47 /* Sources */, - OBJ_52 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - OBJ_54 /* PBXTargetDependency */, - ); - name = ConcurrencyTests; - productName = ConcurrencyTests; - productReference = "Concurrency::ConcurrencyTests::Product" /* ConcurrencyTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - OBJ_1 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 9999; - }; - buildConfigurationList = OBJ_2 /* Build configuration list for PBXProject "Concurrency" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = OBJ_5; - productRefGroup = OBJ_19 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - "Concurrency::Concurrency" /* Concurrency */, - "Concurrency::ConcurrencyTests" /* ConcurrencyTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - OBJ_26 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 0; - files = ( - 41B94846210A4744007E59C8 /* Task.swift in Sources */, - OBJ_27 /* AtomicBool.swift in Sources */, - 41B94844210A4744007E59C8 /* SequenceExecutor.swift in Sources */, - 41B94845210A4744007E59C8 /* ConcurrentSequenceExecutor.swift in Sources */, - OBJ_28 /* AtomicInt.swift in Sources */, - OBJ_29 /* AtomicReference.swift in Sources */, - 41B94843210A4744007E59C8 /* SerialSequenceExecutor.swift in Sources */, - OBJ_30 /* CountDownLatch.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - OBJ_47 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 0; - files = ( - OBJ_48 /* AtomicBoolTests.swift in Sources */, - OBJ_49 /* AtomicIntTests.swift in Sources */, - 41B94849210A4756007E59C8 /* ConcurrentSequenceExecutorTests.swift in Sources */, - OBJ_50 /* AtomicReferenceTests.swift in Sources */, - OBJ_51 /* CountDownLatchTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - OBJ_54 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = "Concurrency::Concurrency" /* Concurrency */; - targetProxy = 412CDD2D20B88EAB00AF5890 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - OBJ_24 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PLATFORM_DIR)/Developer/Library/Frameworks", - ); - HEADER_SEARCH_PATHS = "$(inherited)"; - INFOPLIST_FILE = Concurrency.xcodeproj/Concurrency_Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; - OTHER_CFLAGS = "$(inherited)"; - OTHER_LDFLAGS = "$(inherited)"; - OTHER_SWIFT_FLAGS = "$(inherited)"; - PRODUCT_BUNDLE_IDENTIFIER = Concurrency; - PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SKIP_INSTALL = YES; - SWIFT_VERSION = 4.0; - TARGET_NAME = Concurrency; - }; - name = Debug; - }; - OBJ_25 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PLATFORM_DIR)/Developer/Library/Frameworks", - ); - HEADER_SEARCH_PATHS = "$(inherited)"; - INFOPLIST_FILE = Concurrency.xcodeproj/Concurrency_Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; - OTHER_CFLAGS = "$(inherited)"; - OTHER_LDFLAGS = "$(inherited)"; - OTHER_SWIFT_FLAGS = "$(inherited)"; - PRODUCT_BUNDLE_IDENTIFIER = Concurrency; - PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SKIP_INSTALL = YES; - SWIFT_VERSION = 4.0; - TARGET_NAME = Concurrency; - }; - name = Release; - }; - OBJ_3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ENABLE_OBJC_ARC = YES; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_NS_ASSERTIONS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MACOSX_DEPLOYMENT_TARGET = 10.10; - ONLY_ACTIVE_ARCH = YES; - OTHER_SWIFT_FLAGS = "-DXcode"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx; - SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = SWIFT_PACKAGE; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - USE_HEADERMAP = NO; - }; - name = Debug; - }; - OBJ_4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ENABLE_OBJC_ARC = YES; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_OPTIMIZATION_LEVEL = s; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MACOSX_DEPLOYMENT_TARGET = 10.10; - OTHER_SWIFT_FLAGS = "-DXcode"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx; - SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = SWIFT_PACKAGE; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - USE_HEADERMAP = NO; - }; - name = Release; - }; - OBJ_45 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PLATFORM_DIR)/Developer/Library/Frameworks", - ); - HEADER_SEARCH_PATHS = "$(inherited)"; - INFOPLIST_FILE = Concurrency.xcodeproj/ConcurrencyTests_Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/../Frameworks @loader_path/Frameworks"; - OTHER_CFLAGS = "$(inherited)"; - OTHER_LDFLAGS = "$(inherited)"; - OTHER_SWIFT_FLAGS = "$(inherited)"; - SWIFT_VERSION = 4.0; - TARGET_NAME = ConcurrencyTests; - }; - name = Debug; - }; - OBJ_46 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PLATFORM_DIR)/Developer/Library/Frameworks", - ); - HEADER_SEARCH_PATHS = "$(inherited)"; - INFOPLIST_FILE = Concurrency.xcodeproj/ConcurrencyTests_Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/../Frameworks @loader_path/Frameworks"; - OTHER_CFLAGS = "$(inherited)"; - OTHER_LDFLAGS = "$(inherited)"; - OTHER_SWIFT_FLAGS = "$(inherited)"; - SWIFT_VERSION = 4.0; - TARGET_NAME = ConcurrencyTests; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - OBJ_2 /* Build configuration list for PBXProject "Concurrency" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - OBJ_3 /* Debug */, - OBJ_4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - OBJ_23 /* Build configuration list for PBXNativeTarget "Concurrency" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - OBJ_24 /* Debug */, - OBJ_25 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - OBJ_44 /* Build configuration list for PBXNativeTarget "ConcurrencyTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - OBJ_45 /* Debug */, - OBJ_46 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = OBJ_1 /* Project object */; + archiveVersion = "1"; + objectVersion = "46"; + objects = { + "Concurrency::Concurrency" = { + isa = "PBXNativeTarget"; + buildConfigurationList = "OBJ_47"; + buildPhases = ( + "OBJ_50", + "OBJ_60" + ); + dependencies = ( + "OBJ_62" + ); + name = "Concurrency"; + productName = "Concurrency"; + productReference = "Concurrency::Concurrency::Product"; + productType = "com.apple.product-type.framework"; + }; + "Concurrency::Concurrency::Product" = { + isa = "PBXFileReference"; + path = "Concurrency.framework"; + sourceTree = "BUILT_PRODUCTS_DIR"; + }; + "Concurrency::ConcurrencyPackageTests::ProductTarget" = { + isa = "PBXAggregateTarget"; + buildConfigurationList = "OBJ_71"; + buildPhases = ( + ); + dependencies = ( + "OBJ_74" + ); + name = "ConcurrencyPackageTests"; + productName = "ConcurrencyPackageTests"; + }; + "Concurrency::ConcurrencyTests" = { + isa = "PBXNativeTarget"; + buildConfigurationList = "OBJ_76"; + buildPhases = ( + "OBJ_79", + "OBJ_86" + ); + dependencies = ( + "OBJ_89", + "OBJ_90" + ); + name = "ConcurrencyTests"; + productName = "ConcurrencyTests"; + productReference = "Concurrency::ConcurrencyTests::Product"; + productType = "com.apple.product-type.bundle.unit-test"; + }; + "Concurrency::ConcurrencyTests::Product" = { + isa = "PBXFileReference"; + path = "ConcurrencyTests.xctest"; + sourceTree = "BUILT_PRODUCTS_DIR"; + }; + "Concurrency::ObjCBridges" = { + isa = "PBXNativeTarget"; + buildConfigurationList = "OBJ_91"; + buildPhases = ( + "OBJ_94", + "OBJ_96" + ); + dependencies = ( + ); + name = "ObjCBridges"; + productName = "ObjCBridges"; + productReference = "Concurrency::ObjCBridges::Product"; + productType = "com.apple.product-type.framework"; + }; + "Concurrency::ObjCBridges::Product" = { + isa = "PBXFileReference"; + path = "ObjCBridges.framework"; + sourceTree = "BUILT_PRODUCTS_DIR"; + }; + "Concurrency::SwiftPMPackageDescription" = { + isa = "PBXNativeTarget"; + buildConfigurationList = "OBJ_65"; + buildPhases = ( + "OBJ_68" + ); + dependencies = ( + ); + name = "ConcurrencyPackageDescription"; + productName = "ConcurrencyPackageDescription"; + productType = "com.apple.product-type.framework"; + }; + "OBJ_1" = { + isa = "PBXProject"; + attributes = { + LastSwiftMigration = "9999"; + LastUpgradeCheck = "9999"; + }; + buildConfigurationList = "OBJ_2"; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = "English"; + hasScannedForEncodings = "0"; + knownRegions = ( + "en" + ); + mainGroup = "OBJ_5"; + productRefGroup = "OBJ_36"; + projectDirPath = "."; + targets = ( + "Concurrency::Concurrency", + "Concurrency::SwiftPMPackageDescription", + "Concurrency::ConcurrencyPackageTests::ProductTarget", + "Concurrency::ConcurrencyTests", + "Concurrency::ObjCBridges" + ); + }; + "OBJ_10" = { + isa = "PBXGroup"; + children = ( + "OBJ_11", + "OBJ_12", + "OBJ_13", + "OBJ_14", + "OBJ_15", + "OBJ_16", + "OBJ_17" + ); + name = "Concurrency"; + path = "Sources/Concurrency"; + sourceTree = "SOURCE_ROOT"; + }; + "OBJ_11" = { + isa = "PBXFileReference"; + path = "Concurrency-Bridging-Header.h"; + sourceTree = ""; + }; + "OBJ_12" = { + isa = "PBXFileReference"; + path = "AtomicBool.swift"; + sourceTree = ""; + }; + "OBJ_13" = { + isa = "PBXFileReference"; + path = "AtomicInt.swift"; + sourceTree = ""; + }; + "OBJ_14" = { + isa = "PBXFileReference"; + path = "AtomicReference.swift"; + sourceTree = ""; + }; + "OBJ_15" = { + isa = "PBXFileReference"; + path = "AutoReleasingSemaphore.swift"; + sourceTree = ""; + }; + "OBJ_16" = { + isa = "PBXFileReference"; + path = "CountDownLatch.swift"; + sourceTree = ""; + }; + "OBJ_17" = { + isa = "PBXGroup"; + children = ( + "OBJ_18", + "OBJ_19", + "OBJ_20", + "OBJ_21" + ); + name = "Executor"; + path = "Executor"; + sourceTree = ""; + }; + "OBJ_18" = { + isa = "PBXFileReference"; + path = "ConcurrentSequenceExecutor.swift"; + sourceTree = ""; + }; + "OBJ_19" = { + isa = "PBXFileReference"; + path = "ImmediateSerialSequenceExecutor.swift"; + sourceTree = ""; + }; + "OBJ_2" = { + isa = "XCConfigurationList"; + buildConfigurations = ( + "OBJ_3", + "OBJ_4" + ); + defaultConfigurationIsVisible = "0"; + defaultConfigurationName = "Release"; + }; + "OBJ_20" = { + isa = "PBXFileReference"; + path = "SequenceExecutor.swift"; + sourceTree = ""; + }; + "OBJ_21" = { + isa = "PBXFileReference"; + path = "Task.swift"; + sourceTree = ""; + }; + "OBJ_22" = { + isa = "PBXGroup"; + children = ( + "OBJ_23", + "OBJ_24" + ); + name = "ObjCBridges"; + path = "Sources/ObjCBridges"; + sourceTree = "SOURCE_ROOT"; + }; + "OBJ_23" = { + isa = "PBXFileReference"; + path = "AtomicBridges.m"; + sourceTree = ""; + }; + "OBJ_24" = { + isa = "PBXGroup"; + children = ( + "OBJ_25", + "OBJ_26" + ); + name = "include"; + path = "include"; + sourceTree = ""; + }; + "OBJ_25" = { + isa = "PBXFileReference"; + path = "AtomicBridges.h"; + sourceTree = ""; + }; + "OBJ_26" = { + isa = "PBXFileReference"; + name = "module.modulemap"; + path = "/Users/cameronmcgorian/Documents/dev/swift-concurrency/Concurrency.xcodeproj/GeneratedModuleMap/ObjCBridges/module.modulemap"; + sourceTree = ""; + }; + "OBJ_27" = { + isa = "PBXGroup"; + children = ( + "OBJ_28" + ); + name = "Tests"; + path = ""; + sourceTree = "SOURCE_ROOT"; + }; + "OBJ_28" = { + isa = "PBXGroup"; + children = ( + "OBJ_29", + "OBJ_30", + "OBJ_31", + "OBJ_32", + "OBJ_33", + "OBJ_34" + ); + name = "ConcurrencyTests"; + path = "Tests/ConcurrencyTests"; + sourceTree = "SOURCE_ROOT"; + }; + "OBJ_29" = { + isa = "PBXFileReference"; + path = "AtomicBoolTests.swift"; + sourceTree = ""; + }; + "OBJ_3" = { + isa = "XCBuildConfiguration"; + buildSettings = { + CLANG_ENABLE_OBJC_ARC = "YES"; + COMBINE_HIDPI_IMAGES = "YES"; + COPY_PHASE_STRIP = "NO"; + DEBUG_INFORMATION_FORMAT = "dwarf"; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_NS_ASSERTIONS = "YES"; + GCC_OPTIMIZATION_LEVEL = "0"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SWIFT_PACKAGE=1", + "DEBUG=1" + ); + MACOSX_DEPLOYMENT_TARGET = "10.10"; + ONLY_ACTIVE_ARCH = "YES"; + OTHER_SWIFT_FLAGS = ( + "-DXcode" + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = "macosx"; + SUPPORTED_PLATFORMS = ( + "macosx", + "iphoneos", + "iphonesimulator", + "appletvos", + "appletvsimulator", + "watchos", + "watchsimulator" + ); + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( + "$(inherited)", + "SWIFT_PACKAGE", + "DEBUG" + ); + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + USE_HEADERMAP = "NO"; + }; + name = "Debug"; + }; + "OBJ_30" = { + isa = "PBXFileReference"; + path = "AtomicIntTests.swift"; + sourceTree = ""; + }; + "OBJ_31" = { + isa = "PBXFileReference"; + path = "AtomicReferenceTests.swift"; + sourceTree = ""; + }; + "OBJ_32" = { + isa = "PBXFileReference"; + path = "AutoReleasingSemaphoreTests.swift"; + sourceTree = ""; + }; + "OBJ_33" = { + isa = "PBXFileReference"; + path = "CountDownLatchTests.swift"; + sourceTree = ""; + }; + "OBJ_34" = { + isa = "PBXGroup"; + children = ( + "OBJ_35" + ); + name = "Executor"; + path = "Executor"; + sourceTree = ""; + }; + "OBJ_35" = { + isa = "PBXFileReference"; + path = "ConcurrentSequenceExecutorTests.swift"; + sourceTree = ""; + }; + "OBJ_36" = { + isa = "PBXGroup"; + children = ( + "Concurrency::Concurrency::Product", + "Concurrency::ConcurrencyTests::Product", + "Concurrency::ObjCBridges::Product" + ); + name = "Products"; + path = ""; + sourceTree = "BUILT_PRODUCTS_DIR"; + }; + "OBJ_4" = { + isa = "XCBuildConfiguration"; + buildSettings = { + CLANG_ENABLE_OBJC_ARC = "YES"; + COMBINE_HIDPI_IMAGES = "YES"; + COPY_PHASE_STRIP = "YES"; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_OPTIMIZATION_LEVEL = "s"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SWIFT_PACKAGE=1" + ); + MACOSX_DEPLOYMENT_TARGET = "10.10"; + OTHER_SWIFT_FLAGS = ( + "-DXcode" + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = "macosx"; + SUPPORTED_PLATFORMS = ( + "macosx", + "iphoneos", + "iphonesimulator", + "appletvos", + "appletvsimulator", + "watchos", + "watchsimulator" + ); + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( + "$(inherited)", + "SWIFT_PACKAGE" + ); + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + USE_HEADERMAP = "NO"; + }; + name = "Release"; + }; + "OBJ_40" = { + isa = "PBXFileReference"; + path = "CODE_OF_CONDUCT.md"; + sourceTree = ""; + }; + "OBJ_41" = { + isa = "PBXFileReference"; + path = "Package.xcconfig"; + sourceTree = ""; + }; + "OBJ_42" = { + isa = "PBXFileReference"; + path = "README.md"; + sourceTree = ""; + }; + "OBJ_43" = { + isa = "PBXFileReference"; + path = "NOTICE.txt"; + sourceTree = ""; + }; + "OBJ_44" = { + isa = "PBXFileReference"; + path = "CONTRIBUTING.md"; + sourceTree = ""; + }; + "OBJ_45" = { + isa = "PBXFileReference"; + path = "LICENSE.txt"; + sourceTree = ""; + }; + "OBJ_47" = { + isa = "XCConfigurationList"; + buildConfigurations = ( + "OBJ_48", + "OBJ_49" + ); + defaultConfigurationIsVisible = "0"; + defaultConfigurationName = "Release"; + }; + "OBJ_48" = { + isa = "XCBuildConfiguration"; + baseConfigurationReference = "OBJ_8"; + buildSettings = { + ENABLE_TESTABILITY = "YES"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PLATFORM_DIR)/Developer/Library/Frameworks" + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/Sources/ObjCBridges/include", + "$(SRCROOT)/Concurrency.xcodeproj/GeneratedModuleMap/ObjCBridges" + ); + INFOPLIST_FILE = "Concurrency.xcodeproj/Concurrency_Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx" + ); + OTHER_CFLAGS = ( + "$(inherited)" + ); + OTHER_LDFLAGS = ( + "$(inherited)" + ); + OTHER_SWIFT_FLAGS = ( + "$(inherited)", + "-Xcc", + "-fmodule-map-file=$(SRCROOT)/Concurrency.xcodeproj/GeneratedModuleMap/ObjCBridges/module.modulemap" + ); + PRODUCT_BUNDLE_IDENTIFIER = "Concurrency"; + PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = "YES"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( + "$(inherited)" + ); + SWIFT_VERSION = "4.0"; + TARGET_NAME = "Concurrency"; + }; + name = "Debug"; + }; + "OBJ_49" = { + isa = "XCBuildConfiguration"; + baseConfigurationReference = "OBJ_8"; + buildSettings = { + ENABLE_TESTABILITY = "YES"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PLATFORM_DIR)/Developer/Library/Frameworks" + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/Sources/ObjCBridges/include", + "$(SRCROOT)/Concurrency.xcodeproj/GeneratedModuleMap/ObjCBridges" + ); + INFOPLIST_FILE = "Concurrency.xcodeproj/Concurrency_Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx" + ); + OTHER_CFLAGS = ( + "$(inherited)" + ); + OTHER_LDFLAGS = ( + "$(inherited)" + ); + OTHER_SWIFT_FLAGS = ( + "$(inherited)", + "-Xcc", + "-fmodule-map-file=$(SRCROOT)/Concurrency.xcodeproj/GeneratedModuleMap/ObjCBridges/module.modulemap" + ); + PRODUCT_BUNDLE_IDENTIFIER = "Concurrency"; + PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = "YES"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( + "$(inherited)" + ); + SWIFT_VERSION = "4.0"; + TARGET_NAME = "Concurrency"; + }; + name = "Release"; + }; + "OBJ_5" = { + isa = "PBXGroup"; + children = ( + "OBJ_6", + "OBJ_7", + "OBJ_9", + "OBJ_27", + "OBJ_36", + "OBJ_40", + "OBJ_41", + "OBJ_42", + "OBJ_43", + "OBJ_44", + "OBJ_45" + ); + path = ""; + sourceTree = ""; + }; + "OBJ_50" = { + isa = "PBXSourcesBuildPhase"; + files = ( + "OBJ_51", + "OBJ_52", + "OBJ_53", + "OBJ_54", + "OBJ_55", + "OBJ_56", + "OBJ_57", + "OBJ_58", + "OBJ_59" + ); + }; + "OBJ_51" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_12"; + }; + "OBJ_52" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_13"; + }; + "OBJ_53" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_14"; + }; + "OBJ_54" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_15"; + }; + "OBJ_55" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_16"; + }; + "OBJ_56" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_18"; + }; + "OBJ_57" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_19"; + }; + "OBJ_58" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_20"; + }; + "OBJ_59" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_21"; + }; + "OBJ_6" = { + isa = "PBXFileReference"; + explicitFileType = "sourcecode.swift"; + path = "Package.swift"; + sourceTree = ""; + }; + "OBJ_60" = { + isa = "PBXFrameworksBuildPhase"; + files = ( + "OBJ_61" + ); + }; + "OBJ_61" = { + isa = "PBXBuildFile"; + fileRef = "Concurrency::ObjCBridges::Product"; + }; + "OBJ_62" = { + isa = "PBXTargetDependency"; + target = "Concurrency::ObjCBridges"; + }; + "OBJ_65" = { + isa = "XCConfigurationList"; + buildConfigurations = ( + "OBJ_66", + "OBJ_67" + ); + defaultConfigurationIsVisible = "0"; + defaultConfigurationName = "Release"; + }; + "OBJ_66" = { + isa = "XCBuildConfiguration"; + buildSettings = { + LD = "/usr/bin/true"; + OTHER_SWIFT_FLAGS = ( + "-swift-version", + "4", + "-I", + "$(TOOLCHAIN_DIR)/usr/lib/swift/pm/4", + "-target", + "x86_64-apple-macosx10.10", + "-sdk", + "/Applications/Xcode.10.2.1.10E1001.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk" + ); + SWIFT_VERSION = "4.0"; + }; + name = "Debug"; + }; + "OBJ_67" = { + isa = "XCBuildConfiguration"; + buildSettings = { + LD = "/usr/bin/true"; + OTHER_SWIFT_FLAGS = ( + "-swift-version", + "4", + "-I", + "$(TOOLCHAIN_DIR)/usr/lib/swift/pm/4", + "-target", + "x86_64-apple-macosx10.10", + "-sdk", + "/Applications/Xcode.10.2.1.10E1001.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk" + ); + SWIFT_VERSION = "4.0"; + }; + name = "Release"; + }; + "OBJ_68" = { + isa = "PBXSourcesBuildPhase"; + files = ( + "OBJ_69" + ); + }; + "OBJ_69" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_6"; + }; + "OBJ_7" = { + isa = "PBXGroup"; + children = ( + "OBJ_8" + ); + name = "Configs"; + path = ""; + sourceTree = ""; + }; + "OBJ_71" = { + isa = "XCConfigurationList"; + buildConfigurations = ( + "OBJ_72", + "OBJ_73" + ); + defaultConfigurationIsVisible = "0"; + defaultConfigurationName = "Release"; + }; + "OBJ_72" = { + isa = "XCBuildConfiguration"; + buildSettings = { + }; + name = "Debug"; + }; + "OBJ_73" = { + isa = "XCBuildConfiguration"; + buildSettings = { + }; + name = "Release"; + }; + "OBJ_74" = { + isa = "PBXTargetDependency"; + target = "Concurrency::ConcurrencyTests"; + }; + "OBJ_76" = { + isa = "XCConfigurationList"; + buildConfigurations = ( + "OBJ_77", + "OBJ_78" + ); + defaultConfigurationIsVisible = "0"; + defaultConfigurationName = "Release"; + }; + "OBJ_77" = { + isa = "XCBuildConfiguration"; + baseConfigurationReference = "OBJ_8"; + buildSettings = { + CLANG_ENABLE_MODULES = "YES"; + EMBEDDED_CONTENT_CONTAINS_SWIFT = "YES"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PLATFORM_DIR)/Developer/Library/Frameworks" + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/Sources/ObjCBridges/include", + "$(SRCROOT)/Concurrency.xcodeproj/GeneratedModuleMap/ObjCBridges" + ); + INFOPLIST_FILE = "Concurrency.xcodeproj/ConcurrencyTests_Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@loader_path/../Frameworks", + "@loader_path/Frameworks" + ); + OTHER_CFLAGS = ( + "$(inherited)" + ); + OTHER_LDFLAGS = ( + "$(inherited)" + ); + OTHER_SWIFT_FLAGS = ( + "$(inherited)", + "-Xcc", + "-fmodule-map-file=$(SRCROOT)/Concurrency.xcodeproj/GeneratedModuleMap/ObjCBridges/module.modulemap" + ); + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( + "$(inherited)" + ); + SWIFT_VERSION = "4.0"; + TARGET_NAME = "ConcurrencyTests"; + }; + name = "Debug"; + }; + "OBJ_78" = { + isa = "XCBuildConfiguration"; + baseConfigurationReference = "OBJ_8"; + buildSettings = { + CLANG_ENABLE_MODULES = "YES"; + EMBEDDED_CONTENT_CONTAINS_SWIFT = "YES"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PLATFORM_DIR)/Developer/Library/Frameworks" + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/Sources/ObjCBridges/include", + "$(SRCROOT)/Concurrency.xcodeproj/GeneratedModuleMap/ObjCBridges" + ); + INFOPLIST_FILE = "Concurrency.xcodeproj/ConcurrencyTests_Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@loader_path/../Frameworks", + "@loader_path/Frameworks" + ); + OTHER_CFLAGS = ( + "$(inherited)" + ); + OTHER_LDFLAGS = ( + "$(inherited)" + ); + OTHER_SWIFT_FLAGS = ( + "$(inherited)", + "-Xcc", + "-fmodule-map-file=$(SRCROOT)/Concurrency.xcodeproj/GeneratedModuleMap/ObjCBridges/module.modulemap" + ); + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( + "$(inherited)" + ); + SWIFT_VERSION = "4.0"; + TARGET_NAME = "ConcurrencyTests"; + }; + name = "Release"; + }; + "OBJ_79" = { + isa = "PBXSourcesBuildPhase"; + files = ( + "OBJ_80", + "OBJ_81", + "OBJ_82", + "OBJ_83", + "OBJ_84", + "OBJ_85" + ); + }; + "OBJ_8" = { + isa = "PBXFileReference"; + path = "Package.xcconfig"; + sourceTree = ""; + }; + "OBJ_80" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_29"; + }; + "OBJ_81" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_30"; + }; + "OBJ_82" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_31"; + }; + "OBJ_83" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_32"; + }; + "OBJ_84" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_33"; + }; + "OBJ_85" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_35"; + }; + "OBJ_86" = { + isa = "PBXFrameworksBuildPhase"; + files = ( + "OBJ_87", + "OBJ_88" + ); + }; + "OBJ_87" = { + isa = "PBXBuildFile"; + fileRef = "Concurrency::Concurrency::Product"; + }; + "OBJ_88" = { + isa = "PBXBuildFile"; + fileRef = "Concurrency::ObjCBridges::Product"; + }; + "OBJ_89" = { + isa = "PBXTargetDependency"; + target = "Concurrency::Concurrency"; + }; + "OBJ_9" = { + isa = "PBXGroup"; + children = ( + "OBJ_10", + "OBJ_22" + ); + name = "Sources"; + path = ""; + sourceTree = "SOURCE_ROOT"; + }; + "OBJ_90" = { + isa = "PBXTargetDependency"; + target = "Concurrency::ObjCBridges"; + }; + "OBJ_91" = { + isa = "XCConfigurationList"; + buildConfigurations = ( + "OBJ_92", + "OBJ_93" + ); + defaultConfigurationIsVisible = "0"; + defaultConfigurationName = "Release"; + }; + "OBJ_92" = { + isa = "XCBuildConfiguration"; + baseConfigurationReference = "OBJ_8"; + buildSettings = { + DEFINES_MODULE = "NO"; + ENABLE_TESTABILITY = "YES"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PLATFORM_DIR)/Developer/Library/Frameworks" + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/Sources/ObjCBridges/include" + ); + INFOPLIST_FILE = "Concurrency.xcodeproj/ObjCBridges_Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx" + ); + OTHER_CFLAGS = ( + "$(inherited)" + ); + OTHER_LDFLAGS = ( + "$(inherited)" + ); + OTHER_SWIFT_FLAGS = ( + "$(inherited)" + ); + PRODUCT_BUNDLE_IDENTIFIER = "ObjCBridges"; + PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = "YES"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( + "$(inherited)" + ); + TARGET_NAME = "ObjCBridges"; + }; + name = "Debug"; + }; + "OBJ_93" = { + isa = "XCBuildConfiguration"; + baseConfigurationReference = "OBJ_8"; + buildSettings = { + DEFINES_MODULE = "NO"; + ENABLE_TESTABILITY = "YES"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PLATFORM_DIR)/Developer/Library/Frameworks" + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/Sources/ObjCBridges/include" + ); + INFOPLIST_FILE = "Concurrency.xcodeproj/ObjCBridges_Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx" + ); + OTHER_CFLAGS = ( + "$(inherited)" + ); + OTHER_LDFLAGS = ( + "$(inherited)" + ); + OTHER_SWIFT_FLAGS = ( + "$(inherited)" + ); + PRODUCT_BUNDLE_IDENTIFIER = "ObjCBridges"; + PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = "YES"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( + "$(inherited)" + ); + TARGET_NAME = "ObjCBridges"; + }; + name = "Release"; + }; + "OBJ_94" = { + isa = "PBXSourcesBuildPhase"; + files = ( + "OBJ_95" + ); + }; + "OBJ_95" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_23"; + }; + "OBJ_96" = { + isa = "PBXFrameworksBuildPhase"; + files = ( + ); + }; + }; + rootObject = "OBJ_1"; } diff --git a/Concurrency.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Concurrency.xcodeproj/project.xcworkspace/contents.xcworkspacedata index 919434a..fe1aa71 100644 --- a/Concurrency.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/Concurrency.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,4 @@ - + \ No newline at end of file diff --git a/Concurrency.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Concurrency.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..a72dc2b --- /dev/null +++ b/Concurrency.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded + + + \ No newline at end of file diff --git a/Concurrency.xcodeproj/xcshareddata/xcschemes/Concurrency-Package.xcscheme b/Concurrency.xcodeproj/xcshareddata/xcschemes/Concurrency.xcscheme similarity index 83% rename from Concurrency.xcodeproj/xcshareddata/xcschemes/Concurrency-Package.xcscheme rename to Concurrency.xcodeproj/xcshareddata/xcschemes/Concurrency.xcscheme index f080dd8..5c25636 100644 --- a/Concurrency.xcodeproj/xcshareddata/xcschemes/Concurrency-Package.xcscheme +++ b/Concurrency.xcodeproj/xcshareddata/xcschemes/Concurrency.xcscheme @@ -1,6 +1,6 @@ - - - - @@ -70,6 +60,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> + + + + diff --git a/Concurrency.xcodeproj/xcshareddata/xcschemes/ConcurrencyTests.xcscheme b/Concurrency.xcodeproj/xcshareddata/xcschemes/ConcurrencyTests.xcscheme new file mode 100644 index 0000000..5a416da --- /dev/null +++ b/Concurrency.xcodeproj/xcshareddata/xcschemes/ConcurrencyTests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Package.swift b/Package.swift index d23c66f..7025229 100644 --- a/Package.swift +++ b/Package.swift @@ -1,5 +1,4 @@ -// swift-tools-version:4.0 -// The swift-tools-version declares the minimum version of Swift required to build this package. +// swift-tools-version:5.1 import PackageDescription @@ -12,12 +11,15 @@ let package = Package( ], dependencies: [], targets: [ + .target( + name: "ObjCBridges", + dependencies:[]), .target( name: "Concurrency", - dependencies: []), + dependencies: ["ObjCBridges"]), .testTarget( name: "ConcurrencyTests", dependencies: ["Concurrency"]), ], - swiftLanguageVersions: [4] + swiftLanguageVersions: [.v5] ) diff --git a/Package.xcconfig b/Package.xcconfig new file mode 100644 index 0000000..057251e --- /dev/null +++ b/Package.xcconfig @@ -0,0 +1,2 @@ + +SWIFT_OBJC_BRIDGING_HEADER = Sources/Concurrency/Concurrency-Bridging-Header.h diff --git a/README.md b/README.md index 0eec186..3ae349f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # Swift Concurrency -[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fuber%2Fswift-concurrency.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fuber%2Fswift-concurrency?ref=badge_shield) + +[![Build Status](https://travis-ci.com/uber/swift-concurrency.svg?branch=master)](https://travis-ci.com/uber/swift-concurrency?branch=master) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) ## Contents @@ -92,6 +95,12 @@ $ swift test Or you can follow the steps above to generate a Xcode project and run tests within Xcode. +## Related projects + +If you like Needle, check out other related open source projects from our team: +- [Needle](https://github.com/uber/needle): a compile-time safe Swift dependency injection framework. +- [Swift Abstract Class](https://github.com/uber/swift-abstract-class): a light-weight library along with an executable that enables compile-time safe abstract class development for Swift projects. +- [Swift Common](https://github.com/uber/swift-common): common libraries used by this set of Swift open source projects. ## License [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fuber%2Fswift-concurrency.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fuber%2Fswift-concurrency?ref=badge_large) diff --git a/Sources/Concurrency/AtomicInt.swift b/Sources/Concurrency/AtomicInt.swift index 6622a58..ec757a7 100644 --- a/Sources/Concurrency/AtomicInt.swift +++ b/Sources/Concurrency/AtomicInt.swift @@ -16,6 +16,7 @@ import Foundation import libkern +import ObjCBridges /// A concurrency utility class that supports locking-free synchronization on mutating an integer /// value. Unlike using a lock, concurrent read and write accesses to this class is allowed. At @@ -28,8 +29,8 @@ public class AtomicInt { get { // Create a memory barrier to ensure the entire memory stack is in sync so we // can safely retrieve the value. This guarantees the initial value is in sync. - OSMemoryBarrier() - return Int(wrappedValue) + atomic_thread_fence(memory_order_seq_cst) + return wrappedValue } set { while true { @@ -45,7 +46,7 @@ public class AtomicInt { /// /// - parameter initialValue: The initial value. public init(initialValue: Int) { - wrappedValue = Int64(initialValue) + wrappedValue = initialValue } /// Atomically sets the new value, if the current value equals the expected value. @@ -55,7 +56,8 @@ public class AtomicInt { /// - returns: true if the comparison succeeded and the value is set. false otherwise. @discardableResult public func compareAndSet(expect: Int, newValue: Int) -> Bool { - return OSAtomicCompareAndSwap64Barrier(Int64(expect), Int64(newValue), &wrappedValue) + var mutableExpected = expect + return AtomicBridges.compare(wrappedValueOpaquePointer, withExpected: UnsafeMutablePointer(&mutableExpected), andSwap: newValue) } /// Atomically increment the value and retrieve the new value. @@ -63,8 +65,13 @@ public class AtomicInt { /// - returns: The new value after incrementing. @discardableResult public func incrementAndGet() -> Int { - let result = OSAtomicIncrement64Barrier(&wrappedValue) - return Int(result) + while true { + let oldValue = self.value + let newValue = oldValue + 1 + if self.compareAndSet(expect: oldValue, newValue: newValue) { + return newValue + } + } } /// Atomically decrement the value and retrieve the new value. @@ -72,8 +79,13 @@ public class AtomicInt { /// - returns: The new value after decrementing. @discardableResult public func decrementAndGet() -> Int { - let result = OSAtomicDecrement64Barrier(&wrappedValue) - return Int(result) + while true { + let oldValue = self.value + let newValue = oldValue - 1 + if self.compareAndSet(expect: oldValue, newValue: newValue) { + return newValue + } + } } /// Atomically increment the value and retrieve the old value. @@ -81,13 +93,7 @@ public class AtomicInt { /// - returns: The old value before incrementing. @discardableResult public func getAndIncrement() -> Int { - while true { - let oldValue = self.value - let newValue = oldValue + 1 - if self.compareAndSet(expect: oldValue, newValue: newValue) { - return oldValue - } - } + return AtomicBridges.fetchAndIncrementBarrier(wrappedValueOpaquePointer) } /// Atomically decrement the value and retrieve the old value. @@ -95,13 +101,7 @@ public class AtomicInt { /// - returns: The old value before decrementing. @discardableResult public func getAndDecrement() -> Int { - while true { - let oldValue = self.value - let newValue = oldValue - 1 - if self.compareAndSet(expect: oldValue, newValue: newValue) { - return oldValue - } - } + return AtomicBridges.fetchAndDecrementBarrier(wrappedValueOpaquePointer) } /// Atomically sets to the given new value and returns the old value. @@ -120,5 +120,9 @@ public class AtomicInt { // MARK: - Private - private var wrappedValue: Int64 + private var wrappedValue: Int + + private var wrappedValueOpaquePointer: OpaquePointer { + return OpaquePointer(UnsafeMutablePointer(&wrappedValue)) + } } diff --git a/Sources/Concurrency/AtomicReference.swift b/Sources/Concurrency/AtomicReference.swift index c857386..8a1856e 100644 --- a/Sources/Concurrency/AtomicReference.swift +++ b/Sources/Concurrency/AtomicReference.swift @@ -16,6 +16,7 @@ import Foundation import libkern +import ObjCBridges /// A concurrency utility class that supports locking-free synchronization on mutating an object /// reference. Unlike using a lock, concurrent read and write accesses to this class is allowed. At @@ -28,7 +29,7 @@ public class AtomicReference { get { // Create a memory barrier to ensure the entire memory stack is in sync so we // can safely retrieve the value. This guarantees the initial value is in sync. - OSMemoryBarrier() + atomic_thread_fence(memory_order_seq_cst) return wrappedValue } set { @@ -59,7 +60,7 @@ public class AtomicReference { let expectPointer = unsafePassUnretainedPointer(value: expect) let newValuePointer = unsafePassUnretainedPointer(value: newValue) - if OSAtomicCompareAndSwapPtrBarrier(expectPointer, newValuePointer, pointer) { + if AtomicBridges.comparePointer(pointer, withExpectedPointer: expectPointer, andSwapPointer: newValuePointer) { // If pointer swap succeeded, a memory berrier is created, so we can safely write the new // value. wrappedValue = newValue diff --git a/Sources/Concurrency/AutoReleasingSemaphore.swift b/Sources/Concurrency/AutoReleasingSemaphore.swift new file mode 100644 index 0000000..34a1c20 --- /dev/null +++ b/Sources/Concurrency/AutoReleasingSemaphore.swift @@ -0,0 +1,85 @@ +// +// Copyright (c) 2018. Uber Technologies +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +/// Similar to `DispatchSemaphore`, `AutoReleasingSemaphore` is a +/// synchronization mechanism that ensures only a set number of threads can +/// concurrently access a protected resource. Unlike `DispatchSemaphore`, +/// `AutoReleasingSemaphore` auto-releases all blocked threads when the +/// semaphore itself is deallocated. +public class AutoReleasingSemaphore { + + /// Initializer. + /// + /// - parameter value: The starting value for the semaphore. Do not + /// pass a value less than zero. + public init(value: Int) { + semaphore = DispatchSemaphore(value: value) + } + + /// Signals, or increments, a semaphore. + /// + /// - note: Increment the counting semaphore. If the previous value + /// was less than zero, this function wakes a thread currently waiting + /// in dispatch_semaphore_wait(_:_:). + /// - returns: This function returns non-zero if a thread is woken. + /// Otherwise, zero is returned. + @discardableResult + public func signal() -> Int { + let newValue = waitingCount.decrementAndGet() + if newValue < 0 { + waitingCount.value = 0 + } + return semaphore.signal() + } + + /// Waits for, or decrements, a semaphore. + /// + /// - note: Decrement the counting semaphore. If the resulting value + /// is less than zero, this function waits for a signal to occur + /// before returning. + public func wait() { + waitingCount.incrementAndGet() + semaphore.wait() + } + + /// Waits for, or decrements, a semaphore for up to the specified + /// time. + /// + /// - note: Decrement the counting semaphore. If the resulting value + /// is less than zero, this function waits for a signal to occur + /// before returning. + /// - parameter timeout: The amount of time in seconds to wait + /// before returning with failure. + /// - returns: The waiting result. + @discardableResult + public func wait(timeout: TimeInterval) -> DispatchTimeoutResult { + waitingCount.incrementAndGet() + return semaphore.wait(timeout: DispatchTime.now() + timeout) + } + + deinit { + for _ in 0 ..< waitingCount.value { + semaphore.signal() + } + } + + // MARK: - Private + + private let semaphore: DispatchSemaphore + private let waitingCount = AtomicInt(initialValue: 0) +} diff --git a/Tests/LinuxMain.swift b/Sources/Concurrency/Concurrency-Bridging-Header.h similarity index 68% rename from Tests/LinuxMain.swift rename to Sources/Concurrency/Concurrency-Bridging-Header.h index c38bb51..2a05e68 100644 --- a/Tests/LinuxMain.swift +++ b/Sources/Concurrency/Concurrency-Bridging-Header.h @@ -14,13 +14,10 @@ // limitations under the License. // -import XCTest -@testable import ConcurrencyTests +#ifndef Concurrency_Bridging_Header_h +#define Concurrency_Bridging_Header_h -XCTMain([ - testCase(AtomicBoolTests.allTests), - testCase(AtomicIntTests.allTests), - testCase(AtomicReferenceTests.allTests), - testCase(CountDownLatchTests.allTests), - testCase(ConcurrentSequenceExecutorTests.allTests), -]) +#import "AtomicBridges.h" + + +#endif /* Concurrency_Bridging_Header_h */ diff --git a/Sources/Concurrency/Executor/ConcurrentSequenceExecutor.swift b/Sources/Concurrency/Executor/ConcurrentSequenceExecutor.swift index d20be3c..35f6570 100644 --- a/Sources/Concurrency/Executor/ConcurrentSequenceExecutor.swift +++ b/Sources/Concurrency/Executor/ConcurrentSequenceExecutor.swift @@ -27,8 +27,23 @@ public class ConcurrentSequenceExecutor: SequenceExecutor { /// - parameter name: The name of the executor. /// - parameter qos: The quality of service of this executor. This /// defaults to `userInitiated`. - public init(name: String, qos: DispatchQoS = .userInitiated) { + /// - parameter shouldTrackTaskId: `true` if task IDs should be tracked + /// as tasks are executed. `false` otherwise. By tracking the task IDs, + /// if waiting on the completion of a task sequence times out, the + /// reported error contains the ID of the task that was being executed + /// when the timeout occurred. The tracking does incur a minor + /// performance cost. This value defaults to `false`. + /// - parameter maxConcurrentTasks: The optional maximum number of tasks + /// the executor can execute concurrently. `nil` if the executor should + /// not limit the maximum number of concurrent tasks. Defaults to `nil`. + public init(name: String, qos: DispatchQoS = .userInitiated, shouldTrackTaskId: Bool = false, maxConcurrentTasks: Int? = nil) { taskQueue = DispatchQueue(label: "Executor.taskQueue-\(name)", qos: qos, attributes: .concurrent) + if let maxConcurrentTasks = maxConcurrentTasks { + taskSemaphore = AutoReleasingSemaphore(value: maxConcurrentTasks) + } else { + taskSemaphore = nil + } + self.shouldTrackTaskId = shouldTrackTaskId } /// Execute a sequence of tasks concurrently from the given initial task. @@ -51,20 +66,35 @@ public class ConcurrentSequenceExecutor: SequenceExecutor { // MARK: - Private private let taskQueue: DispatchQueue + private let taskSemaphore: AutoReleasingSemaphore? + private let shouldTrackTaskId: Bool private func execute(_ task: Task, with sequenceHandle: SynchronizedSequenceExecutionHandle, _ execution: @escaping (Task, Any) -> SequenceExecution) { + taskSemaphore?.wait() taskQueue.async { guard !sequenceHandle.isCancelled else { + self.taskSemaphore?.signal() return } - let result = task.typeErasedExecute() - let nextExecution = execution(task, result) - switch nextExecution { - case .continueSequence(let nextTask): - self.execute(nextTask, with: sequenceHandle, execution) - case .endOfSequence(let result): - sequenceHandle.sequenceDidComplete(with: result) + if self.shouldTrackTaskId { + sequenceHandle.willBeginExecuting(taskId: task.id) + } + + do { + let result = try task.typeErasedExecute() + let nextExecution = execution(task, result) + self.taskSemaphore?.signal() + + switch nextExecution { + case .continueSequence(let nextTask): + self.execute(nextTask, with: sequenceHandle, execution) + case .endOfSequence(let result): + sequenceHandle.sequenceDidComplete(with: result) + } + } catch { + self.taskSemaphore?.signal() + sequenceHandle.sequenceDidError(with: error) } } } @@ -74,30 +104,40 @@ private class SynchronizedSequenceExecutionHandle: SequenceE private let latch = CountDownLatch(count: 1) private let didCancel = AtomicBool(initialValue: false) + private let currentTaskId = AtomicInt(initialValue: nonTrackingDefaultTaskId) - // Use a lock to ensure result is properly accessed, since the read + // Use a lock to ensure result/error is properly accessed, since the read // `await` method may be invoked on a different thread than the write - // `sequenceDidComplete` method. + // `sequenceDidComplete`/`sequenceDidError` method. private let resultLock = NSRecursiveLock() private var result: SequenceResultType? + private var error: Error? fileprivate var isCancelled: Bool { return didCancel.value } + fileprivate func willBeginExecuting(taskId: Int) { + currentTaskId.value = taskId + } + fileprivate override func await(withTimeout timeout: TimeInterval?) throws -> SequenceResultType { let didComplete = latch.await(timeout: timeout) if !didComplete { - throw SequenceExecutionError.awaitTimeout + throw SequenceExecutionError.awaitTimeout(currentTaskId.value) } resultLock.lock() defer { resultLock.unlock() } - // If latch was counted down, the result must have been set. Therefore, - // this forced unwrap is safe. - return result! + if let error = self.error { + throw error + } else { + // If latch was counted down and there is no error, the result must have been + // set. Therefore, this forced-unwrap is safe. + return result! + } } fileprivate func sequenceDidComplete(with result: SequenceResultType) { @@ -108,6 +148,14 @@ private class SynchronizedSequenceExecutionHandle: SequenceE latch.countDown() } + fileprivate func sequenceDidError(with error: Error) { + resultLock.lock() + self.error = error + resultLock.unlock() + + latch.countDown() + } + fileprivate override func cancel() { didCancel.compareAndSet(expect: false, newValue: true) } diff --git a/Sources/Concurrency/Executor/SerialSequenceExecutor.swift b/Sources/Concurrency/Executor/ImmediateSerialSequenceExecutor.swift similarity index 77% rename from Sources/Concurrency/Executor/SerialSequenceExecutor.swift rename to Sources/Concurrency/Executor/ImmediateSerialSequenceExecutor.swift index 1245e65..576b046 100644 --- a/Sources/Concurrency/Executor/SerialSequenceExecutor.swift +++ b/Sources/Concurrency/Executor/ImmediateSerialSequenceExecutor.swift @@ -17,20 +17,20 @@ import Foundation /// An executor that executes sequences of tasks serially from the -/// caller thread. +/// caller thread as soon as the execute method is invoked. /// /// - note: Generally this implementation should only be used for debugging /// purposes, as debugging highly concurrent task executions can be very /// challenging. Production code should use `ConcurrentSequenceExecutor`. /// - seeAlso: `SequenceExecutor`. /// - seeAlso: `Task`. -public class SerialSequenceExecutor: SequenceExecutor { +public class ImmediateSerialSequenceExecutor: SequenceExecutor { /// Initializer. public init() {} /// Execute a sequence of tasks serially from the given initial task - /// on the caller thread. + /// on the caller thread, immediately. /// /// - parameter initialTask: The root task of the sequence of tasks /// to be executed. @@ -54,13 +54,17 @@ public class SerialSequenceExecutor: SequenceExecutor { return } - let result = task.typeErasedExecute() - let nextExecution = execution(task, result) - switch nextExecution { - case .continueSequence(let nextTask): - self.execute(nextTask, with: sequenceHandle, execution) - case .endOfSequence(let result): - sequenceHandle.sequenceDidComplete(with: result) + do { + let result = try task.typeErasedExecute() + let nextExecution = execution(task, result) + switch nextExecution { + case .continueSequence(let nextTask): + self.execute(nextTask, with: sequenceHandle, execution) + case .endOfSequence(let result): + sequenceHandle.sequenceDidComplete(with: result) + } + } catch { + sequenceHandle.sequenceDidError(with: error) } } } @@ -69,19 +73,28 @@ private class SequenceExecutionHandleImpl: SequenceExecution private var didCancel = false private var result: SequenceResultType? + private var error: Error? fileprivate var isCancelled: Bool { return didCancel } fileprivate override func await(withTimeout timeout: TimeInterval?) throws -> SequenceResultType { - return result! + if let error = self.error { + throw error + } else { + return result! + } } fileprivate func sequenceDidComplete(with result: SequenceResultType) { self.result = result } + fileprivate func sequenceDidError(with error: Error) { + self.error = error + } + fileprivate override func cancel() { didCancel = true } diff --git a/Sources/Concurrency/Executor/SequenceExecutor.swift b/Sources/Concurrency/Executor/SequenceExecutor.swift index 03c9568..27b5029 100644 --- a/Sources/Concurrency/Executor/SequenceExecutor.swift +++ b/Sources/Concurrency/Executor/SequenceExecutor.swift @@ -18,8 +18,12 @@ import Foundation /// Errors that can occur during a sequence execution. public enum SequenceExecutionError: Error { - /// The waiting on sequence completion timed out. - case awaitTimeout + /// The waiting on sequence completion timed out. The `Int` value + /// indicates the ID of the task that was being executed when the + /// timeout occurred. If the value is `nonTrackingDefaultTaskId`, + /// then the executor was not configured to track task IDs during + /// initialization. + case awaitTimeout(Int) } /// The handle of the execution of a sequence of tasks, that allows control @@ -39,6 +43,7 @@ open class SequenceExecutionHandle { /// completes. /// - throws: `SequenceExecutionError.awaitTimeout` if the given timeout /// period elapsed before the sequence execution completed. + /// - throws: Any error thrown by the task during execution. open func await(withTimeout timeout: TimeInterval?) throws -> SequenceResultType { fatalError("await not yet implemented.") } diff --git a/Sources/Concurrency/Executor/Task.swift b/Sources/Concurrency/Executor/Task.swift index 46dea90..a67a75b 100644 --- a/Sources/Concurrency/Executor/Task.swift +++ b/Sources/Concurrency/Executor/Task.swift @@ -16,21 +16,27 @@ import Foundation +public let nonTrackingDefaultTaskId = Int.min + /// An individual unit of work that can be executed in a concurrent /// environment by an executor. // Task cannot be generic since it needs to be referenced by the executor // class which cannot provide type information for specific tasks. public protocol Task { + /// A unique ID number identifying the task. + var id: Int { get } + /// Execute this task without any type information. /// /// - note: This method should only be used by internal executor /// implementations. /// - returns: The type erased execution result of this task. + /// - throws: Any error occurred during execution. // Return type cannot be generic since the `Task` type needs to be // referenced by the executor class which cannot provide type information // for results. - func typeErasedExecute() -> Any + func typeErasedExecute() throws -> Any } /// The base abstraction of a task that has a defined execution result @@ -41,25 +47,35 @@ public protocol Task { // wildcard generics. open class AbstractTask: Task { + /// A unique ID number identifying the task. + public let id: Int + /// Initializer. - public init() {} + /// + /// - parameter id: A unique ID number identifying the task. This value + /// defaults to `nonTrackingDefaultTaskId`. + public init(id: Int = nonTrackingDefaultTaskId) { + self.id = id + } /// Execute this task without any type information. /// /// - note: This method should only be used by internal executor /// implementations. /// - returns: The type erased execution result of this task. + /// - throws: Any error occurred during execution. // Return type cannot be generic since the `Task` type needs to be // referenced by the executor class which cannot provide type information // for results. - public final func typeErasedExecute() -> Any { - return execute() + public final func typeErasedExecute() throws -> Any { + return try execute() } /// Execute this task and return the result. /// /// - returns: The execution result of this task. - open func execute() -> ResultType { + /// - throws: Any error occurred during execution. + open func execute() throws -> ResultType { fatalError("\(self).execute is not yet implemented.") } } diff --git a/Sources/ObjCBridges/AtomicBridges.m b/Sources/ObjCBridges/AtomicBridges.m new file mode 100644 index 0000000..cc25ddd --- /dev/null +++ b/Sources/ObjCBridges/AtomicBridges.m @@ -0,0 +1,37 @@ +// +// Copyright (c) 2018. Uber Technologies +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "AtomicBridges.h" + +@implementation AtomicBridges + ++ (long)fetchAndIncrementBarrier:(_Atomic(long) *)value { + return atomic_fetch_add(value, 1); +} + ++ (long)fetchAndDecrementBarrier:(_Atomic(long) *)value { + return atomic_fetch_sub(value, 1); +} + ++ (bool)compare:(_Atomic(long) *)value withExpected:(long *)expected andSwap:(long)desired { + return atomic_compare_exchange_strong(value, expected, desired); +} + ++ (bool)comparePointer:(void * volatile *)value withExpectedPointer:(void *)expected andSwapPointer:(void *)desired { + return __sync_bool_compare_and_swap(value, expected, desired); +} + +@end diff --git a/Sources/ObjCBridges/include/AtomicBridges.h b/Sources/ObjCBridges/include/AtomicBridges.h new file mode 100644 index 0000000..3b2fc71 --- /dev/null +++ b/Sources/ObjCBridges/include/AtomicBridges.h @@ -0,0 +1,34 @@ +// +// Copyright (c) 2018. Uber Technologies +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface AtomicBridges: NSObject + ++ (long)fetchAndIncrementBarrier:(_Atomic(long) *)value; + ++ (long)fetchAndDecrementBarrier:(_Atomic(long) *)value; + ++ (bool)compare:(_Atomic(long) *)value withExpected:(long *)expected andSwap:(long)desired; + ++ (bool)comparePointer:(void * _Nullable volatile * _Nonnull)value withExpectedPointer:(void *)expected andSwapPointer:(void *)desired; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Tests/ConcurrencyTests/AtomicIntTests.swift b/Tests/ConcurrencyTests/AtomicIntTests.swift index fc4b5bd..60f8877 100644 --- a/Tests/ConcurrencyTests/AtomicIntTests.swift +++ b/Tests/ConcurrencyTests/AtomicIntTests.swift @@ -19,18 +19,6 @@ import XCTest class AtomicIntTests: XCTestCase { - static var allTests = [ - ("test_init_verifyInitialValue", test_init_verifyInitialValue), - ("test_initGetSet_verifySetToNewValue", test_initGetSet_verifySetToNewValue), - ("test_compareAndSet_verifySettingNewValue", test_compareAndSet_verifySettingNewValue), - ("test_compareAndSet_withFalseExpectValue_verifyNotSettingNewValue", test_compareAndSet_withFalseExpectValue_verifyNotSettingNewValue), - ("test_getAndSet_verifySettingNewValueReturningOldValue", test_getAndSet_verifySettingNewValueReturningOldValue), - ("test_incrementAndGet_verifyNewValue", test_incrementAndGet_verifyNewValue), - ("test_decrementAndGet_verifyNewValue", test_decrementAndGet_verifyNewValue), - ("test_getAndIncrement_verifyNewValue", test_getAndIncrement_verifyNewValue), - ("test_getAndDecrement_verifyNewValue", test_getAndDecrement_verifyNewValue), - ] - func test_init_verifyInitialValue() { let initialValue = 123 let atomicInt = AtomicInt(initialValue: initialValue) diff --git a/Tests/ConcurrencyTests/AtomicReferenceTests.swift b/Tests/ConcurrencyTests/AtomicReferenceTests.swift index c589ba1..8dc540b 100644 --- a/Tests/ConcurrencyTests/AtomicReferenceTests.swift +++ b/Tests/ConcurrencyTests/AtomicReferenceTests.swift @@ -19,16 +19,6 @@ import XCTest class AtomicReferenceTests: XCTestCase { - static var allTests = [ - ("test_init_verifyInitialValue", test_init_verifyInitialValue), - ("test_initGetSet_verifySetToNewValue", test_initGetSet_verifySetToNewValue), - ("test_compareAndSet_verifySettingNewValue", test_compareAndSet_verifySettingNewValue), - ("test_compareAndSet_withFalseExpectValue_verifyNotSettingNewValue", test_compareAndSet_withFalseExpectValue_verifyNotSettingNewValue), - ("test_compareAndSet_withNil_verifySettingNewValue", test_compareAndSet_withNil_verifySettingNewValue), - ("test_getAndSet_verifySettingNewValueReturningOldValue", test_getAndSet_verifySettingNewValueReturningOldValue), - ("test_compareAndSet_initialNilThenResetToNil_verifySuccess", test_compareAndSet_initialNilThenResetToNil_verifySuccess), - ] - func test_init_verifyInitialValue() { let initialValue = NSObject() let atomicRef = AtomicReference(initialValue: initialValue) diff --git a/Tests/ConcurrencyTests/AutoReleasingSemaphoreTests.swift b/Tests/ConcurrencyTests/AutoReleasingSemaphoreTests.swift new file mode 100644 index 0000000..23991d6 --- /dev/null +++ b/Tests/ConcurrencyTests/AutoReleasingSemaphoreTests.swift @@ -0,0 +1,67 @@ +// +// Copyright (c) 2018. Uber Technologies +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import XCTest +@testable import Concurrency + +class AutoReleasingSemaphoreTests: XCTestCase { + + func test_wait_releaseAfterWait_verifyAutoRelease() { + var semaphore: AutoReleasingSemaphore? = AutoReleasingSemaphore(value: 1) + + let autoreleaseExpectation = expectation(description: "autoreleaseExpectation") + DispatchQueue.global(qos: .background).async { + semaphore!.wait() + autoreleaseExpectation.fulfill() + } + + Thread.sleep(forTimeInterval: 1) + semaphore = nil + + waitForExpectations(timeout: 5, handler: nil) + } + + func test_waitWithTimeout_verifyTimeout() { + let semaphore = AutoReleasingSemaphore(value: 0) + + let waitExpectation = expectation(description: "waitExpectation") + DispatchQueue.global(qos: .background).async { + let result = semaphore.wait(timeout: 1) + XCTAssertEqual(result, DispatchTimeoutResult.timedOut) + waitExpectation.fulfill() + } + + waitForExpectations(timeout: 5, handler: nil) + } + + func test_wait_releaseAfterWait_overSignaling_verifyAutoRelease() { + var semaphore: AutoReleasingSemaphore? = AutoReleasingSemaphore(value: 1) + for _ in 0 ..< 1000 { + _ = semaphore!.signal() + } + + let autoreleaseExpectation = expectation(description: "autoreleaseExpectation") + DispatchQueue.global(qos: .background).async { + semaphore!.wait() + autoreleaseExpectation.fulfill() + } + + Thread.sleep(forTimeInterval: 1) + semaphore = nil + + waitForExpectations(timeout: 5, handler: nil) + } +} diff --git a/Tests/ConcurrencyTests/CountDownLatchTests.swift b/Tests/ConcurrencyTests/CountDownLatchTests.swift index b0a0457..ee24609 100644 --- a/Tests/ConcurrencyTests/CountDownLatchTests.swift +++ b/Tests/ConcurrencyTests/CountDownLatchTests.swift @@ -19,14 +19,6 @@ import XCTest class CountDownLatchTests: XCTestCase { - static var allTests = [ - ("test_countDown_await_verifyCompletionWithTrue", test_countDown_await_verifyCompletionWithTrue), - ("test_countDown_await_withTimeout_verifyCompletionWithFalse", test_countDown_await_withTimeout_verifyCompletionWithFalse), - ("test_countDown_await_verifyDuplicateCountDown_verifyDuplicateAwaitCompletesWithTrue", test_countDown_await_verifyDuplicateCountDown_verifyDuplicateAwaitCompletesWithTrue), - ("test_multipleAwaitBeforeCountDown_verifyCompletesWithTrue", test_multipleAwaitBeforeCountDown_verifyCompletesWithTrue), - ("test_multipleAsyncAwaitBeforeCountDown_verifyCompletesWithTrue", test_multipleAsyncAwaitBeforeCountDown_verifyCompletesWithTrue), - ] - func test_countDown_await_verifyCompletionWithTrue() { let latch = CountDownLatch(count: 3) diff --git a/Tests/ConcurrencyTests/Executor/ConcurrentSequenceExecutorTests.swift b/Tests/ConcurrencyTests/Executor/ConcurrentSequenceExecutorTests.swift index 3cd953c..0aaf873 100644 --- a/Tests/ConcurrencyTests/Executor/ConcurrentSequenceExecutorTests.swift +++ b/Tests/ConcurrencyTests/Executor/ConcurrentSequenceExecutorTests.swift @@ -122,14 +122,14 @@ class ConcurrentSequenceExecutorTests: XCTestCase { } func test_executeSequence_withNonTerminatingSequence_withTimeout_verifyAwaitTimeout() { - let executor = ConcurrentSequenceExecutor(name: "test_executeSequence_withNonTerminatingSequence_withTimeout_verifyAwaitTimeout") + let executor = ConcurrentSequenceExecutor(name: "test_executeSequence_withNonTerminatingSequence_withTimeout_verifyAwaitTimeout", shouldTrackTaskId: true) - let sequencedTask = MockSelfRepeatingTask { + let sequencedTask = MockSelfRepeatingTask(id: 123) { return 0 } let handle = executor.executeSequence(from: sequencedTask) { _, _ -> SequenceExecution in - return .continueSequence(MockSelfRepeatingTask { + return .continueSequence(MockSelfRepeatingTask(id: 123) { return 0 }) } @@ -138,27 +138,120 @@ class ConcurrentSequenceExecutorTests: XCTestCase { let startTime = CACurrentMediaTime() do { _ = try handle.await(withTimeout: 0.5) - } catch SequenceExecutionError.awaitTimeout { + } catch SequenceExecutionError.awaitTimeout(let id) { didThrowError = true let endTime = CACurrentMediaTime() XCTAssertTrue((endTime - startTime) >= 0.5) + XCTAssertEqual(id, 123) } catch { XCTFail("Incorrect error thrown: \(error)") } XCTAssertTrue(didThrowError) } + + func test_executeSequence_taskThrowsError_verifyError() { + let executor = ConcurrentSequenceExecutor(name: "test_executeSequence_withNonTerminatingSequence_withTimeout_verifyAwaitTimeout", shouldTrackTaskId: true) + + let throwTask = MockSelfRepeatingTask(id: 123) { + throw MockError.messagedError("bhdsfgqowfnjkbvnzxcvojqweofbn9823ry3h9g") + } + + let handle = executor.executeSequence(from: throwTask) { (_, result) -> SequenceExecution in + return .endOfSequence(result as! Int) + } + + do { + _ = try handle.await(withTimeout: nil) + XCTFail() + } catch { + switch error { + case MockError.messagedError(let message): + XCTAssertEqual(message, "bhdsfgqowfnjkbvnzxcvojqweofbn9823ry3h9g") + default: + XCTFail() + } + } + } + + func test_executeSequence_limitMaxConcurrentTasks_withSuccessTasks_verifyCompletion() { + let executor = ConcurrentSequenceExecutor(name: "test_executeSequence_withNonTerminatingSequence_withTimeout_verifyAwaitTimeout", maxConcurrentTasks: 1) + + let taskCount = AtomicInt(initialValue: 0) + let sequencedTask = MockSelfRepeatingTask(id: 123) { + return 0 + } + + let handle = executor.executeSequence(from: sequencedTask) { _, _ -> SequenceExecution in + let nextTask = MockSelfRepeatingTask(id: 123) { + return 0 + } + let newCount = taskCount.incrementAndGet() + if newCount > 10 { + return .endOfSequence(32838) + } else { + return .continueSequence(nextTask) + } + } + + do { + _ = try handle.await(withTimeout: 0.5) + } catch { + XCTFail() + } + } + + func test_executeSequence_limitMaxConcurrentTasks_withErrorTasks_verifyCompletion() { + let executor = ConcurrentSequenceExecutor(name: "test_executeSequence_withNonTerminatingSequence_withTimeout_verifyAwaitTimeout", maxConcurrentTasks: 1) + + let taskCount = AtomicInt(initialValue: 0) + let sequencedTask = MockSelfRepeatingTask(id: 123) { + return 0 + } + + let handle = executor.executeSequence(from: sequencedTask) { _, _ -> SequenceExecution in + let newCount = taskCount.incrementAndGet() + if newCount > 10 { + let errorTask = MockSelfRepeatingTask(id: 123) { + throw MockError.messagedError("ghasvhfjhbafjkh") + } + return .continueSequence(errorTask) + } else { + let nextTask = MockSelfRepeatingTask(id: 123) { + return 0 + } + return .continueSequence(nextTask) + } + } + + do { + _ = try handle.await(withTimeout: nil) + XCTFail() + } catch { + switch error { + case MockError.messagedError(let message): + XCTAssertEqual(message, "ghasvhfjhbafjkh") + default: + XCTFail() + } + } + } } class MockSelfRepeatingTask: AbstractTask { - private let execution: () -> Int + private let execution: () throws -> Int - init(execution: @escaping () -> Int) { + init(id: Int = nonTrackingDefaultTaskId, execution: @escaping () throws -> Int) { self.execution = execution + super.init(id: id) } - override func execute() -> Int { - return execution() + override func execute() throws -> Int { + return try execution() } } + +enum MockError: Error { + case messagedError(String) +}