├── .gitignore
├── Atomic-OSX
└── Info.plist
├── Atomic.podspec
├── Atomic.xcodeproj
├── project.pbxproj
└── xcshareddata
│ └── xcschemes
│ └── Atomic.xcscheme
├── Atomic.xcworkspace
└── contents.xcworkspacedata
├── Atomic
├── Atomic.h
├── Atomic.swift
├── Info.plist
└── Lock.swift
├── AtomicTests
├── AtomicTests.swift
└── Info.plist
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | build/
4 | *.pbxuser
5 | !default.pbxuser
6 | *.mode1v3
7 | !default.mode1v3
8 | *.mode2v3
9 | !default.mode2v3
10 | *.perspectivev3
11 | !default.perspectivev3
12 | xcuserdata
13 | *.xccheckout
14 | *.moved-aside
15 | DerivedData
16 | *.hmap
17 | *.ipa
18 | *.xcuserstate
19 |
20 | # CocoaPods
21 | #
22 | # We recommend against adding the Pods directory to your .gitignore. However
23 | # you should judge for yourself, the pros and cons are mentioned at:
24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
25 | #
26 | # Pods/
27 |
28 | # Carthage
29 | #
30 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
31 | # Carthage/Checkouts
32 |
33 | Carthage/Build
34 |
--------------------------------------------------------------------------------
/Atomic-OSX/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Atomic.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = 'Atomic'
3 | s.version = '1.0.3'
4 | s.license = 'MIT'
5 | s.summary = 'Atomic is a fast, safe way to make values atomic (thread-safe).'
6 | s.homepage = 'https://github.com/Adlai-Holler/Atomic'
7 | s.social_media_url = 'http://twitter.com/adlaih'
8 | s.authors = { 'Adlai Holler' => 'him@adlai.io' }
9 | s.source = { :git => 'https://github.com/Adlai-Holler/Atomic.git', :tag => 'v1.0.3' }
10 |
11 | s.ios.deployment_target = '8.0'
12 | s.osx.deployment_target = '10.10'
13 |
14 | s.source_files = 'Atomic/*.swift'
15 |
16 | s.requires_arc = true
17 | end
18 |
--------------------------------------------------------------------------------
/Atomic.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | CC60355C1C136EE4003ED664 /* Atomic.h in Headers */ = {isa = PBXBuildFile; fileRef = CC60355B1C136EE4003ED664 /* Atomic.h */; settings = {ATTRIBUTES = (Public, ); }; };
11 | CC6035731C136EF2003ED664 /* Atomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC6035721C136EF2003ED664 /* Atomic.swift */; };
12 | CC649D681C14D6840085ADDE /* Atomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC6035721C136EF2003ED664 /* Atomic.swift */; };
13 | CC649D701C14D8E90085ADDE /* AtomicTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC649D6F1C14D8E90085ADDE /* AtomicTests.swift */; };
14 | CC649D721C14D8E90085ADDE /* Atomic.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC649D501C14D6500085ADDE /* Atomic.framework */; };
15 | CCDAC6C31C5F2D3700255715 /* Lock.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCDAC6C21C5F2D3700255715 /* Lock.swift */; };
16 | CCDAC6C41C5F2ECC00255715 /* Lock.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCDAC6C21C5F2D3700255715 /* Lock.swift */; };
17 | /* End PBXBuildFile section */
18 |
19 | /* Begin PBXContainerItemProxy section */
20 | CC649D731C14D8E90085ADDE /* PBXContainerItemProxy */ = {
21 | isa = PBXContainerItemProxy;
22 | containerPortal = CC60354F1C136EE4003ED664 /* Project object */;
23 | proxyType = 1;
24 | remoteGlobalIDString = CC649D4F1C14D6500085ADDE;
25 | remoteInfo = "Atomic-OSX";
26 | };
27 | /* End PBXContainerItemProxy section */
28 |
29 | /* Begin PBXFileReference section */
30 | CC6035581C136EE4003ED664 /* Atomic.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Atomic.framework; sourceTree = BUILT_PRODUCTS_DIR; };
31 | CC60355B1C136EE4003ED664 /* Atomic.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Atomic.h; sourceTree = ""; };
32 | CC60355D1C136EE4003ED664 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
33 | CC6035721C136EF2003ED664 /* Atomic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Atomic.swift; sourceTree = ""; };
34 | CC649D501C14D6500085ADDE /* Atomic.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Atomic.framework; sourceTree = BUILT_PRODUCTS_DIR; };
35 | CC649D6D1C14D8E90085ADDE /* AtomicTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AtomicTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
36 | CC649D6F1C14D8E90085ADDE /* AtomicTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AtomicTests.swift; sourceTree = ""; };
37 | CC649D711C14D8E90085ADDE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
38 | CCDAC6C21C5F2D3700255715 /* Lock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Lock.swift; sourceTree = ""; };
39 | /* End PBXFileReference section */
40 |
41 | /* Begin PBXFrameworksBuildPhase section */
42 | CC6035541C136EE4003ED664 /* Frameworks */ = {
43 | isa = PBXFrameworksBuildPhase;
44 | buildActionMask = 2147483647;
45 | files = (
46 | );
47 | runOnlyForDeploymentPostprocessing = 0;
48 | };
49 | CC649D4C1C14D6500085ADDE /* Frameworks */ = {
50 | isa = PBXFrameworksBuildPhase;
51 | buildActionMask = 2147483647;
52 | files = (
53 | );
54 | runOnlyForDeploymentPostprocessing = 0;
55 | };
56 | CC649D6A1C14D8E90085ADDE /* Frameworks */ = {
57 | isa = PBXFrameworksBuildPhase;
58 | buildActionMask = 2147483647;
59 | files = (
60 | CC649D721C14D8E90085ADDE /* Atomic.framework in Frameworks */,
61 | );
62 | runOnlyForDeploymentPostprocessing = 0;
63 | };
64 | /* End PBXFrameworksBuildPhase section */
65 |
66 | /* Begin PBXGroup section */
67 | CC60354E1C136EE4003ED664 = {
68 | isa = PBXGroup;
69 | children = (
70 | CC60355A1C136EE4003ED664 /* Atomic */,
71 | CC649D6E1C14D8E90085ADDE /* AtomicTests */,
72 | CC6035591C136EE4003ED664 /* Products */,
73 | );
74 | sourceTree = "";
75 | };
76 | CC6035591C136EE4003ED664 /* Products */ = {
77 | isa = PBXGroup;
78 | children = (
79 | CC6035581C136EE4003ED664 /* Atomic.framework */,
80 | CC649D501C14D6500085ADDE /* Atomic.framework */,
81 | CC649D6D1C14D8E90085ADDE /* AtomicTests.xctest */,
82 | );
83 | name = Products;
84 | sourceTree = "";
85 | };
86 | CC60355A1C136EE4003ED664 /* Atomic */ = {
87 | isa = PBXGroup;
88 | children = (
89 | CC60355B1C136EE4003ED664 /* Atomic.h */,
90 | CC6035721C136EF2003ED664 /* Atomic.swift */,
91 | CCDAC6C21C5F2D3700255715 /* Lock.swift */,
92 | CC60355D1C136EE4003ED664 /* Info.plist */,
93 | );
94 | path = Atomic;
95 | sourceTree = "";
96 | };
97 | CC649D6E1C14D8E90085ADDE /* AtomicTests */ = {
98 | isa = PBXGroup;
99 | children = (
100 | CC649D6F1C14D8E90085ADDE /* AtomicTests.swift */,
101 | CC649D711C14D8E90085ADDE /* Info.plist */,
102 | );
103 | path = AtomicTests;
104 | sourceTree = "";
105 | };
106 | /* End PBXGroup section */
107 |
108 | /* Begin PBXHeadersBuildPhase section */
109 | CC6035551C136EE4003ED664 /* Headers */ = {
110 | isa = PBXHeadersBuildPhase;
111 | buildActionMask = 2147483647;
112 | files = (
113 | CC60355C1C136EE4003ED664 /* Atomic.h in Headers */,
114 | );
115 | runOnlyForDeploymentPostprocessing = 0;
116 | };
117 | CC649D4D1C14D6500085ADDE /* Headers */ = {
118 | isa = PBXHeadersBuildPhase;
119 | buildActionMask = 2147483647;
120 | files = (
121 | );
122 | runOnlyForDeploymentPostprocessing = 0;
123 | };
124 | /* End PBXHeadersBuildPhase section */
125 |
126 | /* Begin PBXNativeTarget section */
127 | CC6035571C136EE4003ED664 /* Atomic */ = {
128 | isa = PBXNativeTarget;
129 | buildConfigurationList = CC60356C1C136EE4003ED664 /* Build configuration list for PBXNativeTarget "Atomic" */;
130 | buildPhases = (
131 | CC6035531C136EE4003ED664 /* Sources */,
132 | CC6035541C136EE4003ED664 /* Frameworks */,
133 | CC6035551C136EE4003ED664 /* Headers */,
134 | CC6035561C136EE4003ED664 /* Resources */,
135 | );
136 | buildRules = (
137 | );
138 | dependencies = (
139 | );
140 | name = Atomic;
141 | productName = Atomic;
142 | productReference = CC6035581C136EE4003ED664 /* Atomic.framework */;
143 | productType = "com.apple.product-type.framework";
144 | };
145 | CC649D4F1C14D6500085ADDE /* Atomic-OSX */ = {
146 | isa = PBXNativeTarget;
147 | buildConfigurationList = CC649D651C14D6500085ADDE /* Build configuration list for PBXNativeTarget "Atomic-OSX" */;
148 | buildPhases = (
149 | CC649D4B1C14D6500085ADDE /* Sources */,
150 | CC649D4C1C14D6500085ADDE /* Frameworks */,
151 | CC649D4D1C14D6500085ADDE /* Headers */,
152 | CC649D4E1C14D6500085ADDE /* Resources */,
153 | );
154 | buildRules = (
155 | );
156 | dependencies = (
157 | );
158 | name = "Atomic-OSX";
159 | productName = "Atomic-OSX";
160 | productReference = CC649D501C14D6500085ADDE /* Atomic.framework */;
161 | productType = "com.apple.product-type.framework";
162 | };
163 | CC649D6C1C14D8E90085ADDE /* AtomicTests */ = {
164 | isa = PBXNativeTarget;
165 | buildConfigurationList = CC649D751C14D8E90085ADDE /* Build configuration list for PBXNativeTarget "AtomicTests" */;
166 | buildPhases = (
167 | CC649D691C14D8E90085ADDE /* Sources */,
168 | CC649D6A1C14D8E90085ADDE /* Frameworks */,
169 | CC649D6B1C14D8E90085ADDE /* Resources */,
170 | );
171 | buildRules = (
172 | );
173 | dependencies = (
174 | CC649D741C14D8E90085ADDE /* PBXTargetDependency */,
175 | );
176 | name = AtomicTests;
177 | productName = AtomicTests;
178 | productReference = CC649D6D1C14D8E90085ADDE /* AtomicTests.xctest */;
179 | productType = "com.apple.product-type.bundle.unit-test";
180 | };
181 | /* End PBXNativeTarget section */
182 |
183 | /* Begin PBXProject section */
184 | CC60354F1C136EE4003ED664 /* Project object */ = {
185 | isa = PBXProject;
186 | attributes = {
187 | LastSwiftUpdateCheck = 0710;
188 | LastUpgradeCheck = 0710;
189 | ORGANIZATIONNAME = "Adlai Holler";
190 | TargetAttributes = {
191 | CC6035571C136EE4003ED664 = {
192 | CreatedOnToolsVersion = 7.1.1;
193 | };
194 | CC649D4F1C14D6500085ADDE = {
195 | CreatedOnToolsVersion = 7.1.1;
196 | };
197 | CC649D6C1C14D8E90085ADDE = {
198 | CreatedOnToolsVersion = 7.1.1;
199 | };
200 | };
201 | };
202 | buildConfigurationList = CC6035521C136EE4003ED664 /* Build configuration list for PBXProject "Atomic" */;
203 | compatibilityVersion = "Xcode 3.2";
204 | developmentRegion = English;
205 | hasScannedForEncodings = 0;
206 | knownRegions = (
207 | en,
208 | );
209 | mainGroup = CC60354E1C136EE4003ED664;
210 | productRefGroup = CC6035591C136EE4003ED664 /* Products */;
211 | projectDirPath = "";
212 | projectRoot = "";
213 | targets = (
214 | CC6035571C136EE4003ED664 /* Atomic */,
215 | CC649D4F1C14D6500085ADDE /* Atomic-OSX */,
216 | CC649D6C1C14D8E90085ADDE /* AtomicTests */,
217 | );
218 | };
219 | /* End PBXProject section */
220 |
221 | /* Begin PBXResourcesBuildPhase section */
222 | CC6035561C136EE4003ED664 /* Resources */ = {
223 | isa = PBXResourcesBuildPhase;
224 | buildActionMask = 2147483647;
225 | files = (
226 | );
227 | runOnlyForDeploymentPostprocessing = 0;
228 | };
229 | CC649D4E1C14D6500085ADDE /* Resources */ = {
230 | isa = PBXResourcesBuildPhase;
231 | buildActionMask = 2147483647;
232 | files = (
233 | );
234 | runOnlyForDeploymentPostprocessing = 0;
235 | };
236 | CC649D6B1C14D8E90085ADDE /* Resources */ = {
237 | isa = PBXResourcesBuildPhase;
238 | buildActionMask = 2147483647;
239 | files = (
240 | );
241 | runOnlyForDeploymentPostprocessing = 0;
242 | };
243 | /* End PBXResourcesBuildPhase section */
244 |
245 | /* Begin PBXSourcesBuildPhase section */
246 | CC6035531C136EE4003ED664 /* Sources */ = {
247 | isa = PBXSourcesBuildPhase;
248 | buildActionMask = 2147483647;
249 | files = (
250 | CCDAC6C31C5F2D3700255715 /* Lock.swift in Sources */,
251 | CC6035731C136EF2003ED664 /* Atomic.swift in Sources */,
252 | );
253 | runOnlyForDeploymentPostprocessing = 0;
254 | };
255 | CC649D4B1C14D6500085ADDE /* Sources */ = {
256 | isa = PBXSourcesBuildPhase;
257 | buildActionMask = 2147483647;
258 | files = (
259 | CCDAC6C41C5F2ECC00255715 /* Lock.swift in Sources */,
260 | CC649D681C14D6840085ADDE /* Atomic.swift in Sources */,
261 | );
262 | runOnlyForDeploymentPostprocessing = 0;
263 | };
264 | CC649D691C14D8E90085ADDE /* Sources */ = {
265 | isa = PBXSourcesBuildPhase;
266 | buildActionMask = 2147483647;
267 | files = (
268 | CC649D701C14D8E90085ADDE /* AtomicTests.swift in Sources */,
269 | );
270 | runOnlyForDeploymentPostprocessing = 0;
271 | };
272 | /* End PBXSourcesBuildPhase section */
273 |
274 | /* Begin PBXTargetDependency section */
275 | CC649D741C14D8E90085ADDE /* PBXTargetDependency */ = {
276 | isa = PBXTargetDependency;
277 | target = CC649D4F1C14D6500085ADDE /* Atomic-OSX */;
278 | targetProxy = CC649D731C14D8E90085ADDE /* PBXContainerItemProxy */;
279 | };
280 | /* End PBXTargetDependency section */
281 |
282 | /* Begin XCBuildConfiguration section */
283 | CC60356A1C136EE4003ED664 /* Debug */ = {
284 | isa = XCBuildConfiguration;
285 | buildSettings = {
286 | ALWAYS_SEARCH_USER_PATHS = NO;
287 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
288 | CLANG_CXX_LIBRARY = "libc++";
289 | CLANG_ENABLE_MODULES = YES;
290 | CLANG_ENABLE_OBJC_ARC = YES;
291 | CLANG_WARN_BOOL_CONVERSION = YES;
292 | CLANG_WARN_CONSTANT_CONVERSION = YES;
293 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
294 | CLANG_WARN_EMPTY_BODY = YES;
295 | CLANG_WARN_ENUM_CONVERSION = YES;
296 | CLANG_WARN_INT_CONVERSION = YES;
297 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
298 | CLANG_WARN_UNREACHABLE_CODE = YES;
299 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
300 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
301 | COPY_PHASE_STRIP = NO;
302 | CURRENT_PROJECT_VERSION = 1;
303 | DEBUG_INFORMATION_FORMAT = dwarf;
304 | ENABLE_STRICT_OBJC_MSGSEND = YES;
305 | ENABLE_TESTABILITY = YES;
306 | GCC_C_LANGUAGE_STANDARD = gnu99;
307 | GCC_DYNAMIC_NO_PIC = NO;
308 | GCC_NO_COMMON_BLOCKS = YES;
309 | GCC_OPTIMIZATION_LEVEL = 0;
310 | GCC_PREPROCESSOR_DEFINITIONS = (
311 | "DEBUG=1",
312 | "$(inherited)",
313 | );
314 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
315 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
316 | GCC_WARN_UNDECLARED_SELECTOR = YES;
317 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
318 | GCC_WARN_UNUSED_FUNCTION = YES;
319 | GCC_WARN_UNUSED_VARIABLE = YES;
320 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
321 | MTL_ENABLE_DEBUG_INFO = YES;
322 | ONLY_ACTIVE_ARCH = YES;
323 | SDKROOT = iphoneos;
324 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
325 | TARGETED_DEVICE_FAMILY = "1,2";
326 | VERSIONING_SYSTEM = "apple-generic";
327 | VERSION_INFO_PREFIX = "";
328 | };
329 | name = Debug;
330 | };
331 | CC60356B1C136EE4003ED664 /* Release */ = {
332 | isa = XCBuildConfiguration;
333 | buildSettings = {
334 | ALWAYS_SEARCH_USER_PATHS = NO;
335 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
336 | CLANG_CXX_LIBRARY = "libc++";
337 | CLANG_ENABLE_MODULES = YES;
338 | CLANG_ENABLE_OBJC_ARC = YES;
339 | CLANG_WARN_BOOL_CONVERSION = YES;
340 | CLANG_WARN_CONSTANT_CONVERSION = YES;
341 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
342 | CLANG_WARN_EMPTY_BODY = YES;
343 | CLANG_WARN_ENUM_CONVERSION = YES;
344 | CLANG_WARN_INT_CONVERSION = YES;
345 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
346 | CLANG_WARN_UNREACHABLE_CODE = YES;
347 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
348 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
349 | COPY_PHASE_STRIP = NO;
350 | CURRENT_PROJECT_VERSION = 1;
351 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
352 | ENABLE_NS_ASSERTIONS = NO;
353 | ENABLE_STRICT_OBJC_MSGSEND = YES;
354 | GCC_C_LANGUAGE_STANDARD = gnu99;
355 | GCC_NO_COMMON_BLOCKS = YES;
356 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
357 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
358 | GCC_WARN_UNDECLARED_SELECTOR = YES;
359 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
360 | GCC_WARN_UNUSED_FUNCTION = YES;
361 | GCC_WARN_UNUSED_VARIABLE = YES;
362 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
363 | MTL_ENABLE_DEBUG_INFO = NO;
364 | SDKROOT = iphoneos;
365 | TARGETED_DEVICE_FAMILY = "1,2";
366 | VALIDATE_PRODUCT = YES;
367 | VERSIONING_SYSTEM = "apple-generic";
368 | VERSION_INFO_PREFIX = "";
369 | };
370 | name = Release;
371 | };
372 | CC60356D1C136EE4003ED664 /* Debug */ = {
373 | isa = XCBuildConfiguration;
374 | buildSettings = {
375 | CLANG_ENABLE_MODULES = YES;
376 | DEFINES_MODULE = YES;
377 | DYLIB_COMPATIBILITY_VERSION = 1;
378 | DYLIB_CURRENT_VERSION = 1;
379 | DYLIB_INSTALL_NAME_BASE = "@rpath";
380 | INFOPLIST_FILE = Atomic/Info.plist;
381 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
382 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
383 | PRODUCT_BUNDLE_IDENTIFIER = adlai.Atomic;
384 | PRODUCT_NAME = "$(TARGET_NAME)";
385 | SKIP_INSTALL = YES;
386 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
387 | };
388 | name = Debug;
389 | };
390 | CC60356E1C136EE4003ED664 /* Release */ = {
391 | isa = XCBuildConfiguration;
392 | buildSettings = {
393 | CLANG_ENABLE_MODULES = YES;
394 | DEFINES_MODULE = YES;
395 | DYLIB_COMPATIBILITY_VERSION = 1;
396 | DYLIB_CURRENT_VERSION = 1;
397 | DYLIB_INSTALL_NAME_BASE = "@rpath";
398 | INFOPLIST_FILE = Atomic/Info.plist;
399 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
400 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
401 | PRODUCT_BUNDLE_IDENTIFIER = adlai.Atomic;
402 | PRODUCT_NAME = "$(TARGET_NAME)";
403 | SKIP_INSTALL = YES;
404 | };
405 | name = Release;
406 | };
407 | CC649D611C14D6500085ADDE /* Debug */ = {
408 | isa = XCBuildConfiguration;
409 | buildSettings = {
410 | CODE_SIGN_IDENTITY = "-";
411 | COMBINE_HIDPI_IMAGES = YES;
412 | DEFINES_MODULE = YES;
413 | DYLIB_COMPATIBILITY_VERSION = 1;
414 | DYLIB_CURRENT_VERSION = 1;
415 | DYLIB_INSTALL_NAME_BASE = "@rpath";
416 | FRAMEWORK_VERSION = A;
417 | INFOPLIST_FILE = "Atomic-OSX/Info.plist";
418 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
419 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
420 | MACOSX_DEPLOYMENT_TARGET = 10.11;
421 | PRODUCT_BUNDLE_IDENTIFIER = "adlai.Atomic-OSX";
422 | PRODUCT_NAME = "$(PROJECT_NAME)";
423 | SDKROOT = macosx;
424 | SKIP_INSTALL = YES;
425 | };
426 | name = Debug;
427 | };
428 | CC649D621C14D6500085ADDE /* Release */ = {
429 | isa = XCBuildConfiguration;
430 | buildSettings = {
431 | CODE_SIGN_IDENTITY = "-";
432 | COMBINE_HIDPI_IMAGES = YES;
433 | DEFINES_MODULE = YES;
434 | DYLIB_COMPATIBILITY_VERSION = 1;
435 | DYLIB_CURRENT_VERSION = 1;
436 | DYLIB_INSTALL_NAME_BASE = "@rpath";
437 | FRAMEWORK_VERSION = A;
438 | INFOPLIST_FILE = "Atomic-OSX/Info.plist";
439 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
440 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
441 | MACOSX_DEPLOYMENT_TARGET = 10.11;
442 | PRODUCT_BUNDLE_IDENTIFIER = "adlai.Atomic-OSX";
443 | PRODUCT_NAME = "$(PROJECT_NAME)";
444 | SDKROOT = macosx;
445 | SKIP_INSTALL = YES;
446 | };
447 | name = Release;
448 | };
449 | CC649D761C14D8E90085ADDE /* Debug */ = {
450 | isa = XCBuildConfiguration;
451 | buildSettings = {
452 | CODE_SIGN_IDENTITY = "-";
453 | COMBINE_HIDPI_IMAGES = YES;
454 | INFOPLIST_FILE = AtomicTests/Info.plist;
455 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
456 | MACOSX_DEPLOYMENT_TARGET = 10.11;
457 | PRODUCT_BUNDLE_IDENTIFIER = adlai.AtomicTests;
458 | PRODUCT_NAME = "$(TARGET_NAME)";
459 | SDKROOT = macosx;
460 | };
461 | name = Debug;
462 | };
463 | CC649D771C14D8E90085ADDE /* Release */ = {
464 | isa = XCBuildConfiguration;
465 | buildSettings = {
466 | CODE_SIGN_IDENTITY = "-";
467 | COMBINE_HIDPI_IMAGES = YES;
468 | INFOPLIST_FILE = AtomicTests/Info.plist;
469 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
470 | MACOSX_DEPLOYMENT_TARGET = 10.11;
471 | PRODUCT_BUNDLE_IDENTIFIER = adlai.AtomicTests;
472 | PRODUCT_NAME = "$(TARGET_NAME)";
473 | SDKROOT = macosx;
474 | };
475 | name = Release;
476 | };
477 | /* End XCBuildConfiguration section */
478 |
479 | /* Begin XCConfigurationList section */
480 | CC6035521C136EE4003ED664 /* Build configuration list for PBXProject "Atomic" */ = {
481 | isa = XCConfigurationList;
482 | buildConfigurations = (
483 | CC60356A1C136EE4003ED664 /* Debug */,
484 | CC60356B1C136EE4003ED664 /* Release */,
485 | );
486 | defaultConfigurationIsVisible = 0;
487 | defaultConfigurationName = Release;
488 | };
489 | CC60356C1C136EE4003ED664 /* Build configuration list for PBXNativeTarget "Atomic" */ = {
490 | isa = XCConfigurationList;
491 | buildConfigurations = (
492 | CC60356D1C136EE4003ED664 /* Debug */,
493 | CC60356E1C136EE4003ED664 /* Release */,
494 | );
495 | defaultConfigurationIsVisible = 0;
496 | defaultConfigurationName = Release;
497 | };
498 | CC649D651C14D6500085ADDE /* Build configuration list for PBXNativeTarget "Atomic-OSX" */ = {
499 | isa = XCConfigurationList;
500 | buildConfigurations = (
501 | CC649D611C14D6500085ADDE /* Debug */,
502 | CC649D621C14D6500085ADDE /* Release */,
503 | );
504 | defaultConfigurationIsVisible = 0;
505 | defaultConfigurationName = Release;
506 | };
507 | CC649D751C14D8E90085ADDE /* Build configuration list for PBXNativeTarget "AtomicTests" */ = {
508 | isa = XCConfigurationList;
509 | buildConfigurations = (
510 | CC649D761C14D8E90085ADDE /* Debug */,
511 | CC649D771C14D8E90085ADDE /* Release */,
512 | );
513 | defaultConfigurationIsVisible = 0;
514 | defaultConfigurationName = Release;
515 | };
516 | /* End XCConfigurationList section */
517 | };
518 | rootObject = CC60354F1C136EE4003ED664 /* Project object */;
519 | }
520 |
--------------------------------------------------------------------------------
/Atomic.xcodeproj/xcshareddata/xcschemes/Atomic.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
55 |
61 |
62 |
63 |
64 |
65 |
66 |
72 |
73 |
79 |
80 |
81 |
82 |
84 |
85 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/Atomic.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Atomic/Atomic.h:
--------------------------------------------------------------------------------
1 | //
2 | // Atomic.h
3 | // Atomic
4 | //
5 | // Created by Adlai Holler on 12/5/15.
6 | // Copyright © 2015 Adlai Holler. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for Atomic.
12 | FOUNDATION_EXPORT double AtomicVersionNumber;
13 |
14 | //! Project version string for Atomic.
15 | FOUNDATION_EXPORT const unsigned char AtomicVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Atomic/Atomic.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Atomic.swift
3 | // Atomic
4 | //
5 | // Adapted from Atomic.swift in ReactiveCocoa.
6 | // Original file is by Justin Spahr-Summers 2014-06-10.
7 | //
8 |
9 | import Foundation
10 |
11 | /// An atomic variable.
12 | public final class Atomic {
13 | internal let lock = Lock()
14 | internal var _value: Value
15 |
16 | /// Atomically gets or sets the value of the variable.
17 | public var value: Value {
18 | get {
19 | return lock.withCriticalScope {
20 | _value
21 | }
22 | }
23 |
24 | set(newValue) {
25 | lock.withCriticalScope {
26 | _value = newValue
27 | }
28 | }
29 | }
30 |
31 | /// Initializes the variable with the given initial value.
32 | public init(_ value: Value) {
33 | _value = value
34 | }
35 |
36 |
37 | /// Atomically replaces the contents of the variable.
38 | ///
39 | /// Returns the old value.
40 | public func swap(newValue: Value) -> Value {
41 | return modify { _ in newValue }
42 | }
43 |
44 | /// Atomically modifies the variable.
45 | ///
46 | /// Returns the old value.
47 | public func modify(@noescape action: (Value) throws -> Value) rethrows -> Value {
48 | return try lock.withCriticalScope {
49 | let oldValue = _value
50 | _value = try action(_value)
51 | return oldValue
52 | }
53 | }
54 |
55 | /// Atomically performs an arbitrary action using the current value of the
56 | /// variable.
57 | ///
58 | /// Returns the result of the action.
59 | public func withValue(@noescape action: (Value) throws -> Result) rethrows -> Result {
60 | return try lock.withCriticalScope {
61 | try action(_value)
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Atomic/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Atomic/Lock.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Lock.swift
3 | // Atomic
4 | //
5 | // Created by Adlai Holler on 1/31/16.
6 | // Copyright © 2016 Adlai Holler. All rights reserved.
7 | //
8 |
9 | import Darwin
10 |
11 | final public class Lock {
12 | internal var _lock = pthread_mutex_t()
13 |
14 | /// Initializes the variable with the given initial value.
15 | public init() {
16 | let result = pthread_mutex_init(&_lock, nil)
17 | assert(result == 0, "Failed to init mutex in \(self)")
18 | }
19 |
20 | public func lock() {
21 | let result = pthread_mutex_lock(&_lock)
22 | assert(result == 0, "Failed to lock mutex in \(self)")
23 | }
24 |
25 | public func tryLock() -> Int32 {
26 | return pthread_mutex_trylock(&_lock)
27 | }
28 |
29 | public func unlock() {
30 | let result = pthread_mutex_unlock(&_lock)
31 | assert(result == 0, "Failed to unlock mutex in \(self)")
32 | }
33 |
34 | deinit {
35 | let result = pthread_mutex_destroy(&_lock)
36 | assert(result == 0, "Failed to destroy mutex in \(self)")
37 | }
38 |
39 | }
40 |
41 | extension Lock {
42 | public func withCriticalScope(@noescape body: () throws -> Result) rethrows -> Result {
43 | lock()
44 | defer { unlock() }
45 | return try body()
46 | }
47 | }
--------------------------------------------------------------------------------
/AtomicTests/AtomicTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AtomicTests.swift
3 | // AtomicTests
4 | //
5 | // Created by Adlai Holler on 12/5/15.
6 | // Copyright © 2015 Adlai Holler. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import Atomic
11 |
12 | class AtomicTests: XCTestCase {
13 |
14 | func testModify() {
15 | let atomic = Atomic(0)
16 | atomic.modify { $0 + 7 }
17 | XCTAssertEqual(atomic._value, 7)
18 | }
19 |
20 | func testWithValue() {
21 | let atomic = Atomic(0)
22 | let result = atomic.withValue { $0 + 7 }
23 | XCTAssertEqual(atomic._value, 0)
24 | XCTAssertEqual(result, 7)
25 | }
26 |
27 | func testSetProperty() {
28 | let atomic = Atomic(0)
29 | atomic.value = 25
30 | XCTAssertEqual(atomic._value, 25)
31 | }
32 |
33 | func testGetProperty() {
34 | let atomic = Atomic(0)
35 | atomic._value = 25
36 | XCTAssertEqual(atomic.value, 25)
37 | }
38 |
39 | func testSwap() {
40 | let atomic = Atomic(1)
41 | let oldValue = atomic.swap(25)
42 | XCTAssertEqual(oldValue, 1)
43 | XCTAssertEqual(atomic._value, 25)
44 | }
45 |
46 | func testRethrowFromWithValue() {
47 | let atomic = Atomic(10)
48 | var didCatch = false
49 | do {
50 | try atomic.withValue { value in
51 | throw NSError(domain: NSCocoaErrorDomain, code: value, userInfo: nil)
52 | }
53 | XCTFail()
54 | } catch let error as NSError {
55 | didCatch = true
56 | XCTAssertEqual(error, NSError(domain: NSCocoaErrorDomain, code: 10, userInfo: nil))
57 | }
58 | if atomic.lock.tryLock() == 0 {
59 | atomic.lock.unlock()
60 | } else {
61 | XCTFail()
62 | }
63 | XCTAssert(didCatch)
64 | }
65 |
66 | func testRethrowFromModify() {
67 | let atomic = Atomic(10)
68 | var didCatch = false
69 | do {
70 | try atomic.modify { value in
71 | throw NSError(domain: NSCocoaErrorDomain, code: value, userInfo: nil)
72 | }
73 | XCTFail()
74 | } catch let error as NSError {
75 | didCatch = true
76 | XCTAssertEqual(error, NSError(domain: NSCocoaErrorDomain, code: 10, userInfo: nil))
77 | }
78 | if atomic.lock.tryLock() == 0 {
79 | atomic.lock.unlock()
80 | } else {
81 | XCTFail()
82 | }
83 | XCTAssert(didCatch)
84 | }
85 |
86 | func testHighlyContestedLocking() {
87 | let contestedAtomic = Atomic(0)
88 | let concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
89 | let dispatchGroup = dispatch_group_create()
90 | let count = 100_000
91 | for _ in 0..
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Adlai Holler
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Atomic
2 | [](https://github.com/Carthage/Carthage) [](https://cocoapods.org) [](https://cocoapods.org)
3 |
4 | Atomic is a fast, safe class for making values thread-safe in Swift. It is backed by `pthread_mutex_lock` which is the fastest, most-efficient locking mechanism available.
5 |
6 | ### Installation
7 |
8 | - Using [CocoaPods](https://cocoapods.org) by adding `pod Atomic` to your Podfile
9 | - Using [Carthage](https://github.com/Carthage/Carthage) by adding `github "Adlai-Holler/Atomic"` to your Cartfile.
10 |
11 | ### How to Use
12 |
13 | ```swift
14 | /// This class is completely thread-safe (yay!).
15 | final class MyCache {
16 | private let entries: Atomic<[String: Value]> = Atomic([:])
17 |
18 | func valueForKey(key: String) -> Value? {
19 | return entries.withValue { $0[key] }
20 | }
21 |
22 | func setValue(value: Value, forKey: Key) {
23 | entries.modify { (var dict) in
24 | dict[key] = value
25 | return dict
26 | }
27 | }
28 |
29 | func clear() {
30 | entries.value = [:]
31 | }
32 |
33 | func copy() -> [String: Value] {
34 | return entries.value
35 | }
36 | }
37 | ```
38 |
39 | #### Another Example
40 |
41 | ```swift
42 | /// Thread-safe manager for the `networkActivityIndicator` on iOS.
43 | final class NetworkActivityIndicatorManager {
44 | static let shared = NetworkActivityIndicatorManager()
45 |
46 | private let count = Atomic(0)
47 |
48 | func incrementActivityCount() {
49 | let oldValue = count.modify { $0 + 1 }
50 | if oldValue == 0 {
51 | updateUI(true)
52 | }
53 | }
54 |
55 | func decrementActivityCount() {
56 | let oldValue = count.modify { $0 - 1 }
57 | if oldValue == 1 {
58 | updateUI(false)
59 | }
60 | }
61 |
62 | private func updateUI(on: Bool) {
63 | dispatch_async(dispatch_get_main_queue()) {
64 | UIApplication.sharedApplication().networkActivityIndicatorVisible = true
65 | }
66 | }
67 | }
68 | ```
69 |
70 | ### Features
71 |
72 | - Safe. No need to remember to unlock.
73 | - Fast. `pthread_mutex_lock` is faster than `NSLock` and more efficient than `OSSpinLock`.
74 | - Modern. You can safely `throw` errors inside its methods, uses `@noescape` and generics to make your code as clean as possible.
75 | - Tested. This thing is tested like crazy, including accessing it concurrently from 100,000 operations!
76 |
77 | ### Attribution
78 |
79 | The original version of `Atomic.swift` was written by the [ReactiveCocoa](https://github.com/ReactiveCocoa/ReactiveCocoa) contributors.
80 |
--------------------------------------------------------------------------------