├── .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 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
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 | 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 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
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 |
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 |
21 | Reference
22 |
23 | Protocols Reference
24 |
25 |
26 |
27 |
59 |
60 |
61 |
62 | Protocols
63 | The following protocols are available globally.
64 |
65 |
66 |
67 |
68 |
69 |
70 |
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 |
22 | Reference
23 |
24 | ThreadQueue Protocol Reference
25 |
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 |
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 |
21 | Reference
22 |
23 | Structs Reference
24 |
25 |
26 |
27 |
59 |
60 |
61 |
62 | Structs
63 | The following structs are available globally.
64 |
65 |
66 |
67 |
68 |
69 |
70 |
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 |
22 | Reference
23 |
24 | Event Class Reference
25 |
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 |
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 |
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 |
22 | Reference
23 |
24 | Lock Class Reference
25 |
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 |
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 |
22 | Reference
23 |
24 | QueueType Enum Reference
25 |
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 |
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 |
22 | Reference
23 |
24 | RWLock Class Reference
25 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
21 | Reference
22 |
23 | Protocols Reference
24 |
25 |
26 |
27 |
59 |
60 |
61 |
62 | Protocols
63 | The following protocols are available globally.
64 |
65 |
66 |
67 |
68 |
69 |
70 |
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 |
22 | Reference
23 |
24 | ThreadQueue Protocol Reference
25 |
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 |
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 |
21 | Reference
22 |
23 | Structs Reference
24 |
25 |
26 |
27 |
59 |
60 |
61 |
62 | Structs
63 | The following structs are available globally.
64 |
65 |
66 |
67 |
68 |
69 |
70 |
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 |
22 | Reference
23 |
24 | Event Class Reference
25 |
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 |
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 |
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 |
22 | Reference
23 |
24 | Lock Class Reference
25 |
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 |
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 |
22 | Reference
23 |
24 | QueueType Enum Reference
25 |
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 |
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 |
22 | Reference
23 |
24 | RWLock Class Reference
25 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
21 | Reference
22 |
23 | Reference
24 |
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 |
21 | Reference
22 |
23 | Reference
24 |
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"}
--------------------------------------------------------------------------------