Skip to content

Commit

Permalink
Fix memory management issues and take advantage of Swift 5.7+
Browse files Browse the repository at this point in the history
  • Loading branch information
rhx committed Jun 15, 2024
1 parent 56c5715 commit 93be8af
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 81 deletions.
6 changes: 3 additions & 3 deletions Sources/GLib/RefList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// GLib
//
// Created by Rene Hexel on 5/1/21.
// Copyright © 2021, 2022, 2023 Rene Hexel. All rights reserved.
// Copyright © 2021, 2022, 2023, 2024 Rene Hexel. All rights reserved.
//
import CGLib
import GLib
Expand Down Expand Up @@ -35,8 +35,8 @@ public extension RefListProtocol {
/// that wraps a pointer to an underlying `GLib` type
/// (which typically is the case for `Ref` types).
@inlinable var element: Element! {
guard var data = data else { return nil }
return withUnsafeBytes(of: &data) {
guard let data = data else { return nil }
return withUnsafeBytes(of: data) {
$0.baseAddress.map {
Element(raw: $0.assumingMemoryBound(to: UnsafeMutableRawPointer.self).pointee)
}
Expand Down
6 changes: 3 additions & 3 deletions Sources/GLib/RefSList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// GLib
//
// Created by Rene Hexel on 5/1/21.
// Copyright © 2021, 2022, 2023 Rene Hexel. All rights reserved.
// Copyright © 2021, 2022, 2023, 2024 Rene Hexel. All rights reserved.
//
import CGLib
import GLib
Expand Down Expand Up @@ -39,8 +39,8 @@ public extension RefSListProtocol {
/// node pointer is treated as pointing to `Element`
@inlinable var element: Element! {
assert(MemoryLayout<Element>.size == MemoryLayout<gpointer>.size)
guard var data = data else { return nil }
return withUnsafeBytes(of: &data) {
guard let data = data else { return nil }
return withUnsafeBytes(of: data) {
$0.baseAddress.map { Element(raw: $0.assumingMemoryBound(to: UnsafeMutableRawPointer.self).pointee) }
}
}
Expand Down
26 changes: 13 additions & 13 deletions Sources/GLib/RefSequence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// GLib
//
// Created by Rene Hexel on 5/1/21.
// Copyright © 2021, 2022, 2023 Rene Hexel. All rights reserved.
// Copyright © 2021, 2022, 2023, 2024 Rene Hexel. All rights reserved.
//
import CGLib
import GLib
Expand Down Expand Up @@ -66,23 +66,18 @@ public extension RefSequenceProtocol {
/// treat the node data as a pointer to the given element.
@inlinable subscript(position: SequenceIterRef) -> Element {
get {
guard var data = position.sequenceGet() else {
guard let data = position.sequenceGet() else {
fatalError("Invalid subscript index at \(position.position)")
}
return withUnsafeBytes(of: &data) {
return withUnsafeBytes(of: data) {
$0.baseAddress.map {
Element(raw: $0.assumingMemoryBound(to: UnsafeMutableRawPointer.self).pointee)
}
}!
}
set {
var pointerValue = newValue.ptr
withUnsafeBytes(of: &pointerValue) {
#if swift(>=5.7)
withUnsafeBytes(of: newValue.ptr) {
position.sequenceSet(data: $0.assumingMemoryBound(to: gpointer.self).baseAddress?.pointee)
#else
position.sequenceSet(data: $0.baseAddress?.assumingMemoryBound(to: gpointer.self).pointee)
#endif
}
}
}
Expand Down Expand Up @@ -226,10 +221,15 @@ public struct RefSequenceIterator<Element: PointerWrapper>: IteratorProtocol {

/// Return the next element in the list
/// - Returns: a pointer to the next element in the list or `nil` if the end of the list has been reached
@inlinable public mutating func next() -> Element? {
defer { iterator = iterator?.next() }
guard var data = iterator?.sequenceGet() else { return nil }
return withUnsafeBytes(of: &data) {
@inlinable
public mutating func next() -> Element? {
guard let iterator, !iterator.isEnd,
let data = iterator.sequenceGet() else {
self.iterator = nil
return nil
}
defer { self.iterator = iterator.next() }
return withUnsafeBytes(of: data) {
$0.baseAddress.map {
Element(raw: $0.assumingMemoryBound(to: UnsafeMutableRawPointer.self).pointee)
}
Expand Down
17 changes: 7 additions & 10 deletions Sources/GLib/ReferenceList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// GLib
//
// Created by Rene Hexel on 5/1/21.
// Copyright © 2021, 2022, 2023 Rene Hexel. All rights reserved.
// Copyright © 2021, 2022, 2023, 2024 Rene Hexel. All rights reserved.
//
import CGLib

Expand Down Expand Up @@ -35,8 +35,8 @@ public extension ReferenceListProtocol {
/// (which typically is the case for `Ref` types).
@inlinable var element: Element! {
assert(MemoryLayout<Element>.size == MemoryLayout<gpointer>.size)
guard var data = data else { return nil }
return withUnsafeBytes(of: &data) {
guard let data else { return nil }
return withUnsafeBytes(of: data) {
$0.baseAddress?.assumingMemoryBound(to: Element.self).pointee
}
}
Expand All @@ -57,18 +57,15 @@ public class ReferenceList<Element>: List, ReferenceListProtocol, ExpressibleByA
/// that will be freed upon deallocation.
///
/// - Parameter elements: The elements to initialise the sequence with
@inlinable required public init(arrayLiteral elements: Element...) {
@inlinable
required public init(arrayLiteral elements: Element...) {
var last: UnsafeMutablePointer<GList>! = nil
freeNodes = true
for var element in elements.reversed() {
withUnsafeMutableBytes(of: &element) {
#if swift(>=5.7)
for element in elements.reversed() {
withUnsafeBytes(of: element) {
$0.withMemoryRebound(to: gpointer.self) {
last = g_list_prepend(last, $0.baseAddress?.pointee)
}
#else
last = g_list_prepend(last, $0.baseAddress?.assumingMemoryBound(to: gpointer.self).pointee)
#endif
}
}
super.init(last)
Expand Down
17 changes: 7 additions & 10 deletions Sources/GLib/ReferenceSList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// GLib
//
// Created by Rene Hexel on 5/1/21.
// Copyright © 2021, 2022, 2023 Rene Hexel. All rights reserved.
// Copyright © 2021, 2022, 2023, 2024 Rene Hexel. All rights reserved.
//
import CGLib

Expand Down Expand Up @@ -38,8 +38,8 @@ public extension ReferenceSListProtocol {
/// node pointer is treated as pointing to `Element`
@inlinable var element: Element! {
assert(MemoryLayout<Element>.size == MemoryLayout<gpointer>.size)
guard var data = data else { return nil }
return withUnsafeBytes(of: &data) {
guard let data = data else { return nil }
return withUnsafeBytes(of: data) {
$0.baseAddress?.assumingMemoryBound(to: Element.self).pointee
}
}
Expand All @@ -60,18 +60,15 @@ public class ReferenceSList<Element>: SList, ReferenceSListProtocol, Expressible
/// that will be freed upon deallocation.
///
/// - Parameter elements: The elements to initialise the sequence with
@inlinable required public init(arrayLiteral elements: Element...) {
@inlinable
required public init(arrayLiteral elements: Element...) {
var last: UnsafeMutablePointer<GSList>! = nil
freeNodes = true
for var element in elements.reversed() {
withUnsafeMutableBytes(of: &element) {
#if swift(>=5.7)
for element in elements.reversed() {
withUnsafeBytes(of: element) {
$0.withMemoryRebound(to: gpointer.self) {
last = g_slist_prepend(last, $0.baseAddress?.pointee)
}
#else
last = g_slist_prepend(last, $0.baseAddress?.assumingMemoryBound(to: gpointer.self).pointee)
#endif
}
}
super.init(last)
Expand Down
33 changes: 17 additions & 16 deletions Sources/GLib/ReferenceSequence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// GLib
//
// Created by Rene Hexel on 5/1/21.
// Copyright © 2021, 2022, 2023 Rene Hexel. All rights reserved.
// Copyright © 2021, 2022, 2023, 2024 Rene Hexel. All rights reserved.
//
import CGLib

Expand Down Expand Up @@ -66,22 +66,17 @@ public extension ReferenceSequenceProtocol {
@inlinable subscript(position: SequenceIterRef) -> Element {
get {
assert(MemoryLayout<Element>.size == MemoryLayout<gpointer>.size)
guard var data = position.sequenceGet() else {
guard let data = position.sequenceGet() else {
fatalError("Invalid subscript index at \(position.position)")
}
return withUnsafeBytes(of: &data) {
return withUnsafeBytes(of: data) {
$0.baseAddress?.assumingMemoryBound(to: Element.self).pointee
}!
}
set {
assert(MemoryLayout<Element>.size == MemoryLayout<gpointer>.size)
var pointerValue = newValue
withUnsafeBytes(of: &pointerValue) {
#if swift(>=5.7)
withUnsafeBytes(of: newValue) {
position.sequenceSet(data: $0.assumingMemoryBound(to: gpointer.self).baseAddress?.pointee)
#else
position.sequenceSet(data: $0.baseAddress?.assumingMemoryBound(to: gpointer.self).pointee)
#endif
}
}
}
Expand All @@ -105,10 +100,11 @@ public class ReferenceSequence<Element>: Sequence, ReferenceSequenceProtocol, Ex
/// that will be freed upon deallocation.
///
/// - Parameter elements: The elements to initialise the sequence with
@inlinable required public init(arrayLiteral elements: Element...) {
@inlinable
required public init(arrayLiteral elements: Element...) {
super.init(retaining: g_sequence_new(nil))
for var element in elements {
withUnsafeMutablePointer(to: &element) {
for element in elements {
withUnsafePointer(to: element) {
$0.withMemoryRebound(to: gpointer.self, capacity: 1) {
append(data: $0.pointee)
}
Expand Down Expand Up @@ -230,10 +226,15 @@ public struct ReferenceSequenceIterator<Element>: IteratorProtocol {

/// Return the next element in the list
/// - Returns: a pointer to the next element in the list or `nil` if the end of the list has been reached
@inlinable public mutating func next() -> Element? {
defer { iterator = iterator?.next() }
guard var data = iterator?.sequenceGet() else { return nil }
return withUnsafeBytes(of: &data) {
@inlinable
public mutating func next() -> Element? {
guard let iterator, !iterator.isEnd,
let data = iterator.sequenceGet() else {
self.iterator = nil
return nil
}
defer { self.iterator = iterator.next() }
return withUnsafeBytes(of: data) {
$0.baseAddress?.assumingMemoryBound(to: Element.self).pointee
}
}
Expand Down
9 changes: 4 additions & 5 deletions Sources/GLib/TypedList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// GLib
//
// Created by Rene Hexel on 5/1/21.
// Copyright © 2021, 2022, 2023 Rene Hexel. All rights reserved.
// Copyright © 2021, 2022, 2023, 2024 Rene Hexel. All rights reserved.
//
import CGLib

Expand All @@ -17,6 +17,7 @@ import CGLib
/// Alternatively, use `TypedListRef` as a lighweight, `unowned` reference
/// if you already have an instance you just want to use.
///
/// - Note: This colection type is mainly for primitive types. For referencing GLib objects, use `ReferenceListProtocol`.
public protocol TypedListProtocol: ListProtocol, Swift.Sequence {
/// The element contained in each `GList` node.
associatedtype Element
Expand All @@ -39,19 +40,16 @@ public extension TypedListProtocol {
/// If `Element` is not pointer size, the list
/// node pointer is treated as pointing to `Element`
@inlinable var element: Element! {
#if swift(>=5.7)
data?.withMemoryRebound(to: Element.self, capacity: 1) {
$0.pointee
}
#else
data?.assumingMemoryBound(to: Element.self).pointee
#endif
}
}

/// The `TypedList` class acts as a typed wrapper around `GList`,
/// with the associated `Element` representing the type of
/// the elements stored in the list.
/// - Note: This collection type is mainly for primitive types. For referencing GLib objects, use `ReferenceList`.
public class TypedList<Element>: List, TypedListProtocol, ExpressibleByArrayLiteral {
/// `true` to deallocate the associated list nodes on deinit.
public var freeNodes = true
Expand Down Expand Up @@ -102,6 +100,7 @@ public class TypedList<Element>: List, TypedListProtocol, ExpressibleByArrayLite
/// The `TypedListRef` struct acts as a lightweight, typed wrapper around `GList`,
/// with the associated `Element` representing the type of
/// the elements stored in the list.
/// - Note: This collection type is mainly for primitive types. For referencing GLib objects, use `ReferenceListRef`.
public struct TypedListRef<Element>: TypedListProtocol {
public var ptr: UnsafeMutableRawPointer!
}
Expand Down
6 changes: 1 addition & 5 deletions Sources/GLib/TypedSList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// GLib
//
// Created by Rene Hexel on 5/1/21.
// Copyright © 2021, 2022, 2023 Rene Hexel. All rights reserved.
// Copyright © 2021, 2022, 2023, 2024 Rene Hexel. All rights reserved.
//
import CGLib

Expand Down Expand Up @@ -38,13 +38,9 @@ public extension TypedSListProtocol {
/// If `Element` is not pointer size, the list
/// node pointer is treated as pointing to `Element`
@inlinable var element: Element! {
#if swift(>=5.7)
data?.withMemoryRebound(to: Element.self, capacity: 1) {
$0.pointee
}
#else
data?.assumingMemoryBound(to: Element.self).pointee
#endif
}
}

Expand Down
27 changes: 11 additions & 16 deletions Sources/GLib/TypedSequence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// GLib
//
// Created by Rene Hexel on 5/1/21.
// Copyright © 2021, 2022, 2023 Rene Hexel. All rights reserved.
// Copyright © 2021, 2022, 2023, 2024 Rene Hexel. All rights reserved.
//
import CGLib

Expand Down Expand Up @@ -69,16 +69,12 @@ public extension TypedSequenceProtocol {
/// `position.sequenceGet()`).
@inlinable subscript(position: SequenceIterRef) -> Element {
get {
guard var data = position.sequenceGet() else {
guard let data = position.sequenceGet() else {
fatalError("Invalid subscript index at \(position)")
}
#if swift(>=5.7)
return data.withMemoryRebound(to: Element.self, capacity: 1) {
$0.pointee
}
#else
return data.assumingMemoryBound(to: Element.self).pointee
#endif
}
set {
let newElementPointer = UnsafeMutablePointer<Element>.allocate(capacity: 1)
Expand Down Expand Up @@ -230,21 +226,20 @@ public struct TypedSequenceIterator<Element>: IteratorProtocol {

/// Return the next element in the list
/// - Returns: a pointer to the next element in the list or `nil` if the end of the list has been reached
@inlinable public mutating func next() -> Element? {
defer { iterator = iterator?.next() }
guard var data = iterator?.sequenceGet() else { return nil }
@inlinable
public mutating func next() -> Element? {
guard let iterator, !iterator.isEnd,
let data = iterator.sequenceGet() else {
self.iterator = nil
return nil
}
defer { self.iterator = iterator.next() }
if MemoryLayout<Element>.size == MemoryLayout<gpointer>.size {
return withUnsafeBytes(of: &data) {
return withUnsafeBytes(of: data) {
$0.baseAddress?.assumingMemoryBound(to: Element.self).pointee
}!
} else {
#if swift(>=5.7)
return data.withMemoryRebound(to: Element.self, capacity: 1) {
$0.pointee
}
#else
return data.assumingMemoryBound(to: Element.self).pointee
#endif
}
}
}

0 comments on commit 93be8af

Please sign in to comment.