Skip to content

Commit 2351723

Browse files
ayushi2103weissiFranzBusch
authored
feat: Implement Copy-On-Write (CoW) behavior for Logger struct (#297)
* feat: Implement Copy-On-Write (CoW) behavior for Logger struct * fix: refactored the struct and added test * fix: refactored the struct * fix: refactored the struct * fix:Added compiler directive and @usableFromInline/@inlinable * fix: Add endif label * fix: Remove colon causing expected type * fix: Add inlinable and moving compiler derective * nit * fix: add inlinable * Update Sources/Logging/Logging.swift Co-authored-by: Johannes Weiss <[email protected]> * Update Sources/Logging/Logging.swift Co-authored-by: Johannes Weiss <[email protected]> * Update Sources/Logging/Logging.swift Co-authored-by: Franz Busch <[email protected]> * Update Sources/Logging/Logging.swift Co-authored-by: Franz Busch <[email protected]> * fix: add self to class declaration and fixed formatting * fix: make label public * fix: format * fix: remove setter * test: added a test case --------- Co-authored-by: Johannes Weiss <[email protected]> Co-authored-by: Franz Busch <[email protected]>
1 parent c7dcb55 commit 2351723

File tree

2 files changed

+55
-5
lines changed

2 files changed

+55
-5
lines changed

Sources/Logging/Logging.swift

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,20 +39,56 @@ import WASILibc
3939
/// logger.info("Hello World!")
4040
/// ```
4141
public struct Logger {
42+
/// Storage class to hold the label and log handler
4243
@usableFromInline
43-
var handler: LogHandler
44+
internal final class Storage: @unchecked /* and not actually */ Sendable /* but safe if only used with CoW */ {
45+
@usableFromInline
46+
var label: String
4447

45-
/// An identifier of the creator of this `Logger`.
46-
public let label: String
48+
@usableFromInline
49+
var handler: LogHandler
50+
51+
@inlinable
52+
init(label: String, handler: LogHandler) {
53+
self.label = label
54+
self.handler = handler
55+
}
56+
57+
@inlinable
58+
func copy() -> Storage {
59+
return Storage(label: self.label, handler: self.handler)
60+
}
61+
}
62+
63+
@usableFromInline
64+
internal var _storage: Storage
65+
public var label: String {
66+
return self._storage.label
67+
}
68+
69+
/// A computed property to access the `LogHandler`.
70+
@inlinable
71+
public var handler: LogHandler {
72+
get {
73+
return self._storage.handler
74+
}
75+
set {
76+
if !isKnownUniquelyReferenced(&self._storage) {
77+
self._storage = self._storage.copy()
78+
}
79+
self._storage.handler = newValue
80+
}
81+
}
4782

4883
/// The metadata provider this logger was created with.
84+
@inlinable
4985
public var metadataProvider: Logger.MetadataProvider? {
5086
return self.handler.metadataProvider
5187
}
5288

89+
@usableFromInline
5390
internal init(label: String, _ handler: LogHandler) {
54-
self.label = label
55-
self.handler = handler
91+
self._storage = Storage(label: label, handler: handler)
5692
}
5793
}
5894

Tests/LoggingTests/LoggingTest.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,6 +1039,20 @@ class LoggingTest: XCTestCase {
10391039
LoggingSystem.bootstrap(StreamLogHandler.standardOutput, metadataProvider: .exampleMetadataProvider)
10401040
LoggingSystem.bootstrap(StreamLogHandler.standardError, metadataProvider: .exampleMetadataProvider)
10411041
}
1042+
1043+
func testLoggerIsJustHoldingASinglePointer() {
1044+
let expectedSize = MemoryLayout<UnsafeRawPointer>.size
1045+
XCTAssertEqual(MemoryLayout<Logger>.size, expectedSize)
1046+
}
1047+
1048+
func testLoggerCopyOnWrite() {
1049+
var logger1 = Logger(label: "foo")
1050+
logger1.logLevel = .error
1051+
var logger2 = logger1
1052+
logger2.logLevel = .trace
1053+
XCTAssertEqual(.error, logger1.logLevel)
1054+
XCTAssertEqual(.trace, logger2.logLevel)
1055+
}
10421056
}
10431057

10441058
extension Logger {

0 commit comments

Comments
 (0)