├── .gitignore ├── LICENSE ├── LICENSE.zh_CN ├── Package.swift ├── README.md ├── README.zh_CN.md ├── Sources └── PerfectThread │ ├── Promise.swift │ ├── ThreadQueue.swift │ └── Threading.swift ├── Tests ├── LinuxMain.swift └── PerfectThreadTests │ └── PerfectThreadTests.swift └── docs ├── Protocols.html ├── Protocols └── ThreadQueue.html ├── Structs.html ├── Structs ├── Threading.html └── Threading │ ├── Event.html │ ├── Lock.html │ ├── QueueType.html │ └── RWLock.html ├── css ├── highlight.css └── jazzy.css ├── docsets ├── .docset │ └── Contents │ │ ├── Info.plist │ │ └── Resources │ │ ├── Documents │ │ ├── Protocols.html │ │ ├── Protocols │ │ │ └── ThreadQueue.html │ │ ├── Structs.html │ │ ├── Structs │ │ │ ├── Threading.html │ │ │ └── Threading │ │ │ │ ├── Event.html │ │ │ │ ├── Lock.html │ │ │ │ ├── QueueType.html │ │ │ │ └── RWLock.html │ │ ├── css │ │ │ ├── highlight.css │ │ │ └── jazzy.css │ │ ├── img │ │ │ ├── carat.png │ │ │ ├── dash.png │ │ │ └── gh.png │ │ ├── index.html │ │ ├── js │ │ │ ├── jazzy.js │ │ │ └── jquery.min.js │ │ └── undocumented.json │ │ └── docSet.dsidx └── .tgz ├── img ├── carat.png ├── dash.png └── gh.png ├── index.html ├── js ├── jazzy.js └── jquery.min.js └── undocumented.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata 19 | 20 | ## Other 21 | *.xccheckout 22 | *.moved-aside 23 | *.xcuserstate 24 | *.xcscmblueprint 25 | 26 | ## Obj-C/Swift specific 27 | *.hmap 28 | *.ipa 29 | 30 | ## Playgrounds 31 | timeline.xctimeline 32 | playground.xcworkspace 33 | 34 | # Swift Package Manager 35 | # 36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 37 | # Packages/ 38 | .build/ 39 | 40 | # CocoaPods 41 | # 42 | # We recommend against adding the Pods directory to your .gitignore. However 43 | # you should judge for yourself, the pros and cons are mentioned at: 44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 45 | # 46 | # Pods/ 47 | 48 | # Carthage 49 | # 50 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 51 | # Carthage/Checkouts 52 | 53 | Carthage/Build 54 | 55 | # fastlane 56 | # 57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 58 | # screenshots whenever they are needed. 59 | # For more information about the recommended setup visit: 60 | # https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md 61 | 62 | fastlane/report.xml 63 | fastlane/screenshots 64 | 65 | Package/ 66 | PerfectThread.xcodeproj/ 67 | .DS_Store 68 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE.zh_CN: -------------------------------------------------------------------------------- 1 | Apache许可证 2 | 2.0版 2004年1月 3 | http://www.apache.org/licenses/ 4 | 5 | 关于使用、复制和分发的条款 6 | 7 | 定义 8 | "许可证"是指根据本文件第1到第9部分关于使用、复制和分发的条款。 9 | 10 | "许可证颁发者"是指版权所有者或者由版权所有者授权许可证的实体。 11 | 12 | "法律实体"是指实施实体和进行控制的所有其它实体受该实体控制,或者受该实体集中控制。根据此定义,"控制"是指(i)让无论是否签订协议的上述实体,进行指导或管理的直接权利或间接权利,或者(ii)拥有百分之五十(50%)或以上已发行股票的所有者,或者(iii)上述实体的实权所有者。 13 | 14 | "用户"(或"用户的")是指行使本许可证所授予权限的个人或法律实体。 15 | 16 | "源程序"形式是指对包括但不限于软件源代码、文件源程序和配置文件进行修改的首选形式。 17 | 18 | "目标"形式是指对源程序形式进行机械转换或翻译的任何形式,包括但不限于对编译的目标代码,生成的文件以及转换为其它媒体类型。 19 | 20 | "作品"是指根据本许可证所制作的源程序形式或目标形式的著作,在著作中包含的或附加的版权通知(在下面附录中提供了一个示例)。 21 | 22 | "衍生作品"是指基于作品(或从作品衍生而来)的源程序形式或目标形式的任何作品,以及编辑修订、注释、详细描述或其它修订等构成原创著作作品的整体。根据本许可证,衍生作品不得包括与作品及其衍生作品分离之作品,或仅与作品及其衍生作品的接口相链接(或按名称结合)之作品。 23 | 24 | "贡献"是指任何著作作品,包括作品的原始版本和对该作品或衍生作品所做的任何修订或补充,意在提交给许可证颁发者以让版权所有者或代表版权所有者的授权个人或法律实体包含在其作品中。根据此定义,"提交"一词表示发送给许可证颁发者或其代表人,任何电子的、口头的或书面的交流信息形式,包括但不限于在由许可证颁发者或者代表其管理的电子邮件清单、源代码控制系统、以及发布跟踪系统上为讨论和提高作品的交流,但不包括由版权所有者以书面形式明显标注或指定为"非贡献"的交流活动。 25 | 26 | "贡献者"是指许可证颁发者和代表从许可证颁发者接受之贡献的并随后包含在作品之贡献中的任何个人或法律实体。 27 | 28 | 版权许可证的授予。根据本许可证的条款,每个贡献者授予用户永久性的、全球性的、非专有性的、免费的、无版权费的、不可撤销的版权许可证以源程序形式或目标形式复制、准备衍生作品、公开显示、公开执行、授予分许可证、以及分发作品和这样的衍生作品。 29 | 专利许可证的授予。根据本许可证的条款,每个贡献者授予用户永久性的、全球性的、非专有性的、免费的、无版权费的、不可撤销的(除在本部分进行说明)专利许可证对作品进行制作、让人制作、使用、提供销售、销售、进口和其它转让,且这样的许可证仅适用于在所递交作品的贡献中因可由单一的或多个这样的贡献者授予而必须侵犯的申请专利。如果用户对任何实体针对作品或作品中所涉及贡献提出因直接性或贡献性专利侵权而提起专利法律诉讼(包括交互诉讼请求或反索赔),那么根据本许可证,授予用户针对作品的任何专利许可证将在提起上述诉讼之日起终止。 30 | 重新分发。用户可在任何媒介中复制和分发作品或衍生作品之副本,无论是否修订,还是以源程序形式或目标形式,条件是用户需满足下列条款: 31 | 用户必须为作品或衍生作品的任何其他接收者提供本许可证的副本;并且 32 | 用户必须让任何修改过的文件附带明显的通知,声明用户已更改文件;并且 33 | 用户必须从作品的源程序形式中保留衍生作品源程序形式的用户所分发的所有版权、专利、商标和属性通知,但不包括不属于衍生作品任何部分的类似通知;并且 34 | 如果作品将"通知"文本文件包括为其分发作品的一部分,那么用户分发的任何衍生作品中须至少在下列地方之一包括,在这样的通知文件中所包含的属性通知的可读副本,但不包括那些不属于衍生作品任何部分的通知:在作为衍生作品一部分而分发的通知文本文件中;如果与衍生作品一起提供则在源程序形式或文件中;或者通常作为第三方通知出现的时候和地方,在衍生作品中产生的画面中。通知文件的内容仅供信息提供,并未对许可证进行修改。用户可在其分发的衍生作品中在作品的通知文本后或作为附录添加自己的属性通知,条件是附加的属性通知不得构成修改本许可证。 35 | 用户可以为自身所做出的修订添加自己的版权声明并可对自身所做出修订内容或为这样的衍生作品作为整体的使用、复制或分发提供附加或不同的条款,条件是用户对作品的使用、复制和分发必须符合本许可证中声明的条款。 36 | 37 | 贡献的提交。除非用户明确声明,在作品中由用户向许可证颁发者的提交若要包含在贡献中,必须在无任何附加条款下符合本许可证的条款。尽管上面如此规定,执行许可证颁发者有关贡献的条款时,任何情况下均不得替代或修改任何单独许可证协议的条款。 38 | 商标。本许可证并未授予用户使用许可证颁发者的商号、商标、服务标记或产品名称,除非将这些名称用于合理性和惯例性描述作品起源和复制通知文件的内容时。 39 | 保证否认条款。除非因适用法律需要或书面同意,许可证颁发者以"按原样"基础提供作品(并且每个贡献者提供其贡献),无任何明示的或暗示的保证或条件,包括但不限于关于所有权、不侵权、商品适销性、或适用性的保证或条件。用户仅对使用或重新分发作品的正确性负责,并需承担根据本许可证行使权限时的任何风险。 40 | 责任限制条款。在任何情况下并根据任何法律,无论是因侵权(包括过失)或根据合同,还是其它原因,除非根据适用法律需要(例如故意行为和重大过失行为)或经书面同意,即使贡献者事先已被告知发生损害的可能性,任何贡献者不就用户因使用本许可证或不能使用或无法使用作品(包括但不限于商誉损失、停工、计算机失效或故障,或任何商业损坏或损失)而造成的损失,包括直接的、非直接的、特殊的、意外的或间接的字符损坏而负责。 41 | 接受保证或附加责任。重新分发作品或及其衍生作品时,用户可选择提供或为符合本许可证承担之支持、担保、赔偿或其它职责义务和/或权利而收取费用。但是,在承担上述义务时,用户只可代表用户本身和用户本身责任来执行,无需代表任何其它贡献者,并且用户仅可保证、防护并保持每个贡献者不受任何因此而产生的责任或对因用户自身承担这样的保证或附加责任而对这样的贡献者所提出的索赔。 42 | 条款结束 43 | 44 | 附录:如何向用户作品中应用Apache许可证。 45 | 46 | 若要向用户作品应用Apache许可证,请附加下列样本通知,将括号"[]"中的字段以用户自身的区分信息来替换(但不包括括号)。文本必须以文件格式适当的注释句法包含在其中。另外建议将文件名或类别名以及目的说明包含在相同的"打印页"上作为版权通知,以更加容易的区分出第三方档案。 47 | 48 | 版权所有[yyyy][版权所有者的名称] 49 | 50 | 根据2.0版本Apache许可证("许可证")授权; 51 | 根据本许可证,用户可以不使用此文件。 52 | 用户可从下列网址获得许可证副本: 53 | 54 | http://www.apache.org/licenses/LICENSE-2.0 55 | 56 | 除非因适用法律需要或书面同意, 57 | 根据许可证分发的软件是基于"按原样"基础提供, 58 | 无任何明示的或暗示的保证或条件。 59 | 详见根据许可证许可下,特定语言的管辖权限和限制。 60 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:4.0 2 | // 3 | // Package.swift 4 | // PerfectThread 5 | // 6 | // Created by Kyle Jessup on 2016-05-02. 7 | // Copyright (C) 2016 PerfectlySoft, Inc. 8 | // 9 | //===----------------------------------------------------------------------===// 10 | // 11 | // This source file is part of the Perfect.org open source project 12 | // 13 | // Copyright (c) 2015 - 2016 PerfectlySoft Inc. and the Perfect project authors 14 | // Licensed under Apache License v2.0 15 | // 16 | // See http://perfect.org/licensing.html for license information 17 | // 18 | //===----------------------------------------------------------------------===// 19 | // 20 | 21 | import PackageDescription 22 | 23 | #if os(Linux) 24 | let package = Package( 25 | name: "PerfectThread", 26 | products: [ 27 | .library( 28 | name: "PerfectThread", 29 | targets: ["PerfectThread"]), 30 | ], 31 | dependencies: [ 32 | .package(url: "https://github.com/PerfectlySoft/Perfect-LinuxBridge.git", from: "3.0.0") 33 | ], 34 | targets: [ 35 | .target( 36 | name: "PerfectThread", 37 | dependencies: ["LinuxBridge"]), 38 | .testTarget( 39 | name: "PerfectThreadTests", 40 | dependencies: ["PerfectThread"]), 41 | ] 42 | ) 43 | #else 44 | let package = Package( 45 | name: "PerfectThread", 46 | products: [ 47 | .library( 48 | name: "PerfectThread", 49 | targets: ["PerfectThread"]), 50 | ], 51 | dependencies: [ 52 | ], 53 | targets: [ 54 | .target( 55 | name: "PerfectThread", 56 | dependencies: []), 57 | .testTarget( 58 | name: "PerfectThreadTests", 59 | dependencies: ["PerfectThread"]), 60 | ] 61 | ) 62 | #endif 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Perfect-Thread [简体中文](README.zh_CN.md) 2 | 3 |

4 | 5 | Get Involed with Perfect! 6 | 7 |

8 | 9 |

10 | 11 | Star Perfect On Github 12 | 13 | 14 | Stack Overflow 15 | 16 | 17 | Follow Perfect on Twitter 18 | 19 | 20 | Join the Perfect Slack 21 | 22 |

23 | 24 |

25 | 26 | Swift 3.0 27 | 28 | 29 | Platforms OS X | Linux 30 | 31 | 32 | License Apache 33 | 34 | 35 | PerfectlySoft Twitter 36 | 37 | 38 | Slack Status 39 | 40 |

41 | 42 | Core threading package used in Perfect. Includes support for serial and concurrent thread queues, locks, read/write locks and events. 43 | 44 | ## Further Information 45 | For more information on the Perfect project, please visit [perfect.org](http://perfect.org). 46 | -------------------------------------------------------------------------------- /README.zh_CN.md: -------------------------------------------------------------------------------- 1 | # Perfect-Thread 线程管理函数库 [English](https://github.com/PerfectlySoft/Perfect-Thread) 2 | 3 |

4 | 5 | Get Involed with Perfect! 6 | 7 |

8 | 9 |

10 | 11 | Star Perfect On Github 12 | 13 | 14 | Chat on Gitter 15 | 16 | 17 | Follow Perfect on Twitter 18 | 19 | 20 | Join the Perfect Slack 21 | 22 |

23 | 24 |

25 | 26 | Swift 3.0 27 | 28 | 29 | Platforms OS X | Linux 30 | 31 | 32 | License Apache 33 | 34 | 35 | PerfectlySoft Twitter 36 | 37 | 38 | Join the chat at https://gitter.im/PerfectlySoft/Perfect 39 | 40 | 41 | Slack Status 42 | 43 |

44 | 45 | 在Perfect软件框架体系中应用的多线程管理核心类库,包括线程并发、队列管理、资源锁的读写操作和线程事件。 46 | 47 | ### 问题报告 48 | 49 | 我们目前正在过渡到使用JIRA来处理所有源代码资源合并申请、修复漏洞以及其它有关问题。因此,GitHub 的“issues”问题报告功能已经被禁用了。 50 | 51 | 如果您发现了问题,或者希望为改进本文提供意见和建议,[请在这里指出](http://jira.perfect.org:8080/servicedesk/customer/portal/1). 52 | 53 | 在您开始之前,请参阅[目前待解决的问题清单](http://jira.perfect.org:8080/projects/ISS/issues). 54 | 55 | 56 | ## 更多信息 57 | 本项目更多信息,请参考项目官网[perfect.org](http://perfect.org)。 58 | -------------------------------------------------------------------------------- /Sources/PerfectThread/Promise.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Promise.swift 3 | // PerfectThread 4 | // 5 | // Created by Kyle Jessup on 2017-03-06. 6 | // Copyright (C) 2017 PerfectlySoft, Inc. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This source file is part of the Perfect.org open source project 11 | // 12 | // Copyright (c) 2015 - 2017 PerfectlySoft Inc. and the Perfect project authors 13 | // Licensed under Apache License v2.0 14 | // 15 | // See http://perfect.org/licensing.html for license information 16 | // 17 | //===----------------------------------------------------------------------===// 18 | // 19 | 20 | /// A Promise is an object which is shared between one or more threads. 21 | /// The promise will execute the closure given to it when it is created on a new thread. When the 22 | /// thread produces its return value a consumer thread will be able to obtain 23 | /// the value or handle the error if one occurred. 24 | /// 25 | /// This object is generally used in one of two ways: 26 | /// * By passing a closure/function which is executed on another thread and accepts the 27 | /// Promise as a parameter. The promise can at some later point be .set or .fail'ed, with a 28 | /// return value or error object, respectively. The Promise creator can periodically .get 29 | /// or .wait for the value or error. This provides the most flexible usage as the Promise can be 30 | /// .set at any point, for example after a series of asynchronous API calls. 31 | /// Example: 32 | /// let prom = Promise { 33 | /// (p: Promise) in 34 | /// Threading.sleep(seconds: 2.0) 35 | /// p.set(true) 36 | /// } 37 | /// XCTAssert(try prom.get() == nil) // not fulfilled yet 38 | /// XCTAssert(try prom.wait(seconds: 3.0) == true) 39 | /// 40 | /// * By passing a closure/function which accepts zero parameters and returns some abitrary type, 41 | /// followed by zero or more calls to .then 42 | /// Example: 43 | /// let v = try Promise { 1 }.then { try $0() + 1 }.then { try $0() + 1 }.wait() 44 | /// XCTAssert(v == 3, "\(v)") 45 | /// 46 | 47 | import Dispatch 48 | 49 | public class Promise { 50 | 51 | let event = Threading.Event() 52 | let queue = DispatchQueue(label: "promise") 53 | var value: ReturnType? 54 | var error: Error? 55 | 56 | /// Initialize a Promise with a closure. The closure is passed the promise object on which the 57 | /// return value or error can be later set. 58 | /// The closure will be executed on a new serial thread queue and will begin 59 | /// executing immediately. 60 | public init(closure: @escaping (Promise) throws -> ()) { 61 | queue.async { 62 | do { 63 | try closure(self) 64 | } catch { 65 | self.fail(error) 66 | } 67 | } 68 | } 69 | 70 | /// Initialize a Promise with a closure. The closure will return a single value type which will 71 | /// fulfill the promise. 72 | /// The closure will be executed on a new serial thread queue and will begin 73 | /// executing immediately. 74 | public init(closure: @escaping () throws -> ReturnType) { 75 | queue.async { 76 | do { 77 | self.set(try closure()) 78 | } catch { 79 | self.fail(error) 80 | } 81 | } 82 | } 83 | 84 | init(from: Promise, closure: @escaping (() throws -> LastType) throws -> ReturnType) { 85 | queue.async { 86 | do { 87 | self.set(try closure({ guard let v = try from.wait() else { throw BrokenPromise() } ; return v })) 88 | } catch { 89 | self.fail(error) 90 | } 91 | } 92 | } 93 | 94 | /// Chain a new Promise to an existing. The provided closure will receive the previous promise's 95 | /// value once it is available and should return a new value. 96 | public func then(closure: @escaping (() throws -> ReturnType) throws -> NewType) -> Promise { 97 | return Promise(from: self, closure: closure) 98 | } 99 | 100 | public func when(closure: @escaping (Error) throws -> ()) -> Promise { 101 | return Promise(from: self) { 102 | value in 103 | do { 104 | return try value() 105 | } catch { 106 | try closure(error) 107 | throw error 108 | } 109 | } 110 | } 111 | } 112 | 113 | public extension Promise { 114 | /// Get the return value if it is available. 115 | /// Returns nil if the return value is not available. 116 | /// If a failure has occurred then the Error will be thrown. 117 | /// This is called by the consumer thread. 118 | func get() throws -> ReturnType? { 119 | event.lock() 120 | defer { 121 | event.unlock() 122 | } 123 | if let error = error { 124 | throw error 125 | } 126 | return value 127 | } 128 | 129 | /// Get the return value if it is available. 130 | /// Returns nil if the return value is not available. 131 | /// If a failure has occurred then the Error will be thrown. 132 | /// Will block and wait up to the indicated number of seconds for the return value to be produced. 133 | /// This is called by the consumer thread. 134 | func wait(seconds: Double = Threading.noTimeout) throws -> ReturnType? { 135 | event.lock() 136 | defer { 137 | event.unlock() 138 | } 139 | if let error = error { 140 | throw error 141 | } 142 | if let value = value { 143 | return value 144 | } 145 | repeat { 146 | if let error = error { 147 | throw error 148 | } 149 | if let value = value { 150 | return value 151 | } 152 | } while event.wait(seconds: seconds) 153 | if let error = error { 154 | throw error 155 | } 156 | return value 157 | } 158 | } 159 | 160 | public extension Promise { 161 | /// Set the Promise's return value, enabling the consumer to retrieve it. 162 | /// This is called by the producer thread. 163 | func set(_ value: ReturnType) { 164 | event.lock() 165 | defer { 166 | event.unlock() 167 | } 168 | self.value = value 169 | event.broadcast() 170 | } 171 | 172 | /// Fail the Promise and set its error value. 173 | /// This is called by the producer thread. 174 | func fail(_ error: Error) { 175 | event.lock() 176 | defer { 177 | event.unlock() 178 | } 179 | self.error = error 180 | event.broadcast() 181 | } 182 | } 183 | 184 | struct BrokenPromise: Error {} 185 | -------------------------------------------------------------------------------- /Sources/PerfectThread/ThreadQueue.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ThreadQueue.swift 3 | // PerfectLib 4 | // 5 | // Created by Kyle Jessup on 2016-04-08. 6 | // Copyright © 2016 PerfectlySoft. All rights reserved. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This source file is part of the Perfect.org open source project 11 | // 12 | // Copyright (c) 2015 - 2016 PerfectlySoft Inc. and the Perfect project authors 13 | // Licensed under Apache License v2.0 14 | // 15 | // See http://perfect.org/licensing.html for license information 16 | // 17 | //===----------------------------------------------------------------------===// 18 | // 19 | 20 | #if os(Linux) 21 | import SwiftGlibc 22 | import LinuxBridge 23 | #else 24 | import Foundation 25 | #endif 26 | 27 | import Dispatch 28 | 29 | private let anonymousQueueName = "__unregistered__" 30 | 31 | /// A thread queue which can dispatch a closure according to the queue type. 32 | public protocol ThreadQueue { 33 | /// The queue name. 34 | var name: String { get } 35 | /// The queue type. 36 | var type: Threading.QueueType { get } 37 | /// Execute the given closure within the queue's thread. 38 | func dispatch(_ closure: @escaping Threading.ThreadClosure) 39 | } 40 | 41 | protocol ThreadQueueInternal { 42 | var running: Bool { get set } 43 | var lock: Threading.Event { get } 44 | } 45 | 46 | public extension Threading { 47 | 48 | private static var serialQueues = [String:ThreadQueue]() 49 | private static var concurrentQueues = [String:ThreadQueue]() 50 | private static let queuesLock = Threading.Lock() 51 | 52 | private static let defaultQueue = DefaultQueue() 53 | 54 | /// Queue type indicator. 55 | enum QueueType { 56 | /// A queue which operates on only one thread. 57 | case serial 58 | /// A queue which operates on a number of threads, usually equal to the number of logical CPUs. 59 | case concurrent 60 | } 61 | 62 | private class DefaultQueue: ThreadQueue { 63 | let name = "default" 64 | let type = Threading.QueueType.concurrent 65 | let queue = DispatchQueue(label: "default", attributes: .concurrent) 66 | @inline(__always) 67 | final func dispatch(_ closure: @escaping Threading.ThreadClosure) { 68 | queue.async(execute: closure) 69 | } 70 | } 71 | 72 | private class SerialQueue: ThreadQueue, ThreadQueueInternal { 73 | let name: String 74 | let type = Threading.QueueType.serial 75 | var running = true 76 | let lock = Threading.Event() 77 | private var q: [Threading.ThreadClosure] = [] 78 | 79 | init(name: String) { 80 | self.name = name 81 | self.startLoop() 82 | } 83 | 84 | func dispatch(_ closure: @escaping Threading.ThreadClosure) { 85 | let _ = self.lock.lock() 86 | defer { let _ = self.lock.unlock() } 87 | self.q.append(closure) 88 | let _ = self.lock.signal() 89 | } 90 | 91 | private func startLoop() { 92 | Threading.dispatchOnNewThread { 93 | while self.running { 94 | var block: Threading.ThreadClosure? 95 | do { 96 | self.lock.lock() 97 | defer { self.lock.unlock() } 98 | 99 | let count = self.q.count 100 | if count > 0 { 101 | block = self.q.removeFirst() 102 | } else { 103 | _ = self.lock.wait() 104 | if self.q.count > 0 { 105 | block = self.q.removeFirst() 106 | } 107 | } 108 | } 109 | if let b = block { 110 | #if os(macOS) 111 | autoreleasepool { b() } 112 | #else 113 | b() 114 | #endif 115 | } 116 | } 117 | } 118 | } 119 | } 120 | 121 | private class ConcurrentQueue: ThreadQueue, ThreadQueueInternal { 122 | let name: String 123 | let type = Threading.QueueType.concurrent 124 | var running = true 125 | let lock = Threading.Event() 126 | private var q: [Threading.ThreadClosure] = [] 127 | 128 | init(name: String) { 129 | self.name = name 130 | self.startLoop() 131 | } 132 | 133 | func dispatch(_ closure: @escaping Threading.ThreadClosure) { 134 | let _ = self.lock.lock() 135 | defer { let _ = self.lock.unlock() } 136 | self.q.append(closure) 137 | let _ = self.lock.signal() 138 | } 139 | 140 | private func startLoop() { 141 | for _ in 0.. 0 { 151 | block = self.q.removeFirst() 152 | } else { 153 | let _ = self.lock.wait() 154 | if self.q.count > 0 { 155 | block = self.q.removeFirst() 156 | } 157 | } 158 | } 159 | if let b = block { 160 | #if os(macOS) 161 | autoreleasepool { b() } 162 | #else 163 | b() 164 | #endif 165 | } 166 | } 167 | } 168 | } 169 | } 170 | } 171 | 172 | private static var processorCount: Int { 173 | #if os(Linux) 174 | let num = sysconf(Int32(_SC_NPROCESSORS_ONLN)) 175 | #else 176 | let num = sysconf(_SC_NPROCESSORS_ONLN) 177 | #endif 178 | return num 179 | } 180 | 181 | /// Return the default queue 182 | static func getDefaultQueue() -> ThreadQueue { 183 | return defaultQueue 184 | } 185 | 186 | /// Returns an anonymous queue of the indicated type. 187 | /// This queue can not be utilized without the returned ThreadQueue object. 188 | /// The queue should be destroyed when no longer needed. 189 | static func getQueue(type: QueueType) -> ThreadQueue { 190 | switch type { 191 | case .serial: 192 | return SerialQueue(name: anonymousQueueName) 193 | case .concurrent: 194 | return ConcurrentQueue(name: anonymousQueueName) 195 | } 196 | } 197 | 198 | /// Find or create a queue indicated by name and type. 199 | static func getQueue(name: String, type: QueueType) -> ThreadQueue { 200 | Threading.queuesLock.lock() 201 | defer { Threading.queuesLock.unlock() } 202 | 203 | switch type { 204 | case .serial: 205 | if let qTst = Threading.serialQueues[name] { 206 | return qTst 207 | } 208 | let q = SerialQueue(name: name) 209 | Threading.serialQueues[name] = q 210 | return q 211 | case .concurrent: 212 | if let qTst = Threading.concurrentQueues[name] { 213 | return qTst 214 | } 215 | let q = ConcurrentQueue(name: name) 216 | Threading.concurrentQueues[name] = q 217 | return q 218 | } 219 | } 220 | 221 | /// Terminate and remove a thread queue. 222 | static func destroyQueue(_ queue: ThreadQueue) { 223 | if queue.name != anonymousQueueName { 224 | Threading.queuesLock.lock() 225 | defer { Threading.queuesLock.unlock() } 226 | switch queue.type { 227 | case .serial: 228 | Threading.serialQueues.removeValue(forKey: queue.name) 229 | case .concurrent: 230 | Threading.concurrentQueues.removeValue(forKey: queue.name) 231 | } 232 | } 233 | if var qi = queue as? ThreadQueueInternal { 234 | qi.running = false 235 | qi.lock.broadcast() 236 | } 237 | } 238 | 239 | /// Call the given closure on the "default" concurrent queue 240 | /// Returns immediately. 241 | static func dispatch(closure: @escaping Threading.ThreadClosure) { 242 | defaultQueue.dispatch(closure) 243 | } 244 | 245 | // This is a lower level function which does not utilize the ThreadQueue system. 246 | private static func dispatchOnNewThread(closure: @escaping ThreadClosure) { 247 | #if os(Linux) 248 | var thrdSlf = pthread_t() 249 | #else 250 | var thrdSlf = pthread_t(nil as OpaquePointer?) 251 | #endif 252 | var attr = pthread_attr_t() 253 | 254 | pthread_attr_init(&attr) 255 | pthread_attr_setdetachstate(&attr, Int32(PTHREAD_CREATE_DETACHED)) 256 | 257 | final class IsThisRequired { 258 | let closure: ThreadClosure 259 | init(closure: @escaping ThreadClosure) { 260 | self.closure = closure 261 | } 262 | } 263 | 264 | let holderObject = IsThisRequired(closure: closure) 265 | #if os(Linux) 266 | typealias ThreadFunction = @convention(c) (UnsafeMutableRawPointer?) -> UnsafeMutableRawPointer? 267 | let pthreadFunc: ThreadFunction = { 268 | p in 269 | guard let p = p else { 270 | return nil 271 | } 272 | let unleakyObject = Unmanaged.fromOpaque(UnsafeMutableRawPointer(p)).takeRetainedValue() 273 | unleakyObject.closure() 274 | return nil 275 | } 276 | #else 277 | typealias ThreadFunction = @convention(c) (UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? 278 | let pthreadFunc: ThreadFunction = { 279 | p in 280 | let unleakyObject = Unmanaged.fromOpaque(UnsafeMutableRawPointer(p)).takeRetainedValue() 281 | unleakyObject.closure() 282 | return nil 283 | } 284 | #endif 285 | let leakyObject = Unmanaged.passRetained(holderObject).toOpaque() 286 | pthread_create(&thrdSlf, &attr, pthreadFunc, leakyObject) 287 | } 288 | } 289 | -------------------------------------------------------------------------------- /Sources/PerfectThread/Threading.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Threading.swift 3 | // PerfectLib 4 | // 5 | // Created by Kyle Jessup on 2015-12-03. 6 | // Copyright © 2015 PerfectlySoft. All rights reserved. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This source file is part of the Perfect.org open source project 11 | // 12 | // Copyright (c) 2015 - 2016 PerfectlySoft Inc. and the Perfect project authors 13 | // Licensed under Apache License v2.0 14 | // 15 | // See http://perfect.org/licensing.html for license information 16 | // 17 | //===----------------------------------------------------------------------===// 18 | // 19 | 20 | #if os(Linux) 21 | import SwiftGlibc 22 | import LinuxBridge 23 | let CLOCK_MONOTONIC = Int32(1) 24 | #else 25 | import Darwin 26 | #endif 27 | 28 | 29 | private func my_pthread_cond_timedwait_relative_np(_ cond: UnsafeMutablePointer, 30 | _ mutx: UnsafeMutablePointer, 31 | _ tmspec: UnsafePointer) -> Int32 { 32 | #if os(Linux) 33 | var timeout = timespec() 34 | var time = timeval() 35 | gettimeofday(&time, nil) 36 | timeout.tv_sec = time.tv_sec 37 | timeout.tv_nsec = Int(time.tv_usec) * 1000 38 | 39 | clock_gettime(CLOCK_MONOTONIC, &timeout) 40 | timeout.tv_sec += tmspec.pointee.tv_sec 41 | timeout.tv_nsec += tmspec.pointee.tv_nsec 42 | if timeout.tv_nsec >= 1000000000 { 43 | timeout.tv_sec += 1 44 | timeout.tv_nsec -= 1000000000 45 | } 46 | let i = pthread_cond_timedwait(cond, mutx, &timeout) 47 | #else 48 | let i = pthread_cond_timedwait_relative_np(cond, mutx, tmspec) 49 | #endif 50 | return i 51 | } 52 | 53 | 54 | /// A wrapper around a variety of threading related functions and classes. 55 | public struct Threading { 56 | /// Indicates that the call should have no timeout. 57 | public static let noTimeout = 0.0 58 | // Non-instantiable. 59 | private init() {} 60 | /// The function type which can be given to `Threading.dispatch`. 61 | public typealias ThreadClosure = () -> () 62 | } 63 | 64 | public extension Threading { 65 | /// A mutex-type thread lock. 66 | /// The lock can be held by only one thread. Other threads attempting to secure the lock while it is held will block. 67 | /// The lock is initialized as being recursive. The locking thread may lock multiple times, but each lock should be accompanied by an unlock. 68 | class Lock { 69 | var mutex = pthread_mutex_t() 70 | /// Initialize a new lock object. 71 | public init() { 72 | var attr = pthread_mutexattr_t() 73 | pthread_mutexattr_init(&attr) 74 | pthread_mutexattr_settype(&attr, Int32(PTHREAD_MUTEX_RECURSIVE)) 75 | pthread_mutex_init(&mutex, &attr) 76 | } 77 | 78 | deinit { 79 | pthread_mutex_destroy(&mutex) 80 | } 81 | 82 | /// Attempt to grab the lock. 83 | /// Returns true if the lock was successful. 84 | @discardableResult 85 | public func lock() -> Bool { 86 | return 0 == pthread_mutex_lock(&self.mutex) 87 | } 88 | 89 | /// Attempt to grab the lock. 90 | /// Will only return true if the lock was not being held by any other thread. 91 | /// Returns false if the lock is currently being held by another thread. 92 | public func tryLock() -> Bool { 93 | return 0 == pthread_mutex_trylock(&self.mutex) 94 | } 95 | 96 | /// Unlock. Returns true if the lock was held by the current thread and was successfully unlocked. ior the lock count was decremented. 97 | @discardableResult 98 | public func unlock() -> Bool { 99 | return 0 == pthread_mutex_unlock(&self.mutex) 100 | } 101 | 102 | /// Acquire the lock, execute the closure, release the lock. 103 | public func doWithLock(closure: () throws -> Result) rethrows -> Result { 104 | _ = self.lock() 105 | defer { 106 | _ = self.unlock() 107 | } 108 | return try closure() 109 | } 110 | } 111 | } 112 | 113 | public extension Threading { 114 | /// A thread event object. Inherits from `Threading.Lock`. 115 | /// The event MUST be locked before `wait` or `signal` is called. 116 | /// While inside the `wait` call, the event is automatically placed in the unlocked state. 117 | /// After `wait` or `signal` return the event will be in the locked state and must be unlocked. 118 | final class Event: Lock { 119 | 120 | var cond = pthread_cond_t() 121 | 122 | /// Initialize a new Event object. 123 | override public init() { 124 | super.init() 125 | 126 | var attr = pthread_condattr_t() 127 | pthread_condattr_init(&attr) 128 | #if os (Linux) 129 | pthread_condattr_setclock(&attr, CLOCK_MONOTONIC) 130 | #endif 131 | pthread_cond_init(&cond, &attr) 132 | pthread_condattr_destroy(&attr) 133 | } 134 | 135 | deinit { 136 | pthread_cond_destroy(&cond) 137 | } 138 | 139 | /// Signal at most ONE thread which may be waiting on this event. 140 | /// Has no effect if there is no waiting thread. 141 | @discardableResult 142 | public func signal() -> Bool { 143 | return 0 == pthread_cond_signal(&self.cond) 144 | } 145 | 146 | /// Signal ALL threads which may be waiting on this event. 147 | /// Has no effect if there is no waiting thread. 148 | @discardableResult 149 | public func broadcast() -> Bool { 150 | return 0 == pthread_cond_broadcast(&self.cond) 151 | } 152 | 153 | /// Wait on this event for another thread to call signal. 154 | /// Blocks the calling thread until a signal is received or the timeout occurs. 155 | /// Returns true only if the signal was received. 156 | /// Returns false upon timeout or error. 157 | public func wait(seconds: Double = Threading.noTimeout) -> Bool { 158 | if seconds == Threading.noTimeout { 159 | return 0 == pthread_cond_wait(&self.cond, &self.mutex) 160 | } 161 | var tm = timespec() 162 | tm.tv_sec = Int(floor(seconds)) 163 | tm.tv_nsec = (Int(seconds * 1000.0) - (tm.tv_sec * 1000)) * 1000000 164 | 165 | let ret = my_pthread_cond_timedwait_relative_np(&self.cond, &self.mutex, &tm) 166 | return ret == 0; 167 | } 168 | } 169 | } 170 | 171 | public extension Threading { 172 | /// A read-write thread lock. 173 | /// Permits multiple readers to hold the while, while only allowing at most one writer to hold the lock. 174 | /// For a writer to acquire the lock all readers must have unlocked. 175 | /// For a reader to acquire the lock no writers must hold the lock. 176 | final class RWLock { 177 | 178 | var lock = pthread_rwlock_t() 179 | 180 | /// Initialize a new read-write lock. 181 | public init() { 182 | pthread_rwlock_init(&self.lock, nil) 183 | } 184 | 185 | deinit { 186 | pthread_rwlock_destroy(&self.lock) 187 | } 188 | 189 | /// Attempt to acquire the lock for reading. 190 | /// Returns false if an error occurs. 191 | @discardableResult 192 | public func readLock() -> Bool { 193 | return 0 == pthread_rwlock_rdlock(&self.lock) 194 | } 195 | 196 | /// Attempts to acquire the lock for reading. 197 | /// Returns false if the lock is held by a writer or an error occurs. 198 | public func tryReadLock() -> Bool { 199 | return 0 == pthread_rwlock_tryrdlock(&self.lock) 200 | } 201 | 202 | /// Attempt to acquire the lock for writing. 203 | /// Returns false if an error occurs. 204 | @discardableResult 205 | public func writeLock() -> Bool { 206 | return 0 == pthread_rwlock_wrlock(&self.lock) 207 | } 208 | 209 | /// Attempt to acquire the lock for writing. 210 | /// Returns false if the lock is held by readers or a writer or an error occurs. 211 | public func tryWriteLock() -> Bool { 212 | return 0 == pthread_rwlock_trywrlock(&self.lock) 213 | } 214 | 215 | /// Unlock a lock which is held for either reading or writing. 216 | /// Returns false if an error occurs. 217 | @discardableResult 218 | public func unlock() -> Bool { 219 | return 0 == pthread_rwlock_unlock(&self.lock) 220 | } 221 | 222 | /// Acquire the read lock, execute the closure, release the lock. 223 | public func doWithReadLock(closure: () throws -> Result) rethrows -> Result { 224 | _ = self.readLock() 225 | defer { 226 | _ = self.unlock() 227 | } 228 | return try closure() 229 | } 230 | 231 | /// Acquire the write lock, execute the closure, release the lock. 232 | public func doWithWriteLock(closure: () throws -> Result) rethrows -> Result { 233 | _ = self.writeLock() 234 | defer { 235 | _ = self.unlock() 236 | } 237 | return try closure() 238 | } 239 | } 240 | } 241 | 242 | public extension Threading { 243 | /// Block the current thread for the indicated time. 244 | static func sleep(seconds inSeconds: Double) { 245 | guard inSeconds >= 0.0 else { 246 | return 247 | } 248 | let milliseconds = Int(inSeconds * 1000.0) 249 | var tv = timeval() 250 | tv.tv_sec = milliseconds/1000 251 | #if os(Linux) 252 | tv.tv_usec = Int((milliseconds%1000)*1000) 253 | #else 254 | tv.tv_usec = Int32((milliseconds%1000)*1000) 255 | #endif 256 | select(0, nil, nil, nil, &tv) 257 | } 258 | } 259 | -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Package.swift 3 | // PerfectThread 4 | // 5 | // Created by Kyle Jessup on 2016-05-02. 6 | // Copyright (C) 2016 PerfectlySoft, Inc. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This source file is part of the Perfect.org open source project 11 | // 12 | // Copyright (c) 2015 - 2016 PerfectlySoft Inc. and the Perfect project authors 13 | // Licensed under Apache License v2.0 14 | // 15 | // See http://perfect.org/licensing.html for license information 16 | // 17 | //===----------------------------------------------------------------------===// 18 | // 19 | 20 | import XCTest 21 | @testable import PerfectThreadTests 22 | 23 | XCTMain([ 24 | testCase(PerfectThreadTests.allTests), 25 | ]) 26 | -------------------------------------------------------------------------------- /Tests/PerfectThreadTests/PerfectThreadTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Package.swift 3 | // PerfectThread 4 | // 5 | // Created by Kyle Jessup on 2016-05-02. 6 | // Copyright (C) 2016 PerfectlySoft, Inc. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This source file is part of the Perfect.org open source project 11 | // 12 | // Copyright (c) 2015 - 2016 PerfectlySoft Inc. and the Perfect project authors 13 | // Licensed under Apache License v2.0 14 | // 15 | // See http://perfect.org/licensing.html for license information 16 | // 17 | //===----------------------------------------------------------------------===// 18 | // 19 | 20 | #if os(Linux) 21 | import LinuxBridge 22 | #else 23 | import Darwin 24 | #endif 25 | 26 | import XCTest 27 | @testable import PerfectThread 28 | 29 | class PerfectThreadTests: XCTestCase { 30 | 31 | func testConcurrentQueue1() { 32 | let q = Threading.getQueue(name: "concurrent", type: .concurrent) 33 | 34 | var t1 = 0, t2 = 0, t3 = 0 35 | 36 | q.dispatch { 37 | t1 = 1 38 | Threading.sleep(seconds: 5) 39 | } 40 | q.dispatch { 41 | t2 = 1 42 | Threading.sleep(seconds: 5) 43 | } 44 | q.dispatch { 45 | t3 = 1 46 | Threading.sleep(seconds: 5) 47 | } 48 | Threading.sleep(seconds: 1) 49 | 50 | XCTAssert(t1 == 1 && t2 == 1 && t3 == 1) 51 | } 52 | 53 | func testConcurrentQueue2() { 54 | _ = Threading.getQueue(name: "concurrent", type: .concurrent) 55 | var expects = [XCTestExpectation]() 56 | let threadCount = 32 57 | let iterationCount = 10000 58 | for n in 0.. Double { 116 | var posixTime = timeval() 117 | gettimeofday(&posixTime, nil) 118 | return Double(posixTime.tv_sec * 1000 + Int(posixTime.tv_usec) / 1000) 119 | } 120 | 121 | let now = getNow() 122 | Threading.sleep(seconds: 1.9) 123 | let nower = getNow() 124 | XCTAssert(nower - now >= 2.0) 125 | } 126 | 127 | func testEventTimeout() { 128 | let event = Threading.Event() 129 | event.lock() 130 | let startTime = time(nil) 131 | let waitRes = event.wait(seconds: 2.0) 132 | let endTime = time(nil) 133 | event.unlock() 134 | XCTAssert(waitRes == false) 135 | XCTAssert(endTime - startTime >= 2) 136 | XCTAssert(endTime - startTime < 3) 137 | } 138 | 139 | func testPromise1() { 140 | let p = Promise { 141 | (p: Promise) in 142 | Threading.sleep(seconds: 2.0) 143 | p.set(true) 144 | } 145 | 146 | XCTAssert(try p.get() == nil) 147 | XCTAssert(try p.wait(seconds: 3.0) == true) 148 | } 149 | 150 | func testPromise2() { 151 | 152 | struct E: Error {} 153 | 154 | let p = Promise { 155 | (p: Promise) in 156 | Threading.sleep(seconds: 2.0) 157 | p.fail(E()) 158 | } 159 | 160 | XCTAssert(try p.get() == nil) 161 | do { 162 | _ = try p.wait(seconds: 3.0) 163 | XCTAssert(false) 164 | } catch { 165 | XCTAssert(error is E) 166 | } 167 | } 168 | 169 | func testPromise3() { 170 | do { 171 | let v = try Promise { 1 }.then { try $0() + 1 }.then { try $0() + 1 }.wait() 172 | XCTAssert(v == 3, "\(String(describing: v))") 173 | } catch { 174 | XCTAssert(false, "\(error)") 175 | } 176 | } 177 | 178 | func testPromise4() { 179 | struct E: Error {} 180 | do { 181 | let v = try Promise { throw E() }.then { try $0() + 1 }.then { try $0() + 1 }.wait() 182 | XCTAssert(false, "\(String(describing: v))") 183 | } catch { 184 | XCTAssert(error is E) 185 | } 186 | } 187 | 188 | func testPromise5() { 189 | do { 190 | for _ in 0..<100000 { 191 | let v = try Promise { 1 } 192 | .then { try $0() + 2 } 193 | .then { try $0() + 3 } 194 | .wait() 195 | XCTAssert(v == 6, "\(String(describing: v))") 196 | } 197 | } catch { 198 | XCTAssert(false, "\(error)") 199 | } 200 | } 201 | 202 | func testPromiseFail() { 203 | struct E: Error {} 204 | let exp = expectation(description: "wait") 205 | var err = false 206 | _ = Promise { 1 }.then { 207 | _ = try $0() 208 | throw E() 209 | }.when { 210 | e in 211 | err = true 212 | exp.fulfill() 213 | } 214 | waitForExpectations(timeout: 3) { 215 | _ in 216 | } 217 | XCTAssert(err) 218 | } 219 | 220 | func testDoWithLock() { 221 | let lock = Threading.Lock() 222 | lock.doWithLock { // test compilation of no return usage 223 | for _ in 0...1 { 224 | () 225 | } 226 | } 227 | let result = lock.doWithLock { 228 | return "foo" 229 | } 230 | XCTAssertEqual(result, "foo") 231 | } 232 | 233 | static var allTests : [(String, (PerfectThreadTests) -> () throws -> Void)] { 234 | return [ 235 | ("testConcurrentQueue1", testConcurrentQueue1), 236 | ("testConcurrentQueue2", testConcurrentQueue2), 237 | ("testSerialQueue", testSerialQueue), 238 | ("testThreadSleep", testThreadSleep), 239 | ("testEventTimeout", testEventTimeout), 240 | ("testPromise1", testPromise1), 241 | ("testPromise2", testPromise2), 242 | ("testPromise3", testPromise3), 243 | ("testPromise4", testPromise4), 244 | ("testPromise5", testPromise5), 245 | ("testDoWithLock", testDoWithLock), 246 | ("testPromiseFail", testPromiseFail) 247 | ] 248 | } 249 | } 250 | -------------------------------------------------------------------------------- /docs/Protocols.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Protocols Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Docs (100% documented)

17 |
18 |
19 |
20 | 25 |
26 |
27 | 59 |
60 |
61 |
62 |

Protocols

63 |

The following protocols are available globally.

64 | 65 |
66 |
67 |
68 |
    69 |
  • 70 |
    71 | 72 | 73 | 74 | ThreadQueue 75 | 76 |
    77 |
    78 |
    79 |
    80 |
    81 |
    82 |

    A thread queue which can dispatch a closure according to the queue type.

    83 | 84 | See more 85 |
    86 |
    87 |

    Declaration

    88 |
    89 |

    Swift

    90 |
    public protocol ThreadQueue
    91 | 92 |
    93 |
    94 |
    95 |
    96 |
  • 97 |
98 |
99 |
100 |
101 | 105 |
106 |
107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /docs/Protocols/ThreadQueue.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ThreadQueue Protocol Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

Docs (100% documented)

18 |
19 |
20 |
21 | 26 |
27 |
28 | 60 |
61 |
62 |
63 |

ThreadQueue

64 |
65 |
66 |
public protocol ThreadQueue
67 | 68 |
69 |
70 |

A thread queue which can dispatch a closure according to the queue type.

71 | 72 |
73 |
74 |
75 |
    76 |
  • 77 |
    78 | 79 | 80 | 81 | name 82 | 83 |
    84 |
    85 |
    86 |
    87 |
    88 |
    89 |

    The queue name.

    90 | 91 |
    92 |
    93 |

    Declaration

    94 |
    95 |

    Swift

    96 |
    var name: String
    97 | 98 |
    99 |
    100 |
    101 |
    102 |
  • 103 |
  • 104 |
    105 | 106 | 107 | 108 | type 109 | 110 |
    111 |
    112 |
    113 |
    114 |
    115 |
    116 |

    The queue type.

    117 | 118 |
    119 |
    120 |

    Declaration

    121 |
    122 |

    Swift

    123 |
    var type: Threading.QueueType
    124 | 125 |
    126 |
    127 |
    128 |
    129 |
  • 130 |
  • 131 |
    132 | 133 | 134 | 135 | dispatch(_:) 136 | 137 |
    138 |
    139 |
    140 |
    141 |
    142 |
    143 |

    Execute the given closure within the queue’s thread.

    144 | 145 |
    146 |
    147 |

    Declaration

    148 |
    149 |

    Swift

    150 |
    func dispatch(_ closure: Threading.ThreadClosure)
    151 | 152 |
    153 |
    154 |
    155 |
    156 |
  • 157 |
158 |
159 |
160 |
161 | 165 |
166 |
167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /docs/Structs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Structs Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Docs (100% documented)

17 |
18 |
19 |
20 | 25 |
26 |
27 | 59 |
60 |
61 |
62 |

Structs

63 |

The following structs are available globally.

64 | 65 |
66 |
67 |
68 |
    69 |
  • 70 |
    71 | 72 | 73 | 74 | Threading 75 | 76 |
    77 |
    78 |
    79 |
    80 |
    81 |
    82 |

    A wrapper around a variety of threading related functions and classes.

    83 | 84 | See more 85 |
    86 |
    87 |

    Declaration

    88 |
    89 |

    Swift

    90 |
    public struct Threading
    91 | 92 |
    93 |
    94 |
    95 |
    96 |
  • 97 |
98 |
99 |
100 |
101 | 105 |
106 |
107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /docs/Structs/Threading/Event.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Event Class Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

Docs (100% documented)

18 |
19 |
20 |
21 | 26 |
27 |
28 | 60 |
61 |
62 |
63 |

Event

64 |
65 |
66 |
public final class Event: Lock
67 | 68 |
69 |
70 |

A thread event object. Inherits from Threading.Lock. 71 | The event MUST be locked before wait or signal is called. 72 | While inside the wait call, the event is automatically placed in the unlocked state. 73 | After wait or signal return the event will be in the locked state and must be unlocked.

74 | 75 |
76 |
77 |
78 |
    79 |
  • 80 |
    81 | 82 | 83 | 84 | init() 85 | 86 |
    87 |
    88 |
    89 |
    90 |
    91 |
    92 |

    Initialize a new Event object.

    93 | 94 |
    95 |
    96 |

    Declaration

    97 |
    98 |

    Swift

    99 |
    override public init()
    100 | 101 |
    102 |
    103 |
    104 |
    105 |
  • 106 |
  • 107 |
    108 | 109 | 110 | 111 | signal() 112 | 113 |
    114 |
    115 |
    116 |
    117 |
    118 |
    119 |

    Signal at most ONE thread which may be waiting on this event. 120 | Has no effect if there is no waiting thread.

    121 | 122 |
    123 |
    124 |

    Declaration

    125 |
    126 |

    Swift

    127 |
    public func signal() -> Bool
    128 | 129 |
    130 |
    131 |
    132 |
    133 |
  • 134 |
  • 135 |
    136 | 137 | 138 | 139 | broadcast() 140 | 141 |
    142 |
    143 |
    144 |
    145 |
    146 |
    147 |

    Signal ALL threads which may be waiting on this event. 148 | Has no effect if there is no waiting thread.

    149 | 150 |
    151 |
    152 |

    Declaration

    153 |
    154 |

    Swift

    155 |
    public func broadcast() -> Bool
    156 | 157 |
    158 |
    159 |
    160 |
    161 |
  • 162 |
  • 163 |
    164 | 165 | 166 | 167 | wait(seconds:) 168 | 169 |
    170 |
    171 |
    172 |
    173 |
    174 |
    175 |

    Wait on this event for another thread to call signal. 176 | Blocks the calling thread until a signal is received or the timeout occurs. 177 | Returns true only if the signal was received. 178 | Returns false upon timeout or error.

    179 | 180 |
    181 |
    182 |

    Declaration

    183 |
    184 |

    Swift

    185 |
    public func wait(seconds secs: Double = Threading.noTimeout) -> Bool
    186 | 187 |
    188 |
    189 |
    190 |
    191 |
  • 192 |
193 |
194 |
195 |
196 | 200 |
201 |
202 | 203 | 204 | 205 | -------------------------------------------------------------------------------- /docs/Structs/Threading/Lock.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Lock Class Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

Docs (100% documented)

18 |
19 |
20 |
21 | 26 |
27 |
28 | 60 |
61 |
62 |
63 |

Lock

64 |
65 |
66 |
public class Lock
67 | 68 |
69 |
70 |

A mutex-type thread lock. 71 | The lock can be held by only one thread. Other threads attempting to secure the lock while it is held will block. 72 | The lock is initialized as being recursive. The locking thread may lock multiple times, but each lock should be accompanied by an unlock.

73 | 74 |
75 |
76 |
77 |
    78 |
  • 79 |
    80 | 81 | 82 | 83 | init() 84 | 85 |
    86 |
    87 |
    88 |
    89 |
    90 |
    91 |

    Initialize a new lock object.

    92 | 93 |
    94 |
    95 |

    Declaration

    96 |
    97 |

    Swift

    98 |
    public init()
    99 | 100 |
    101 |
    102 |
    103 |
    104 |
  • 105 |
  • 106 |
    107 | 108 | 109 | 110 | lock() 111 | 112 |
    113 |
    114 |
    115 |
    116 |
    117 |
    118 |

    Attempt to grab the lock. 119 | Returns true if the lock was successful.

    120 | 121 |
    122 |
    123 |

    Declaration

    124 |
    125 |

    Swift

    126 |
    public func lock() -> Bool
    127 | 128 |
    129 |
    130 |
    131 |
    132 |
  • 133 |
  • 134 |
    135 | 136 | 137 | 138 | tryLock() 139 | 140 |
    141 |
    142 |
    143 |
    144 |
    145 |
    146 |

    Attempt to grab the lock. 147 | Will only return true if the lock was not being held by any other thread. 148 | Returns false if the lock is currently being held by another thread.

    149 | 150 |
    151 |
    152 |

    Declaration

    153 |
    154 |

    Swift

    155 |
    public func tryLock() -> Bool
    156 | 157 |
    158 |
    159 |
    160 |
    161 |
  • 162 |
  • 163 |
    164 | 165 | 166 | 167 | unlock() 168 | 169 |
    170 |
    171 |
    172 |
    173 |
    174 |
    175 |

    Unlock. Returns true if the lock was held by the current thread and was successfully unlocked. ior the lock count was decremented.

    176 | 177 |
    178 |
    179 |

    Declaration

    180 |
    181 |

    Swift

    182 |
    public func unlock() -> Bool
    183 | 184 |
    185 |
    186 |
    187 |
    188 |
  • 189 |
  • 190 |
    191 | 192 | 193 | 194 | doWithLock(_:) 195 | 196 |
    197 |
    198 |
    199 |
    200 |
    201 |
    202 |

    Acquire the lock, execute the closure, release the lock.

    203 | 204 |
    205 |
    206 |

    Declaration

    207 |
    208 |

    Swift

    209 |
    public func doWithLock(closure: () throws -> ()) rethrows
    210 | 211 |
    212 |
    213 |
    214 |
    215 |
  • 216 |
217 |
218 |
219 |
220 | 224 |
225 |
226 | 227 | 228 | 229 | -------------------------------------------------------------------------------- /docs/Structs/Threading/QueueType.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | QueueType Enum Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

Docs (100% documented)

18 |
19 |
20 |
21 | 26 |
27 |
28 | 60 |
61 |
62 |
63 |

QueueType

64 |
65 |
66 |
public enum QueueType
67 | 68 |
69 |
70 |

Queue type indicator.

71 | 72 |
73 |
74 |
75 |
    76 |
  • 77 |
    78 | 79 | 80 | 81 | serial 82 | 83 |
    84 |
    85 |
    86 |
    87 |
    88 |
    89 |

    A queue which operates on only one thread.

    90 | 91 |
    92 |
    93 |

    Declaration

    94 |
    95 |

    Swift

    96 |
    case serial
    97 | 98 |
    99 |
    100 |
    101 |
    102 |
  • 103 |
104 |
105 |
106 |
    107 |
  • 108 |
    109 | 110 | 111 | 112 | concurrent 113 | 114 |
    115 |
    116 |
    117 |
    118 |
    119 |
    120 |

    A queue which operates on a number of threads, usually equal to the number of logical CPUs.

    121 | 122 |
    123 |
    124 |

    Declaration

    125 |
    126 |

    Swift

    127 |
    case concurrent
    128 | 129 |
    130 |
    131 |
    132 |
    133 |
  • 134 |
135 |
136 |
137 |
138 | 142 |
143 |
144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /docs/Structs/Threading/RWLock.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | RWLock Class Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

Docs (100% documented)

18 |
19 |
20 |
21 | 26 |
27 |
28 | 60 |
61 |
62 |
63 |

RWLock

64 |
65 |
66 |
public final class RWLock
67 | 68 |
69 |
70 |

A read-write thread lock. 71 | Permits multiple readers to hold the while, while only allowing at most one writer to hold the lock. 72 | For a writer to acquire the lock all readers must have unlocked. 73 | For a reader to acquire the lock no writers must hold the lock.

74 | 75 |
76 |
77 |
78 |
    79 |
  • 80 |
    81 | 82 | 83 | 84 | init() 85 | 86 |
    87 |
    88 |
    89 |
    90 |
    91 |
    92 |

    Initialize a new read-write lock.

    93 | 94 |
    95 |
    96 |

    Declaration

    97 |
    98 |

    Swift

    99 |
    public init()
    100 | 101 |
    102 |
    103 |
    104 |
    105 |
  • 106 |
  • 107 |
    108 | 109 | 110 | 111 | readLock() 112 | 113 |
    114 |
    115 |
    116 |
    117 |
    118 |
    119 |

    Attempt to acquire the lock for reading. 120 | Returns false if an error occurs.

    121 | 122 |
    123 |
    124 |

    Declaration

    125 |
    126 |

    Swift

    127 |
    public func readLock() -> Bool
    128 | 129 |
    130 |
    131 |
    132 |
    133 |
  • 134 |
  • 135 |
    136 | 137 | 138 | 139 | tryReadLock() 140 | 141 |
    142 |
    143 |
    144 |
    145 |
    146 |
    147 |

    Attempts to acquire the lock for reading. 148 | Returns false if the lock is held by a writer or an error occurs.

    149 | 150 |
    151 |
    152 |

    Declaration

    153 |
    154 |

    Swift

    155 |
    public func tryReadLock() -> Bool
    156 | 157 |
    158 |
    159 |
    160 |
    161 |
  • 162 |
  • 163 |
    164 | 165 | 166 | 167 | writeLock() 168 | 169 |
    170 |
    171 |
    172 |
    173 |
    174 |
    175 |

    Attempt to acquire the lock for writing. 176 | Returns false if an error occurs.

    177 | 178 |
    179 |
    180 |

    Declaration

    181 |
    182 |

    Swift

    183 |
    public func writeLock() -> Bool
    184 | 185 |
    186 |
    187 |
    188 |
    189 |
  • 190 |
  • 191 |
    192 | 193 | 194 | 195 | tryWriteLock() 196 | 197 |
    198 |
    199 |
    200 |
    201 |
    202 |
    203 |

    Attempt to acquire the lock for writing. 204 | Returns false if the lock is held by readers or a writer or an error occurs.

    205 | 206 |
    207 |
    208 |

    Declaration

    209 |
    210 |

    Swift

    211 |
    public func tryWriteLock() -> Bool
    212 | 213 |
    214 |
    215 |
    216 |
    217 |
  • 218 |
  • 219 |
    220 | 221 | 222 | 223 | unlock() 224 | 225 |
    226 |
    227 |
    228 |
    229 |
    230 |
    231 |

    Unlock a lock which is held for either reading or writing. 232 | Returns false if an error occurs.

    233 | 234 |
    235 |
    236 |

    Declaration

    237 |
    238 |

    Swift

    239 |
    public func unlock() -> Bool
    240 | 241 |
    242 |
    243 |
    244 |
    245 |
  • 246 |
  • 247 |
    248 | 249 | 250 | 251 | doWithReadLock(_:) 252 | 253 |
    254 |
    255 |
    256 |
    257 |
    258 |
    259 |

    Acquire the read lock, execute the closure, release the lock.

    260 | 261 |
    262 |
    263 |

    Declaration

    264 |
    265 |

    Swift

    266 |
    public func doWithReadLock(closure: () throws -> ()) rethrows
    267 | 268 |
    269 |
    270 |
    271 |
    272 |
  • 273 |
  • 274 |
    275 | 276 | 277 | 278 | doWithWriteLock(_:) 279 | 280 |
    281 |
    282 |
    283 |
    284 |
    285 |
    286 |

    Acquire the write lock, execute the closure, release the lock.

    287 | 288 |
    289 |
    290 |

    Declaration

    291 |
    292 |

    Swift

    293 |
    public func doWithWriteLock(closure: () throws -> ()) rethrows
    294 | 295 |
    296 |
    297 |
    298 |
    299 |
  • 300 |
301 |
302 |
303 |
304 | 308 |
309 |
310 | 311 | 312 | 313 | -------------------------------------------------------------------------------- /docs/css/highlight.css: -------------------------------------------------------------------------------- 1 | /* Credit to https://gist.github.com/wataru420/2048287 */ 2 | .highlight { 3 | /* Comment */ 4 | /* Error */ 5 | /* Keyword */ 6 | /* Operator */ 7 | /* Comment.Multiline */ 8 | /* Comment.Preproc */ 9 | /* Comment.Single */ 10 | /* Comment.Special */ 11 | /* Generic.Deleted */ 12 | /* Generic.Deleted.Specific */ 13 | /* Generic.Emph */ 14 | /* Generic.Error */ 15 | /* Generic.Heading */ 16 | /* Generic.Inserted */ 17 | /* Generic.Inserted.Specific */ 18 | /* Generic.Output */ 19 | /* Generic.Prompt */ 20 | /* Generic.Strong */ 21 | /* Generic.Subheading */ 22 | /* Generic.Traceback */ 23 | /* Keyword.Constant */ 24 | /* Keyword.Declaration */ 25 | /* Keyword.Pseudo */ 26 | /* Keyword.Reserved */ 27 | /* Keyword.Type */ 28 | /* Literal.Number */ 29 | /* Literal.String */ 30 | /* Name.Attribute */ 31 | /* Name.Builtin */ 32 | /* Name.Class */ 33 | /* Name.Constant */ 34 | /* Name.Entity */ 35 | /* Name.Exception */ 36 | /* Name.Function */ 37 | /* Name.Namespace */ 38 | /* Name.Tag */ 39 | /* Name.Variable */ 40 | /* Operator.Word */ 41 | /* Text.Whitespace */ 42 | /* Literal.Number.Float */ 43 | /* Literal.Number.Hex */ 44 | /* Literal.Number.Integer */ 45 | /* Literal.Number.Oct */ 46 | /* Literal.String.Backtick */ 47 | /* Literal.String.Char */ 48 | /* Literal.String.Doc */ 49 | /* Literal.String.Double */ 50 | /* Literal.String.Escape */ 51 | /* Literal.String.Heredoc */ 52 | /* Literal.String.Interpol */ 53 | /* Literal.String.Other */ 54 | /* Literal.String.Regex */ 55 | /* Literal.String.Single */ 56 | /* Literal.String.Symbol */ 57 | /* Name.Builtin.Pseudo */ 58 | /* Name.Variable.Class */ 59 | /* Name.Variable.Global */ 60 | /* Name.Variable.Instance */ 61 | /* Literal.Number.Integer.Long */ } 62 | .highlight .c { 63 | color: #999988; 64 | font-style: italic; } 65 | .highlight .err { 66 | color: #a61717; 67 | background-color: #e3d2d2; } 68 | .highlight .k { 69 | color: #000000; 70 | font-weight: bold; } 71 | .highlight .o { 72 | color: #000000; 73 | font-weight: bold; } 74 | .highlight .cm { 75 | color: #999988; 76 | font-style: italic; } 77 | .highlight .cp { 78 | color: #999999; 79 | font-weight: bold; } 80 | .highlight .c1 { 81 | color: #999988; 82 | font-style: italic; } 83 | .highlight .cs { 84 | color: #999999; 85 | font-weight: bold; 86 | font-style: italic; } 87 | .highlight .gd { 88 | color: #000000; 89 | background-color: #ffdddd; } 90 | .highlight .gd .x { 91 | color: #000000; 92 | background-color: #ffaaaa; } 93 | .highlight .ge { 94 | color: #000000; 95 | font-style: italic; } 96 | .highlight .gr { 97 | color: #aa0000; } 98 | .highlight .gh { 99 | color: #999999; } 100 | .highlight .gi { 101 | color: #000000; 102 | background-color: #ddffdd; } 103 | .highlight .gi .x { 104 | color: #000000; 105 | background-color: #aaffaa; } 106 | .highlight .go { 107 | color: #888888; } 108 | .highlight .gp { 109 | color: #555555; } 110 | .highlight .gs { 111 | font-weight: bold; } 112 | .highlight .gu { 113 | color: #aaaaaa; } 114 | .highlight .gt { 115 | color: #aa0000; } 116 | .highlight .kc { 117 | color: #000000; 118 | font-weight: bold; } 119 | .highlight .kd { 120 | color: #000000; 121 | font-weight: bold; } 122 | .highlight .kp { 123 | color: #000000; 124 | font-weight: bold; } 125 | .highlight .kr { 126 | color: #000000; 127 | font-weight: bold; } 128 | .highlight .kt { 129 | color: #445588; } 130 | .highlight .m { 131 | color: #009999; } 132 | .highlight .s { 133 | color: #d14; } 134 | .highlight .na { 135 | color: #008080; } 136 | .highlight .nb { 137 | color: #0086B3; } 138 | .highlight .nc { 139 | color: #445588; 140 | font-weight: bold; } 141 | .highlight .no { 142 | color: #008080; } 143 | .highlight .ni { 144 | color: #800080; } 145 | .highlight .ne { 146 | color: #990000; 147 | font-weight: bold; } 148 | .highlight .nf { 149 | color: #990000; } 150 | .highlight .nn { 151 | color: #555555; } 152 | .highlight .nt { 153 | color: #000080; } 154 | .highlight .nv { 155 | color: #008080; } 156 | .highlight .ow { 157 | color: #000000; 158 | font-weight: bold; } 159 | .highlight .w { 160 | color: #bbbbbb; } 161 | .highlight .mf { 162 | color: #009999; } 163 | .highlight .mh { 164 | color: #009999; } 165 | .highlight .mi { 166 | color: #009999; } 167 | .highlight .mo { 168 | color: #009999; } 169 | .highlight .sb { 170 | color: #d14; } 171 | .highlight .sc { 172 | color: #d14; } 173 | .highlight .sd { 174 | color: #d14; } 175 | .highlight .s2 { 176 | color: #d14; } 177 | .highlight .se { 178 | color: #d14; } 179 | .highlight .sh { 180 | color: #d14; } 181 | .highlight .si { 182 | color: #d14; } 183 | .highlight .sx { 184 | color: #d14; } 185 | .highlight .sr { 186 | color: #009926; } 187 | .highlight .s1 { 188 | color: #d14; } 189 | .highlight .ss { 190 | color: #990073; } 191 | .highlight .bp { 192 | color: #999999; } 193 | .highlight .vc { 194 | color: #008080; } 195 | .highlight .vg { 196 | color: #008080; } 197 | .highlight .vi { 198 | color: #008080; } 199 | .highlight .il { 200 | color: #009999; } 201 | -------------------------------------------------------------------------------- /docs/css/jazzy.css: -------------------------------------------------------------------------------- 1 | html, body, div, span, h1, h3, h4, p, a, code, em, img, ul, li, table, tbody, tr, td { 2 | background: transparent; 3 | border: 0; 4 | margin: 0; 5 | outline: 0; 6 | padding: 0; 7 | vertical-align: baseline; } 8 | 9 | body { 10 | background-color: #f2f2f2; 11 | font-family: Helvetica, freesans, Arial, sans-serif; 12 | font-size: 14px; 13 | -webkit-font-smoothing: subpixel-antialiased; 14 | word-wrap: break-word; } 15 | 16 | h1, h2, h3 { 17 | margin-top: 0.8em; 18 | margin-bottom: 0.3em; 19 | font-weight: 100; 20 | color: black; } 21 | 22 | h1 { 23 | font-size: 2.5em; } 24 | 25 | h2 { 26 | font-size: 2em; 27 | border-bottom: 1px solid #e2e2e2; } 28 | 29 | h4 { 30 | font-size: 13px; 31 | line-height: 1.5; 32 | margin-top: 21px; } 33 | 34 | h5 { 35 | font-size: 1.1em; } 36 | 37 | h6 { 38 | font-size: 1.1em; 39 | color: #777; } 40 | 41 | .section-name { 42 | color: gray; 43 | display: block; 44 | font-family: Helvetica; 45 | font-size: 22px; 46 | font-weight: 100; 47 | margin-bottom: 15px; } 48 | 49 | pre, code { 50 | font: 0.95em Menlo, monospace; 51 | color: #777; 52 | word-wrap: normal; } 53 | 54 | p code, li code { 55 | background-color: #eee; 56 | padding: 2px 4px; 57 | border-radius: 4px; } 58 | 59 | a { 60 | color: #0088cc; 61 | text-decoration: none; } 62 | 63 | ul { 64 | padding-left: 15px; } 65 | 66 | li { 67 | line-height: 1.8em; } 68 | 69 | img { 70 | max-width: 100%; } 71 | 72 | blockquote { 73 | margin-left: 0; 74 | padding: 0 10px; 75 | border-left: 4px solid #ccc; } 76 | 77 | .content-wrapper { 78 | margin: 0 auto; 79 | width: 980px; } 80 | 81 | header { 82 | font-size: 0.85em; 83 | line-height: 26px; 84 | background-color: #414141; 85 | position: fixed; 86 | width: 100%; 87 | z-index: 1; } 88 | header img { 89 | padding-right: 6px; 90 | vertical-align: -4px; 91 | height: 16px; } 92 | header a { 93 | color: #fff; } 94 | header p { 95 | float: left; 96 | color: #999; } 97 | header .header-right { 98 | float: right; 99 | margin-left: 16px; } 100 | 101 | #breadcrumbs { 102 | background-color: #f2f2f2; 103 | height: 27px; 104 | padding-top: 17px; 105 | position: fixed; 106 | width: 100%; 107 | z-index: 1; 108 | margin-top: 26px; } 109 | #breadcrumbs #carat { 110 | height: 10px; 111 | margin: 0 5px; } 112 | 113 | .sidebar { 114 | background-color: #f9f9f9; 115 | border: 1px solid #e2e2e2; 116 | overflow-y: auto; 117 | overflow-x: hidden; 118 | position: fixed; 119 | top: 70px; 120 | bottom: 0; 121 | width: 230px; 122 | word-wrap: normal; } 123 | 124 | .nav-groups { 125 | list-style-type: none; 126 | background: #fff; 127 | padding-left: 0; } 128 | 129 | .nav-group-name { 130 | border-bottom: 1px solid #e2e2e2; 131 | font-size: 1.1em; 132 | font-weight: 100; 133 | padding: 15px 0 15px 20px; } 134 | .nav-group-name > a { 135 | color: #333; } 136 | 137 | .nav-group-tasks { 138 | margin-top: 5px; } 139 | 140 | .nav-group-task { 141 | font-size: 0.9em; 142 | list-style-type: none; 143 | white-space: nowrap; } 144 | .nav-group-task a { 145 | color: #888; } 146 | 147 | .main-content { 148 | background-color: #fff; 149 | border: 1px solid #e2e2e2; 150 | margin-left: 246px; 151 | position: absolute; 152 | overflow: hidden; 153 | padding-bottom: 60px; 154 | top: 70px; 155 | width: 734px; } 156 | .main-content p, .main-content a, .main-content code, .main-content em, .main-content ul, .main-content table, .main-content blockquote { 157 | margin-bottom: 1em; } 158 | .main-content p { 159 | line-height: 1.8em; } 160 | .main-content section .section:first-child { 161 | margin-top: 0; 162 | padding-top: 0; } 163 | .main-content section .task-group-section .task-group:first-of-type { 164 | padding-top: 10px; } 165 | .main-content section .task-group-section .task-group:first-of-type .section-name { 166 | padding-top: 15px; } 167 | 168 | .section { 169 | padding: 0 25px; } 170 | 171 | .highlight { 172 | background-color: #eee; 173 | padding: 10px 12px; 174 | border: 1px solid #e2e2e2; 175 | border-radius: 4px; 176 | overflow-x: auto; } 177 | 178 | .declaration .highlight { 179 | overflow-x: initial; 180 | padding: 0 40px 40px 0; 181 | margin-bottom: -25px; 182 | background-color: transparent; 183 | border: none; } 184 | 185 | .section-name { 186 | margin: 0; 187 | margin-left: 18px; } 188 | 189 | .task-group-section { 190 | padding-left: 6px; 191 | border-top: 1px solid #e2e2e2; } 192 | 193 | .task-group { 194 | padding-top: 0px; } 195 | 196 | .task-name-container a[name]:before { 197 | content: ""; 198 | display: block; 199 | padding-top: 70px; 200 | margin: -70px 0 0; } 201 | 202 | .item { 203 | padding-top: 8px; 204 | width: 100%; 205 | list-style-type: none; } 206 | .item a[name]:before { 207 | content: ""; 208 | display: block; 209 | padding-top: 70px; 210 | margin: -70px 0 0; } 211 | .item code { 212 | background-color: transparent; 213 | padding: 0; } 214 | .item .token { 215 | padding-left: 3px; 216 | margin-left: 15px; 217 | font-size: 11.9px; } 218 | .item .declaration-note { 219 | font-size: .85em; 220 | color: gray; 221 | font-style: italic; } 222 | 223 | .pointer-container { 224 | border-bottom: 1px solid #e2e2e2; 225 | left: -23px; 226 | padding-bottom: 13px; 227 | position: relative; 228 | width: 110%; } 229 | 230 | .pointer { 231 | background: #f9f9f9; 232 | border-left: 1px solid #e2e2e2; 233 | border-top: 1px solid #e2e2e2; 234 | height: 12px; 235 | left: 21px; 236 | top: -7px; 237 | -webkit-transform: rotate(45deg); 238 | -moz-transform: rotate(45deg); 239 | -o-transform: rotate(45deg); 240 | transform: rotate(45deg); 241 | position: absolute; 242 | width: 12px; } 243 | 244 | .height-container { 245 | display: none; 246 | left: -25px; 247 | padding: 0 25px; 248 | position: relative; 249 | width: 100%; 250 | overflow: hidden; } 251 | .height-container .section { 252 | background: #f9f9f9; 253 | border-bottom: 1px solid #e2e2e2; 254 | left: -25px; 255 | position: relative; 256 | width: 100%; 257 | padding-top: 10px; 258 | padding-bottom: 5px; } 259 | 260 | .aside, .language { 261 | padding: 6px 12px; 262 | margin: 12px 0; 263 | border-left: 5px solid #dddddd; 264 | overflow-y: hidden; } 265 | .aside .aside-title, .language .aside-title { 266 | font-size: 9px; 267 | letter-spacing: 2px; 268 | text-transform: uppercase; 269 | padding-bottom: 0; 270 | margin: 0; 271 | color: #aaa; 272 | -webkit-user-select: none; } 273 | .aside p:last-child, .language p:last-child { 274 | margin-bottom: 0; } 275 | 276 | .language { 277 | border-left: 5px solid #cde9f4; } 278 | .language .aside-title { 279 | color: #4b8afb; } 280 | 281 | .aside-warning { 282 | border-left: 5px solid #ff6666; } 283 | .aside-warning .aside-title { 284 | color: #ff0000; } 285 | 286 | .graybox { 287 | border-collapse: collapse; 288 | width: 100%; } 289 | .graybox p { 290 | margin: 0; 291 | word-break: break-word; 292 | min-width: 50px; } 293 | .graybox td { 294 | border: 1px solid #e2e2e2; 295 | padding: 5px 25px 5px 10px; 296 | vertical-align: middle; } 297 | .graybox tr td:first-of-type { 298 | text-align: right; 299 | padding: 7px; 300 | vertical-align: top; 301 | word-break: normal; 302 | width: 40px; } 303 | 304 | .slightly-smaller { 305 | font-size: 0.9em; } 306 | 307 | #footer { 308 | position: absolute; 309 | bottom: 10px; 310 | margin-left: 25px; } 311 | #footer p { 312 | margin: 0; 313 | color: #aaa; 314 | font-size: 0.8em; } 315 | 316 | html.dash header, html.dash #breadcrumbs, html.dash .sidebar { 317 | display: none; } 318 | html.dash .main-content { 319 | width: 980px; 320 | margin-left: 0; 321 | border: none; 322 | width: 100%; 323 | top: 0; 324 | padding-bottom: 0; } 325 | html.dash .height-container { 326 | display: block; } 327 | html.dash .item .token { 328 | margin-left: 0; } 329 | html.dash .content-wrapper { 330 | width: auto; } 331 | html.dash #footer { 332 | position: static; } 333 | -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleIdentifier 6 | com.jazzy. 7 | CFBundleName 8 | 9 | DocSetPlatformFamily 10 | 11 | isDashDocset 12 | 13 | dashIndexFilePath 14 | index.html 15 | isJavaScriptEnabled 16 | 17 | DashDocSetFamily 18 | dashtoc 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/Protocols.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Protocols Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Docs (100% documented)

17 |
18 |
19 |
20 | 25 |
26 |
27 | 59 |
60 |
61 |
62 |

Protocols

63 |

The following protocols are available globally.

64 | 65 |
66 |
67 |
68 |
    69 |
  • 70 |
    71 | 72 | 73 | 74 | ThreadQueue 75 | 76 |
    77 |
    78 |
    79 |
    80 |
    81 |
    82 |

    A thread queue which can dispatch a closure according to the queue type.

    83 | 84 | See more 85 |
    86 |
    87 |

    Declaration

    88 |
    89 |

    Swift

    90 |
    public protocol ThreadQueue
    91 | 92 |
    93 |
    94 |
    95 |
    96 |
  • 97 |
98 |
99 |
100 |
101 | 105 |
106 |
107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/Protocols/ThreadQueue.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ThreadQueue Protocol Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

Docs (100% documented)

18 |
19 |
20 |
21 | 26 |
27 |
28 | 60 |
61 |
62 |
63 |

ThreadQueue

64 |
65 |
66 |
public protocol ThreadQueue
67 | 68 |
69 |
70 |

A thread queue which can dispatch a closure according to the queue type.

71 | 72 |
73 |
74 |
75 |
    76 |
  • 77 |
    78 | 79 | 80 | 81 | name 82 | 83 |
    84 |
    85 |
    86 |
    87 |
    88 |
    89 |

    The queue name.

    90 | 91 |
    92 |
    93 |

    Declaration

    94 |
    95 |

    Swift

    96 |
    var name: String
    97 | 98 |
    99 |
    100 |
    101 |
    102 |
  • 103 |
  • 104 |
    105 | 106 | 107 | 108 | type 109 | 110 |
    111 |
    112 |
    113 |
    114 |
    115 |
    116 |

    The queue type.

    117 | 118 |
    119 |
    120 |

    Declaration

    121 |
    122 |

    Swift

    123 |
    var type: Threading.QueueType
    124 | 125 |
    126 |
    127 |
    128 |
    129 |
  • 130 |
  • 131 |
    132 | 133 | 134 | 135 | dispatch(_:) 136 | 137 |
    138 |
    139 |
    140 |
    141 |
    142 |
    143 |

    Execute the given closure within the queue’s thread.

    144 | 145 |
    146 |
    147 |

    Declaration

    148 |
    149 |

    Swift

    150 |
    func dispatch(_ closure: Threading.ThreadClosure)
    151 | 152 |
    153 |
    154 |
    155 |
    156 |
  • 157 |
158 |
159 |
160 |
161 | 165 |
166 |
167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/Structs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Structs Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Docs (100% documented)

17 |
18 |
19 |
20 | 25 |
26 |
27 | 59 |
60 |
61 |
62 |

Structs

63 |

The following structs are available globally.

64 | 65 |
66 |
67 |
68 |
    69 |
  • 70 |
    71 | 72 | 73 | 74 | Threading 75 | 76 |
    77 |
    78 |
    79 |
    80 |
    81 |
    82 |

    A wrapper around a variety of threading related functions and classes.

    83 | 84 | See more 85 |
    86 |
    87 |

    Declaration

    88 |
    89 |

    Swift

    90 |
    public struct Threading
    91 | 92 |
    93 |
    94 |
    95 |
    96 |
  • 97 |
98 |
99 |
100 |
101 | 105 |
106 |
107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/Structs/Threading/Event.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Event Class Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

Docs (100% documented)

18 |
19 |
20 |
21 | 26 |
27 |
28 | 60 |
61 |
62 |
63 |

Event

64 |
65 |
66 |
public final class Event: Lock
67 | 68 |
69 |
70 |

A thread event object. Inherits from Threading.Lock. 71 | The event MUST be locked before wait or signal is called. 72 | While inside the wait call, the event is automatically placed in the unlocked state. 73 | After wait or signal return the event will be in the locked state and must be unlocked.

74 | 75 |
76 |
77 |
78 |
    79 |
  • 80 |
    81 | 82 | 83 | 84 | init() 85 | 86 |
    87 |
    88 |
    89 |
    90 |
    91 |
    92 |

    Initialize a new Event object.

    93 | 94 |
    95 |
    96 |

    Declaration

    97 |
    98 |

    Swift

    99 |
    override public init()
    100 | 101 |
    102 |
    103 |
    104 |
    105 |
  • 106 |
  • 107 |
    108 | 109 | 110 | 111 | signal() 112 | 113 |
    114 |
    115 |
    116 |
    117 |
    118 |
    119 |

    Signal at most ONE thread which may be waiting on this event. 120 | Has no effect if there is no waiting thread.

    121 | 122 |
    123 |
    124 |

    Declaration

    125 |
    126 |

    Swift

    127 |
    public func signal() -> Bool
    128 | 129 |
    130 |
    131 |
    132 |
    133 |
  • 134 |
  • 135 |
    136 | 137 | 138 | 139 | broadcast() 140 | 141 |
    142 |
    143 |
    144 |
    145 |
    146 |
    147 |

    Signal ALL threads which may be waiting on this event. 148 | Has no effect if there is no waiting thread.

    149 | 150 |
    151 |
    152 |

    Declaration

    153 |
    154 |

    Swift

    155 |
    public func broadcast() -> Bool
    156 | 157 |
    158 |
    159 |
    160 |
    161 |
  • 162 |
  • 163 |
    164 | 165 | 166 | 167 | wait(seconds:) 168 | 169 |
    170 |
    171 |
    172 |
    173 |
    174 |
    175 |

    Wait on this event for another thread to call signal. 176 | Blocks the calling thread until a signal is received or the timeout occurs. 177 | Returns true only if the signal was received. 178 | Returns false upon timeout or error.

    179 | 180 |
    181 |
    182 |

    Declaration

    183 |
    184 |

    Swift

    185 |
    public func wait(seconds secs: Double = Threading.noTimeout) -> Bool
    186 | 187 |
    188 |
    189 |
    190 |
    191 |
  • 192 |
193 |
194 |
195 |
196 | 200 |
201 |
202 | 203 | 204 | 205 | -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/Structs/Threading/Lock.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Lock Class Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

Docs (100% documented)

18 |
19 |
20 |
21 | 26 |
27 |
28 | 60 |
61 |
62 |
63 |

Lock

64 |
65 |
66 |
public class Lock
67 | 68 |
69 |
70 |

A mutex-type thread lock. 71 | The lock can be held by only one thread. Other threads attempting to secure the lock while it is held will block. 72 | The lock is initialized as being recursive. The locking thread may lock multiple times, but each lock should be accompanied by an unlock.

73 | 74 |
75 |
76 |
77 |
    78 |
  • 79 |
    80 | 81 | 82 | 83 | init() 84 | 85 |
    86 |
    87 |
    88 |
    89 |
    90 |
    91 |

    Initialize a new lock object.

    92 | 93 |
    94 |
    95 |

    Declaration

    96 |
    97 |

    Swift

    98 |
    public init()
    99 | 100 |
    101 |
    102 |
    103 |
    104 |
  • 105 |
  • 106 |
    107 | 108 | 109 | 110 | lock() 111 | 112 |
    113 |
    114 |
    115 |
    116 |
    117 |
    118 |

    Attempt to grab the lock. 119 | Returns true if the lock was successful.

    120 | 121 |
    122 |
    123 |

    Declaration

    124 |
    125 |

    Swift

    126 |
    public func lock() -> Bool
    127 | 128 |
    129 |
    130 |
    131 |
    132 |
  • 133 |
  • 134 |
    135 | 136 | 137 | 138 | tryLock() 139 | 140 |
    141 |
    142 |
    143 |
    144 |
    145 |
    146 |

    Attempt to grab the lock. 147 | Will only return true if the lock was not being held by any other thread. 148 | Returns false if the lock is currently being held by another thread.

    149 | 150 |
    151 |
    152 |

    Declaration

    153 |
    154 |

    Swift

    155 |
    public func tryLock() -> Bool
    156 | 157 |
    158 |
    159 |
    160 |
    161 |
  • 162 |
  • 163 |
    164 | 165 | 166 | 167 | unlock() 168 | 169 |
    170 |
    171 |
    172 |
    173 |
    174 |
    175 |

    Unlock. Returns true if the lock was held by the current thread and was successfully unlocked. ior the lock count was decremented.

    176 | 177 |
    178 |
    179 |

    Declaration

    180 |
    181 |

    Swift

    182 |
    public func unlock() -> Bool
    183 | 184 |
    185 |
    186 |
    187 |
    188 |
  • 189 |
  • 190 |
    191 | 192 | 193 | 194 | doWithLock(_:) 195 | 196 |
    197 |
    198 |
    199 |
    200 |
    201 |
    202 |

    Acquire the lock, execute the closure, release the lock.

    203 | 204 |
    205 |
    206 |

    Declaration

    207 |
    208 |

    Swift

    209 |
    public func doWithLock(closure: () throws -> ()) rethrows
    210 | 211 |
    212 |
    213 |
    214 |
    215 |
  • 216 |
217 |
218 |
219 |
220 | 224 |
225 |
226 | 227 | 228 | 229 | -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/Structs/Threading/QueueType.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | QueueType Enum Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

Docs (100% documented)

18 |
19 |
20 |
21 | 26 |
27 |
28 | 60 |
61 |
62 |
63 |

QueueType

64 |
65 |
66 |
public enum QueueType
67 | 68 |
69 |
70 |

Queue type indicator.

71 | 72 |
73 |
74 |
75 |
    76 |
  • 77 |
    78 | 79 | 80 | 81 | serial 82 | 83 |
    84 |
    85 |
    86 |
    87 |
    88 |
    89 |

    A queue which operates on only one thread.

    90 | 91 |
    92 |
    93 |

    Declaration

    94 |
    95 |

    Swift

    96 |
    case serial
    97 | 98 |
    99 |
    100 |
    101 |
    102 |
  • 103 |
104 |
105 |
106 |
    107 |
  • 108 |
    109 | 110 | 111 | 112 | concurrent 113 | 114 |
    115 |
    116 |
    117 |
    118 |
    119 |
    120 |

    A queue which operates on a number of threads, usually equal to the number of logical CPUs.

    121 | 122 |
    123 |
    124 |

    Declaration

    125 |
    126 |

    Swift

    127 |
    case concurrent
    128 | 129 |
    130 |
    131 |
    132 |
    133 |
  • 134 |
135 |
136 |
137 |
138 | 142 |
143 |
144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/Structs/Threading/RWLock.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | RWLock Class Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

Docs (100% documented)

18 |
19 |
20 |
21 | 26 |
27 |
28 | 60 |
61 |
62 |
63 |

RWLock

64 |
65 |
66 |
public final class RWLock
67 | 68 |
69 |
70 |

A read-write thread lock. 71 | Permits multiple readers to hold the while, while only allowing at most one writer to hold the lock. 72 | For a writer to acquire the lock all readers must have unlocked. 73 | For a reader to acquire the lock no writers must hold the lock.

74 | 75 |
76 |
77 |
78 |
    79 |
  • 80 |
    81 | 82 | 83 | 84 | init() 85 | 86 |
    87 |
    88 |
    89 |
    90 |
    91 |
    92 |

    Initialize a new read-write lock.

    93 | 94 |
    95 |
    96 |

    Declaration

    97 |
    98 |

    Swift

    99 |
    public init()
    100 | 101 |
    102 |
    103 |
    104 |
    105 |
  • 106 |
  • 107 |
    108 | 109 | 110 | 111 | readLock() 112 | 113 |
    114 |
    115 |
    116 |
    117 |
    118 |
    119 |

    Attempt to acquire the lock for reading. 120 | Returns false if an error occurs.

    121 | 122 |
    123 |
    124 |

    Declaration

    125 |
    126 |

    Swift

    127 |
    public func readLock() -> Bool
    128 | 129 |
    130 |
    131 |
    132 |
    133 |
  • 134 |
  • 135 |
    136 | 137 | 138 | 139 | tryReadLock() 140 | 141 |
    142 |
    143 |
    144 |
    145 |
    146 |
    147 |

    Attempts to acquire the lock for reading. 148 | Returns false if the lock is held by a writer or an error occurs.

    149 | 150 |
    151 |
    152 |

    Declaration

    153 |
    154 |

    Swift

    155 |
    public func tryReadLock() -> Bool
    156 | 157 |
    158 |
    159 |
    160 |
    161 |
  • 162 |
  • 163 |
    164 | 165 | 166 | 167 | writeLock() 168 | 169 |
    170 |
    171 |
    172 |
    173 |
    174 |
    175 |

    Attempt to acquire the lock for writing. 176 | Returns false if an error occurs.

    177 | 178 |
    179 |
    180 |

    Declaration

    181 |
    182 |

    Swift

    183 |
    public func writeLock() -> Bool
    184 | 185 |
    186 |
    187 |
    188 |
    189 |
  • 190 |
  • 191 |
    192 | 193 | 194 | 195 | tryWriteLock() 196 | 197 |
    198 |
    199 |
    200 |
    201 |
    202 |
    203 |

    Attempt to acquire the lock for writing. 204 | Returns false if the lock is held by readers or a writer or an error occurs.

    205 | 206 |
    207 |
    208 |

    Declaration

    209 |
    210 |

    Swift

    211 |
    public func tryWriteLock() -> Bool
    212 | 213 |
    214 |
    215 |
    216 |
    217 |
  • 218 |
  • 219 |
    220 | 221 | 222 | 223 | unlock() 224 | 225 |
    226 |
    227 |
    228 |
    229 |
    230 |
    231 |

    Unlock a lock which is held for either reading or writing. 232 | Returns false if an error occurs.

    233 | 234 |
    235 |
    236 |

    Declaration

    237 |
    238 |

    Swift

    239 |
    public func unlock() -> Bool
    240 | 241 |
    242 |
    243 |
    244 |
    245 |
  • 246 |
  • 247 |
    248 | 249 | 250 | 251 | doWithReadLock(_:) 252 | 253 |
    254 |
    255 |
    256 |
    257 |
    258 |
    259 |

    Acquire the read lock, execute the closure, release the lock.

    260 | 261 |
    262 |
    263 |

    Declaration

    264 |
    265 |

    Swift

    266 |
    public func doWithReadLock(closure: () throws -> ()) rethrows
    267 | 268 |
    269 |
    270 |
    271 |
    272 |
  • 273 |
  • 274 |
    275 | 276 | 277 | 278 | doWithWriteLock(_:) 279 | 280 |
    281 |
    282 |
    283 |
    284 |
    285 |
    286 |

    Acquire the write lock, execute the closure, release the lock.

    287 | 288 |
    289 |
    290 |

    Declaration

    291 |
    292 |

    Swift

    293 |
    public func doWithWriteLock(closure: () throws -> ()) rethrows
    294 | 295 |
    296 |
    297 |
    298 |
    299 |
  • 300 |
301 |
302 |
303 |
304 | 308 |
309 |
310 | 311 | 312 | 313 | -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/css/highlight.css: -------------------------------------------------------------------------------- 1 | /* Credit to https://gist.github.com/wataru420/2048287 */ 2 | .highlight { 3 | /* Comment */ 4 | /* Error */ 5 | /* Keyword */ 6 | /* Operator */ 7 | /* Comment.Multiline */ 8 | /* Comment.Preproc */ 9 | /* Comment.Single */ 10 | /* Comment.Special */ 11 | /* Generic.Deleted */ 12 | /* Generic.Deleted.Specific */ 13 | /* Generic.Emph */ 14 | /* Generic.Error */ 15 | /* Generic.Heading */ 16 | /* Generic.Inserted */ 17 | /* Generic.Inserted.Specific */ 18 | /* Generic.Output */ 19 | /* Generic.Prompt */ 20 | /* Generic.Strong */ 21 | /* Generic.Subheading */ 22 | /* Generic.Traceback */ 23 | /* Keyword.Constant */ 24 | /* Keyword.Declaration */ 25 | /* Keyword.Pseudo */ 26 | /* Keyword.Reserved */ 27 | /* Keyword.Type */ 28 | /* Literal.Number */ 29 | /* Literal.String */ 30 | /* Name.Attribute */ 31 | /* Name.Builtin */ 32 | /* Name.Class */ 33 | /* Name.Constant */ 34 | /* Name.Entity */ 35 | /* Name.Exception */ 36 | /* Name.Function */ 37 | /* Name.Namespace */ 38 | /* Name.Tag */ 39 | /* Name.Variable */ 40 | /* Operator.Word */ 41 | /* Text.Whitespace */ 42 | /* Literal.Number.Float */ 43 | /* Literal.Number.Hex */ 44 | /* Literal.Number.Integer */ 45 | /* Literal.Number.Oct */ 46 | /* Literal.String.Backtick */ 47 | /* Literal.String.Char */ 48 | /* Literal.String.Doc */ 49 | /* Literal.String.Double */ 50 | /* Literal.String.Escape */ 51 | /* Literal.String.Heredoc */ 52 | /* Literal.String.Interpol */ 53 | /* Literal.String.Other */ 54 | /* Literal.String.Regex */ 55 | /* Literal.String.Single */ 56 | /* Literal.String.Symbol */ 57 | /* Name.Builtin.Pseudo */ 58 | /* Name.Variable.Class */ 59 | /* Name.Variable.Global */ 60 | /* Name.Variable.Instance */ 61 | /* Literal.Number.Integer.Long */ } 62 | .highlight .c { 63 | color: #999988; 64 | font-style: italic; } 65 | .highlight .err { 66 | color: #a61717; 67 | background-color: #e3d2d2; } 68 | .highlight .k { 69 | color: #000000; 70 | font-weight: bold; } 71 | .highlight .o { 72 | color: #000000; 73 | font-weight: bold; } 74 | .highlight .cm { 75 | color: #999988; 76 | font-style: italic; } 77 | .highlight .cp { 78 | color: #999999; 79 | font-weight: bold; } 80 | .highlight .c1 { 81 | color: #999988; 82 | font-style: italic; } 83 | .highlight .cs { 84 | color: #999999; 85 | font-weight: bold; 86 | font-style: italic; } 87 | .highlight .gd { 88 | color: #000000; 89 | background-color: #ffdddd; } 90 | .highlight .gd .x { 91 | color: #000000; 92 | background-color: #ffaaaa; } 93 | .highlight .ge { 94 | color: #000000; 95 | font-style: italic; } 96 | .highlight .gr { 97 | color: #aa0000; } 98 | .highlight .gh { 99 | color: #999999; } 100 | .highlight .gi { 101 | color: #000000; 102 | background-color: #ddffdd; } 103 | .highlight .gi .x { 104 | color: #000000; 105 | background-color: #aaffaa; } 106 | .highlight .go { 107 | color: #888888; } 108 | .highlight .gp { 109 | color: #555555; } 110 | .highlight .gs { 111 | font-weight: bold; } 112 | .highlight .gu { 113 | color: #aaaaaa; } 114 | .highlight .gt { 115 | color: #aa0000; } 116 | .highlight .kc { 117 | color: #000000; 118 | font-weight: bold; } 119 | .highlight .kd { 120 | color: #000000; 121 | font-weight: bold; } 122 | .highlight .kp { 123 | color: #000000; 124 | font-weight: bold; } 125 | .highlight .kr { 126 | color: #000000; 127 | font-weight: bold; } 128 | .highlight .kt { 129 | color: #445588; } 130 | .highlight .m { 131 | color: #009999; } 132 | .highlight .s { 133 | color: #d14; } 134 | .highlight .na { 135 | color: #008080; } 136 | .highlight .nb { 137 | color: #0086B3; } 138 | .highlight .nc { 139 | color: #445588; 140 | font-weight: bold; } 141 | .highlight .no { 142 | color: #008080; } 143 | .highlight .ni { 144 | color: #800080; } 145 | .highlight .ne { 146 | color: #990000; 147 | font-weight: bold; } 148 | .highlight .nf { 149 | color: #990000; } 150 | .highlight .nn { 151 | color: #555555; } 152 | .highlight .nt { 153 | color: #000080; } 154 | .highlight .nv { 155 | color: #008080; } 156 | .highlight .ow { 157 | color: #000000; 158 | font-weight: bold; } 159 | .highlight .w { 160 | color: #bbbbbb; } 161 | .highlight .mf { 162 | color: #009999; } 163 | .highlight .mh { 164 | color: #009999; } 165 | .highlight .mi { 166 | color: #009999; } 167 | .highlight .mo { 168 | color: #009999; } 169 | .highlight .sb { 170 | color: #d14; } 171 | .highlight .sc { 172 | color: #d14; } 173 | .highlight .sd { 174 | color: #d14; } 175 | .highlight .s2 { 176 | color: #d14; } 177 | .highlight .se { 178 | color: #d14; } 179 | .highlight .sh { 180 | color: #d14; } 181 | .highlight .si { 182 | color: #d14; } 183 | .highlight .sx { 184 | color: #d14; } 185 | .highlight .sr { 186 | color: #009926; } 187 | .highlight .s1 { 188 | color: #d14; } 189 | .highlight .ss { 190 | color: #990073; } 191 | .highlight .bp { 192 | color: #999999; } 193 | .highlight .vc { 194 | color: #008080; } 195 | .highlight .vg { 196 | color: #008080; } 197 | .highlight .vi { 198 | color: #008080; } 199 | .highlight .il { 200 | color: #009999; } 201 | -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/css/jazzy.css: -------------------------------------------------------------------------------- 1 | html, body, div, span, h1, h3, h4, p, a, code, em, img, ul, li, table, tbody, tr, td { 2 | background: transparent; 3 | border: 0; 4 | margin: 0; 5 | outline: 0; 6 | padding: 0; 7 | vertical-align: baseline; } 8 | 9 | body { 10 | background-color: #f2f2f2; 11 | font-family: Helvetica, freesans, Arial, sans-serif; 12 | font-size: 14px; 13 | -webkit-font-smoothing: subpixel-antialiased; 14 | word-wrap: break-word; } 15 | 16 | h1, h2, h3 { 17 | margin-top: 0.8em; 18 | margin-bottom: 0.3em; 19 | font-weight: 100; 20 | color: black; } 21 | 22 | h1 { 23 | font-size: 2.5em; } 24 | 25 | h2 { 26 | font-size: 2em; 27 | border-bottom: 1px solid #e2e2e2; } 28 | 29 | h4 { 30 | font-size: 13px; 31 | line-height: 1.5; 32 | margin-top: 21px; } 33 | 34 | h5 { 35 | font-size: 1.1em; } 36 | 37 | h6 { 38 | font-size: 1.1em; 39 | color: #777; } 40 | 41 | .section-name { 42 | color: gray; 43 | display: block; 44 | font-family: Helvetica; 45 | font-size: 22px; 46 | font-weight: 100; 47 | margin-bottom: 15px; } 48 | 49 | pre, code { 50 | font: 0.95em Menlo, monospace; 51 | color: #777; 52 | word-wrap: normal; } 53 | 54 | p code, li code { 55 | background-color: #eee; 56 | padding: 2px 4px; 57 | border-radius: 4px; } 58 | 59 | a { 60 | color: #0088cc; 61 | text-decoration: none; } 62 | 63 | ul { 64 | padding-left: 15px; } 65 | 66 | li { 67 | line-height: 1.8em; } 68 | 69 | img { 70 | max-width: 100%; } 71 | 72 | blockquote { 73 | margin-left: 0; 74 | padding: 0 10px; 75 | border-left: 4px solid #ccc; } 76 | 77 | .content-wrapper { 78 | margin: 0 auto; 79 | width: 980px; } 80 | 81 | header { 82 | font-size: 0.85em; 83 | line-height: 26px; 84 | background-color: #414141; 85 | position: fixed; 86 | width: 100%; 87 | z-index: 1; } 88 | header img { 89 | padding-right: 6px; 90 | vertical-align: -4px; 91 | height: 16px; } 92 | header a { 93 | color: #fff; } 94 | header p { 95 | float: left; 96 | color: #999; } 97 | header .header-right { 98 | float: right; 99 | margin-left: 16px; } 100 | 101 | #breadcrumbs { 102 | background-color: #f2f2f2; 103 | height: 27px; 104 | padding-top: 17px; 105 | position: fixed; 106 | width: 100%; 107 | z-index: 1; 108 | margin-top: 26px; } 109 | #breadcrumbs #carat { 110 | height: 10px; 111 | margin: 0 5px; } 112 | 113 | .sidebar { 114 | background-color: #f9f9f9; 115 | border: 1px solid #e2e2e2; 116 | overflow-y: auto; 117 | overflow-x: hidden; 118 | position: fixed; 119 | top: 70px; 120 | bottom: 0; 121 | width: 230px; 122 | word-wrap: normal; } 123 | 124 | .nav-groups { 125 | list-style-type: none; 126 | background: #fff; 127 | padding-left: 0; } 128 | 129 | .nav-group-name { 130 | border-bottom: 1px solid #e2e2e2; 131 | font-size: 1.1em; 132 | font-weight: 100; 133 | padding: 15px 0 15px 20px; } 134 | .nav-group-name > a { 135 | color: #333; } 136 | 137 | .nav-group-tasks { 138 | margin-top: 5px; } 139 | 140 | .nav-group-task { 141 | font-size: 0.9em; 142 | list-style-type: none; 143 | white-space: nowrap; } 144 | .nav-group-task a { 145 | color: #888; } 146 | 147 | .main-content { 148 | background-color: #fff; 149 | border: 1px solid #e2e2e2; 150 | margin-left: 246px; 151 | position: absolute; 152 | overflow: hidden; 153 | padding-bottom: 60px; 154 | top: 70px; 155 | width: 734px; } 156 | .main-content p, .main-content a, .main-content code, .main-content em, .main-content ul, .main-content table, .main-content blockquote { 157 | margin-bottom: 1em; } 158 | .main-content p { 159 | line-height: 1.8em; } 160 | .main-content section .section:first-child { 161 | margin-top: 0; 162 | padding-top: 0; } 163 | .main-content section .task-group-section .task-group:first-of-type { 164 | padding-top: 10px; } 165 | .main-content section .task-group-section .task-group:first-of-type .section-name { 166 | padding-top: 15px; } 167 | 168 | .section { 169 | padding: 0 25px; } 170 | 171 | .highlight { 172 | background-color: #eee; 173 | padding: 10px 12px; 174 | border: 1px solid #e2e2e2; 175 | border-radius: 4px; 176 | overflow-x: auto; } 177 | 178 | .declaration .highlight { 179 | overflow-x: initial; 180 | padding: 0 40px 40px 0; 181 | margin-bottom: -25px; 182 | background-color: transparent; 183 | border: none; } 184 | 185 | .section-name { 186 | margin: 0; 187 | margin-left: 18px; } 188 | 189 | .task-group-section { 190 | padding-left: 6px; 191 | border-top: 1px solid #e2e2e2; } 192 | 193 | .task-group { 194 | padding-top: 0px; } 195 | 196 | .task-name-container a[name]:before { 197 | content: ""; 198 | display: block; 199 | padding-top: 70px; 200 | margin: -70px 0 0; } 201 | 202 | .item { 203 | padding-top: 8px; 204 | width: 100%; 205 | list-style-type: none; } 206 | .item a[name]:before { 207 | content: ""; 208 | display: block; 209 | padding-top: 70px; 210 | margin: -70px 0 0; } 211 | .item code { 212 | background-color: transparent; 213 | padding: 0; } 214 | .item .token { 215 | padding-left: 3px; 216 | margin-left: 15px; 217 | font-size: 11.9px; } 218 | .item .declaration-note { 219 | font-size: .85em; 220 | color: gray; 221 | font-style: italic; } 222 | 223 | .pointer-container { 224 | border-bottom: 1px solid #e2e2e2; 225 | left: -23px; 226 | padding-bottom: 13px; 227 | position: relative; 228 | width: 110%; } 229 | 230 | .pointer { 231 | background: #f9f9f9; 232 | border-left: 1px solid #e2e2e2; 233 | border-top: 1px solid #e2e2e2; 234 | height: 12px; 235 | left: 21px; 236 | top: -7px; 237 | -webkit-transform: rotate(45deg); 238 | -moz-transform: rotate(45deg); 239 | -o-transform: rotate(45deg); 240 | transform: rotate(45deg); 241 | position: absolute; 242 | width: 12px; } 243 | 244 | .height-container { 245 | display: none; 246 | left: -25px; 247 | padding: 0 25px; 248 | position: relative; 249 | width: 100%; 250 | overflow: hidden; } 251 | .height-container .section { 252 | background: #f9f9f9; 253 | border-bottom: 1px solid #e2e2e2; 254 | left: -25px; 255 | position: relative; 256 | width: 100%; 257 | padding-top: 10px; 258 | padding-bottom: 5px; } 259 | 260 | .aside, .language { 261 | padding: 6px 12px; 262 | margin: 12px 0; 263 | border-left: 5px solid #dddddd; 264 | overflow-y: hidden; } 265 | .aside .aside-title, .language .aside-title { 266 | font-size: 9px; 267 | letter-spacing: 2px; 268 | text-transform: uppercase; 269 | padding-bottom: 0; 270 | margin: 0; 271 | color: #aaa; 272 | -webkit-user-select: none; } 273 | .aside p:last-child, .language p:last-child { 274 | margin-bottom: 0; } 275 | 276 | .language { 277 | border-left: 5px solid #cde9f4; } 278 | .language .aside-title { 279 | color: #4b8afb; } 280 | 281 | .aside-warning { 282 | border-left: 5px solid #ff6666; } 283 | .aside-warning .aside-title { 284 | color: #ff0000; } 285 | 286 | .graybox { 287 | border-collapse: collapse; 288 | width: 100%; } 289 | .graybox p { 290 | margin: 0; 291 | word-break: break-word; 292 | min-width: 50px; } 293 | .graybox td { 294 | border: 1px solid #e2e2e2; 295 | padding: 5px 25px 5px 10px; 296 | vertical-align: middle; } 297 | .graybox tr td:first-of-type { 298 | text-align: right; 299 | padding: 7px; 300 | vertical-align: top; 301 | word-break: normal; 302 | width: 40px; } 303 | 304 | .slightly-smaller { 305 | font-size: 0.9em; } 306 | 307 | #footer { 308 | position: absolute; 309 | bottom: 10px; 310 | margin-left: 25px; } 311 | #footer p { 312 | margin: 0; 313 | color: #aaa; 314 | font-size: 0.8em; } 315 | 316 | html.dash header, html.dash #breadcrumbs, html.dash .sidebar { 317 | display: none; } 318 | html.dash .main-content { 319 | width: 980px; 320 | margin-left: 0; 321 | border: none; 322 | width: 100%; 323 | top: 0; 324 | padding-bottom: 0; } 325 | html.dash .height-container { 326 | display: block; } 327 | html.dash .item .token { 328 | margin-left: 0; } 329 | html.dash .content-wrapper { 330 | width: auto; } 331 | html.dash #footer { 332 | position: static; } 333 | -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/img/carat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerfectlySoft/Perfect-Thread/a50b9a33f08fce638f33ae3121613fe499cc23ec/docs/docsets/.docset/Contents/Resources/Documents/img/carat.png -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/img/dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerfectlySoft/Perfect-Thread/a50b9a33f08fce638f33ae3121613fe499cc23ec/docs/docsets/.docset/Contents/Resources/Documents/img/dash.png -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/img/gh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerfectlySoft/Perfect-Thread/a50b9a33f08fce638f33ae3121613fe499cc23ec/docs/docsets/.docset/Contents/Resources/Documents/img/gh.png -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Docs (100% documented)

17 |
18 |
19 |
20 | 25 |
26 |
27 | 59 |
60 |
61 |
62 | 63 |

Perfect-Thread

64 | 65 |

Core threading package used in Perfect. Includes support for serial and concurrent thread queues, locks, read/write locks and events.

66 | 67 |
68 |
69 | 73 |
74 |
75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/js/jazzy.js: -------------------------------------------------------------------------------- 1 | window.jazzy = {'docset': false} 2 | if (typeof window.dash != 'undefined') { 3 | document.documentElement.className += ' dash' 4 | window.jazzy.docset = true 5 | } 6 | if (navigator.userAgent.match(/xcode/i)) { 7 | document.documentElement.className += ' xcode' 8 | window.jazzy.docset = true 9 | } 10 | 11 | // On doc load, toggle the URL hash discussion if present 12 | $(document).ready(function() { 13 | if (!window.jazzy.docset) { 14 | var linkToHash = $('a[href="' + window.location.hash +'"]'); 15 | linkToHash.trigger("click"); 16 | } 17 | }); 18 | 19 | // On token click, toggle its discussion and animate token.marginLeft 20 | $(".token").click(function(event) { 21 | if (window.jazzy.docset) { 22 | return; 23 | } 24 | var link = $(this); 25 | var animationDuration = 300; 26 | var tokenOffset = "15px"; 27 | var original = link.css('marginLeft') == tokenOffset; 28 | link.animate({'margin-left':original ? "0px" : tokenOffset}, animationDuration); 29 | $content = link.parent().parent().next(); 30 | $content.slideToggle(animationDuration); 31 | 32 | // Keeps the document from jumping to the hash. 33 | var href = $(this).attr('href'); 34 | if (history.pushState) { 35 | history.pushState({}, '', href); 36 | } else { 37 | location.hash = href; 38 | } 39 | event.preventDefault(); 40 | }); 41 | -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/Documents/undocumented.json: -------------------------------------------------------------------------------- 1 | {"warnings":[],"source_directory":"/Users/kjessup/development/PerfectNeu/Perfect-Thread"} -------------------------------------------------------------------------------- /docs/docsets/.docset/Contents/Resources/docSet.dsidx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerfectlySoft/Perfect-Thread/a50b9a33f08fce638f33ae3121613fe499cc23ec/docs/docsets/.docset/Contents/Resources/docSet.dsidx -------------------------------------------------------------------------------- /docs/docsets/.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerfectlySoft/Perfect-Thread/a50b9a33f08fce638f33ae3121613fe499cc23ec/docs/docsets/.tgz -------------------------------------------------------------------------------- /docs/img/carat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerfectlySoft/Perfect-Thread/a50b9a33f08fce638f33ae3121613fe499cc23ec/docs/img/carat.png -------------------------------------------------------------------------------- /docs/img/dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerfectlySoft/Perfect-Thread/a50b9a33f08fce638f33ae3121613fe499cc23ec/docs/img/dash.png -------------------------------------------------------------------------------- /docs/img/gh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PerfectlySoft/Perfect-Thread/a50b9a33f08fce638f33ae3121613fe499cc23ec/docs/img/gh.png -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Reference 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Docs (100% documented)

17 |
18 |
19 |
20 | 25 |
26 |
27 | 59 |
60 |
61 |
62 | 63 |

Perfect-Thread

64 | 65 |

Core threading package used in Perfect. Includes support for serial and concurrent thread queues, locks, read/write locks and events.

66 | 67 |
68 |
69 | 73 |
74 |
75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /docs/js/jazzy.js: -------------------------------------------------------------------------------- 1 | window.jazzy = {'docset': false} 2 | if (typeof window.dash != 'undefined') { 3 | document.documentElement.className += ' dash' 4 | window.jazzy.docset = true 5 | } 6 | if (navigator.userAgent.match(/xcode/i)) { 7 | document.documentElement.className += ' xcode' 8 | window.jazzy.docset = true 9 | } 10 | 11 | // On doc load, toggle the URL hash discussion if present 12 | $(document).ready(function() { 13 | if (!window.jazzy.docset) { 14 | var linkToHash = $('a[href="' + window.location.hash +'"]'); 15 | linkToHash.trigger("click"); 16 | } 17 | }); 18 | 19 | // On token click, toggle its discussion and animate token.marginLeft 20 | $(".token").click(function(event) { 21 | if (window.jazzy.docset) { 22 | return; 23 | } 24 | var link = $(this); 25 | var animationDuration = 300; 26 | var tokenOffset = "15px"; 27 | var original = link.css('marginLeft') == tokenOffset; 28 | link.animate({'margin-left':original ? "0px" : tokenOffset}, animationDuration); 29 | $content = link.parent().parent().next(); 30 | $content.slideToggle(animationDuration); 31 | 32 | // Keeps the document from jumping to the hash. 33 | var href = $(this).attr('href'); 34 | if (history.pushState) { 35 | history.pushState({}, '', href); 36 | } else { 37 | location.hash = href; 38 | } 39 | event.preventDefault(); 40 | }); 41 | -------------------------------------------------------------------------------- /docs/undocumented.json: -------------------------------------------------------------------------------- 1 | {"warnings":[],"source_directory":"/Users/kjessup/development/PerfectNeu/Perfect-Thread"} --------------------------------------------------------------------------------