Skip to content

Commit a58963c

Browse files
committed
refactor: replace Semaphore package with native Swift actor
1 parent 25f759c commit a58963c

4 files changed

Lines changed: 43 additions & 44 deletions

File tree

Thaw.xcodeproj/project.pbxproj

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
7127A9FF2C4886D100D99DEF /* IfritStatic in Frameworks */ = {isa = PBXBuildFile; productRef = 7127A9FE2C4886D100D99DEF /* IfritStatic */; };
1515
7168EE532E281CBC00FF9830 /* AXSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 7168EE522E281CBC00FF9830 /* AXSwift */; };
1616
7188A68C2E27F9ED008F131D /* MenuBarItemService.xpc in Embed XPC Services */ = {isa = PBXBuildFile; fileRef = 7188A6832E27F9ED008F131D /* MenuBarItemService.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
17-
71A065092E680C620087DB38 /* Semaphore in Frameworks */ = {isa = PBXBuildFile; productRef = 71A065082E680C620087DB38 /* Semaphore */; };
1817
/* End PBXBuildFile section */
1918

2019
/* Begin PBXContainerItemProxy section */
@@ -97,7 +96,6 @@
9796
175061912B1543DD003144CD /* LaunchAtLogin in Frameworks */,
9897
1787C4272B16890B002F50DF /* AXSwift in Frameworks */,
9998
17F71BB52B880B4500905CBA /* CompactSlider in Frameworks */,
100-
71A065092E680C620087DB38 /* Semaphore in Frameworks */,
10199
);
102100
runOnlyForDeploymentPostprocessing = 0;
103101
};
@@ -160,7 +158,6 @@
160158
170423D82B56DE78004A2549 /* Sparkle */,
161159
17F71BB42B880B4500905CBA /* CompactSlider */,
162160
7127A9FE2C4886D100D99DEF /* IfritStatic */,
163-
71A065082E680C620087DB38 /* Semaphore */,
164161
);
165162
productName = Ice;
166163
productReference = 7166832A2A767E6A006ABF84 /* Thaw.app */;
@@ -222,7 +219,6 @@
222219
170423D72B56DE78004A2549 /* XCRemoteSwiftPackageReference "Sparkle" */,
223220
17F71BB32B880B4500905CBA /* XCRemoteSwiftPackageReference "CompactSlider" */,
224221
7127A9FB2C4881BC00D99DEF /* XCRemoteSwiftPackageReference "Ifrit" */,
225-
71A065072E680C620087DB38 /* XCRemoteSwiftPackageReference "Semaphore" */,
226222
);
227223
preferredProjectObjectVersion = 77;
228224
productRefGroup = 7166832B2A767E6A006ABF84 /* Products */;
@@ -623,14 +619,6 @@
623619
minimumVersion = 4.0.0;
624620
};
625621
};
626-
71A065072E680C620087DB38 /* XCRemoteSwiftPackageReference "Semaphore" */ = {
627-
isa = XCRemoteSwiftPackageReference;
628-
repositoryURL = "https://github.com/groue/Semaphore";
629-
requirement = {
630-
kind = upToNextMajorVersion;
631-
minimumVersion = 0.1.0;
632-
};
633-
};
634622
/* End XCRemoteSwiftPackageReference section */
635623

636624
/* Begin XCSwiftPackageProductDependency section */
@@ -664,11 +652,6 @@
664652
package = 1787C4252B16890B002F50DF /* XCRemoteSwiftPackageReference "AXSwift" */;
665653
productName = AXSwift;
666654
};
667-
71A065082E680C620087DB38 /* Semaphore */ = {
668-
isa = XCSwiftPackageProductDependency;
669-
package = 71A065072E680C620087DB38 /* XCRemoteSwiftPackageReference "Semaphore" */;
670-
productName = Semaphore;
671-
};
672655
/* End XCSwiftPackageProductDependency section */
673656
};
674657
rootObject = 716683222A767E6A006ABF84 /* Project object */;

Thaw.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 1 addition & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Thaw/MenuBar/MenuBarItems/MenuBarItemManager.swift

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,36 @@
66
import Cocoa
77
import Combine
88
import OSLog
9-
import Semaphore
9+
10+
/// Simple actor-based semaphore to prevent overlapping operations
11+
actor SimpleSemaphore {
12+
private var value: Int
13+
private var waiters: [CheckedContinuation<Void, Never>] = []
14+
15+
init(value: Int) {
16+
self.value = value
17+
}
18+
19+
func wait() async {
20+
if value > 0 {
21+
value -= 1
22+
return
23+
}
24+
25+
await withCheckedContinuation { continuation in
26+
waiters.append(continuation)
27+
}
28+
}
29+
30+
func signal() {
31+
if let waiter = waiters.first {
32+
waiters.removeFirst()
33+
waiter.resume()
34+
} else {
35+
value += 1
36+
}
37+
}
38+
}
1039

1140
/// Manager for menu bar items.
1241
@MainActor
@@ -18,7 +47,7 @@ final class MenuBarItemManager: ObservableObject {
1847
private nonisolated let logger = Logger.menuBarItemManager
1948

2049
/// Semaphore to prevent overlapping event operations.
21-
private nonisolated let eventSemaphore = AsyncSemaphore(value: 1)
50+
private let eventSemaphore = SimpleSemaphore(value: 1)
2251

2352
/// Actor for managing menu bar item cache operations.
2453
private let cacheActor = CacheActor()
@@ -1007,9 +1036,11 @@ extension MenuBarItemManager {
10071036
/// - item: The menu bar item to move.
10081037
/// - destination: The destination to move the menu bar item.
10091038
private func postMoveEvents(item: MenuBarItem, destination: MoveDestination) async throws {
1010-
try await eventSemaphore.waitUnlessCancelled()
1039+
await eventSemaphore.wait()
10111040
defer {
1012-
eventSemaphore.signal()
1041+
Task {
1042+
await eventSemaphore.signal()
1043+
}
10131044
}
10141045

10151046
var itemOrigin = try await getCurrentBounds(for: item).origin
@@ -1178,9 +1209,11 @@ extension MenuBarItemManager {
11781209
/// - item: The menu bar item to click.
11791210
/// - mouseButton: The mouse button to click the item with.
11801211
private func postClickEvents(item: MenuBarItem, mouseButton: CGMouseButton) async throws {
1181-
try await eventSemaphore.waitUnlessCancelled()
1212+
await eventSemaphore.wait()
11821213
defer {
1183-
eventSemaphore.signal()
1214+
Task {
1215+
await eventSemaphore.signal()
1216+
}
11841217
}
11851218

11861219
let clickPoint = try await getCurrentBounds(for: item).center

Thaw/Resources/Acknowledgements.rtf

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
{\rtf1\ansi\ansicpg1252\cocoartf2865
1+
{\rtf1\ansi\ansicpg1252\cocoartf2867
22
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Arial-BoldMT;\f1\fswiss\fcharset0 ArialMT;}
33
{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
44
{\*\expandedcolortbl;;\cssrgb\c0\c1\c1;}
5-
\margl1440\margr1440\vieww34360\viewh20220\viewkind0
5+
\paperw12240\paperh15840\margl1440\margr1440\vieww34360\viewh20220\viewkind0
66
\deftab720
77
\pard\pardeftab720\partightenfactor0
88

99
\f0\b\fs24 \cf2 \expnd0\expndtw0\kerning0
1010
Acknowledgements
1111
\f1\b0 \
12-
Ice uses a number of excellent open source libraries. Their licenses and copyright notices are included below.\
12+
Thaw uses a number of excellent open source libraries. Their licenses and copyright notices are included below.\
1313
\
1414

1515
\f0\b AXSwift - https://github.com/tmandry/AXSwift
@@ -44,14 +44,6 @@ The above copyright notice and this permission notice shall be included in all c
4444
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\
4545
\
4646

47-
\f0\b Semaphore - https://github.com/groue/Semaphore
48-
\f1\b0 \
49-
Copyright (c) 2022 Gwendal Rou\'e9\
50-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\
51-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\
52-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\
53-
\
54-
5547
\f0\b Sparkle - https://github.com/sparkle-project/Sparkle
5648
\f1\b0 \
5749
Copyright (c) 2006-2013 Andy Matuschak.\

0 commit comments

Comments
 (0)