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
-[](https://app.fossa.io/projects/git%2Bgithub.com%2Fuber%2Fswift-concurrency?ref=badge_shield)
+
+[](https://travis-ci.com/uber/swift-concurrency?branch=master)
+[](https://github.com/Carthage/Carthage)
+[](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
[](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)
+}