Skip to content

Commit 43deddf

Browse files
author
Dave Abrahams
committed
[stdlib] Move ManagedBuffer prototype into stdlib
...in preparation to use it in _[Contiguous]ArrayBuffer Swift SVN r22440
1 parent b6f28be commit 43deddf

File tree

3 files changed

+119
-134
lines changed

3 files changed

+119
-134
lines changed

stdlib/core/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ set(SWIFTLIB_ESSENTIAL
5656
LazyCollection.swift.gyb
5757
LazySequence.swift
5858
LifetimeManager.swift
59+
ManagedBuffer.swift
5960
Map.swift.gyb
6061
Mirrors.swift.gyb
6162
Misc.swift
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//===--- HeapStorage.swift - Replacement for HeapBuffer -------------------===//
1+
//===--- ManagedBuffer.swift - variable-sized buffer of aligned memory ---===//
22
//
33
// This source file is part of the Swift.org open source project
44
//
@@ -9,39 +9,12 @@
99
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
1010
//
1111
//===----------------------------------------------------------------------===//
12-
//
13-
//
14-
//
15-
//===----------------------------------------------------------------------===//
16-
// RUN: %target-build-swift -parse-stdlib -Xfrontend -disable-access-control %s -o %t.out
17-
// RUN: %target-run %t.out
1812

19-
import Swift
20-
import Darwin
2113
import SwiftShims
22-
import StdlibUnittest
23-
24-
typealias _HeapObject = SwiftShims.HeapObject
25-
26-
// This is already in the standard library
27-
func _roundUpToAlignment(offset: Int, alignment: Int) -> Int {
28-
_sanityCheck(offset >= 0)
29-
_sanityCheck(alignment > 0)
30-
// Note, given that offset is >= 0, and alignment > 0, we don't
31-
// need to underflow check the -1, as it can never underflow.
32-
let x = (offset + alignment &- 1)
33-
// Note, as alignment is a power of 2, we'll use masking to efficiently
34-
// get the aligned value
35-
return x & ~(alignment &- 1)
36-
}
3714

38-
@asmname("swift_bufferAllocate")
39-
func _swift_bufferAllocate(
40-
bufferType: AnyClass, size: Int, alignMask: Int) -> AnyObject
41-
42-
/// A class containing a property of type `Value` and
43-
/// raw storage for an array of `Element` whose size is
44-
/// determined at create time.
15+
/// A class whose instances contain a property of type `Value` and raw
16+
/// storage for an array of `Element`, whose size is determined at
17+
/// instance creation.
4518
///
4619
/// Note that the `Element` array is suitably-aligned **raw memory**.
4720
/// You are expected to construct and---if necessary---destroy objects
@@ -50,23 +23,23 @@ func _swift_bufferAllocate(
5023
/// any live elements in the `deinit` of a subclass. Note: subclasses
5124
/// must not have any stored properties; any storage needed should be
5225
/// included in `Value`.
53-
public class HeapStorage<Value, Element> {
26+
public class ManagedBuffer<Value, Element> {
5427

5528
/// Create a new instance of the most-derived class, calling
5629
/// `initialize` on the partially-constructed object to generate an
5730
/// initial `Value`. Note, in particular, accessing `value` inside
5831
/// the `initialize` function is undefined.
5932
public final class func create(
60-
minimumCapacity: Int, initialize: (HeapStorage)->Value
61-
) -> HeapStorage {
33+
minimumCapacity: Int, initialize: (ManagedBuffer)->Value
34+
) -> ManagedBuffer {
6235
_precondition(
6336
minimumCapacity >= 0,
64-
"HeapStorage must have non-negative capacity")
37+
"ManagedBuffer must have non-negative capacity")
6538

66-
let totalSize = HeapStorage._elementOffset
39+
let totalSize = ManagedBuffer._elementOffset
6740
+ minimumCapacity * strideof(Element.self)
6841

69-
let alignMask = HeapStorage._alignmentMask
42+
let alignMask = ManagedBuffer._alignmentMask
7043

7144
let result = self._allocate(totalSize, alignMask: alignMask)
7245

@@ -79,7 +52,7 @@ public class HeapStorage<Value, Element> {
7952
// helper function for create, above
8053
internal final class func _allocate(
8154
totalSize: Int, alignMask: Int
82-
) -> HeapStorage {
55+
) -> ManagedBuffer {
8356
return unsafeDowncast(
8457
_swift_bufferAllocate(self, totalSize, alignMask)
8558
)
@@ -119,9 +92,9 @@ public class HeapStorage<Value, Element> {
11992
/// The actual number of elements allocated for this object. May be
12093
/// nontrivial to compute; it may be a good idea to store this
12194
/// information in the value area upon creation.
122-
internal final var _allocatedElementCount : Int {
95+
public final var allocatedElementCount : Int {
12396
return (
124-
_allocatedByteCount &- HeapStorage._elementOffset &+ sizeof(Element) &- 1
97+
_allocatedByteCount &- ManagedBuffer._elementOffset &+ sizeof(Element) &- 1
12598
) &/ sizeof(Element)
12699
}
127100

@@ -159,8 +132,8 @@ public class HeapStorage<Value, Element> {
159132
body: (_: UnsafeMutablePointer<Value>, _: UnsafeMutablePointer<Element>)->R
160133
) -> R {
161134
let result = body(
162-
UnsafeMutablePointer(_address + HeapStorage._valueOffset),
163-
UnsafeMutablePointer(_address + HeapStorage._elementOffset)
135+
UnsafeMutablePointer(_address + ManagedBuffer._valueOffset),
136+
UnsafeMutablePointer(_address + ManagedBuffer._elementOffset)
164137
)
165138
_fixLifetime(self)
166139
return result
@@ -186,97 +159,6 @@ public class HeapStorage<Value, Element> {
186159
/// allocated size. Probably completely unused per
187160
/// <rdar://problem/18156440>
188161
internal final func __getInstanceSizeAndAlignMask() -> (Int,Int) {
189-
return (_allocatedByteCount, HeapStorage._alignmentMask)
162+
return (_allocatedByteCount, ManagedBuffer._alignmentMask)
190163
}
191164
}
192-
193-
//===----------------------------------------------------------------------===//
194-
//===--- Testing code -----------------------------------------------------===//
195-
//===----------------------------------------------------------------------===//
196-
197-
struct CountAndCapacity {
198-
var count: LifetimeTracked
199-
let capacity: Int = 0
200-
}
201-
202-
// An example of HeapStorage, very similar to what Array will use.
203-
// However, only half of the element storage is actually used to store
204-
// elements, as a simple way of catching potential bugs.
205-
final class TestHeapStorage<T> : HeapStorage<CountAndCapacity,T> {
206-
class func create(capacity: Int) -> TestHeapStorage {
207-
let r = self.create(capacity) {
208-
CountAndCapacity(
209-
count: LifetimeTracked(0), capacity: $0._allocatedElementCount)
210-
}
211-
return r as TestHeapStorage
212-
}
213-
214-
var count: Int {
215-
get {
216-
return value.count.value
217-
}
218-
set {
219-
value.count = LifetimeTracked(newValue)
220-
}
221-
}
222-
223-
var capacity: Int {
224-
return value.capacity
225-
}
226-
227-
deinit {
228-
teardown()
229-
}
230-
231-
// This doesn't seem to compile properly when embedded directly in
232-
// deinit.
233-
func teardown() {
234-
let count = self.count
235-
236-
withUnsafeMutablePointerToElements {
237-
(x: UnsafeMutablePointer<T>)->() in
238-
for i in stride(from: 0, to: count, by: 2) {
239-
(x + i).destroy()
240-
}
241-
}
242-
}
243-
244-
func append(x: T) {
245-
let count = self.count
246-
precondition(count + 2 <= capacity)
247-
248-
withUnsafeMutablePointerToElements {
249-
(p: UnsafeMutablePointer<T>)->() in
250-
(p + count).initialize(x)
251-
}
252-
self.count = count + 2
253-
}
254-
}
255-
256-
var tests = TestSuite("HeapStorage")
257-
258-
tests.test("basic") {
259-
expectEqual(0, LifetimeTracked.instances)
260-
if true {
261-
let s = TestHeapStorage<LifetimeTracked>.create(0)
262-
expectEqual(1, LifetimeTracked.instances)
263-
}
264-
265-
expectEqual(0, LifetimeTracked.instances)
266-
if true {
267-
let s = TestHeapStorage<LifetimeTracked>.create(10)
268-
expectEqual(0, s.count)
269-
expectLE(10, s.capacity)
270-
expectGE(12, s.capacity) // allow some over-allocation but not too much
271-
272-
expectEqual(1, LifetimeTracked.instances)
273-
for i in 1..<6 {
274-
s.append(LifetimeTracked(i))
275-
expectEqual(i + 1, LifetimeTracked.instances)
276-
expectEqual(i * 2, s.count)
277-
}
278-
}
279-
expectEqual(0, LifetimeTracked.instances)
280-
}
281-
282-
runAllTests()

test/stdlib/ManagedBuffer.swift

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
//===--- ManagedBuffer.swift ----------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
// RUN: %target-run-simple-swift
13+
14+
import StdlibUnittest
15+
16+
struct CountAndCapacity {
17+
var count: LifetimeTracked
18+
let capacity: Int = 0
19+
}
20+
21+
// An example of ManagedBuffer, very similar to what Array will use.
22+
// However, only half of the element storage is actually used to store
23+
// elements, interleaved with garbage, as a simple way of catching
24+
// potential bugs.
25+
final class TestManagedBuffer<T> : ManagedBuffer<CountAndCapacity,T> {
26+
class func create(capacity: Int) -> TestManagedBuffer {
27+
let r = super.create(capacity) {
28+
CountAndCapacity(
29+
count: LifetimeTracked(0), capacity: $0.allocatedElementCount)
30+
}
31+
return r as TestManagedBuffer
32+
}
33+
34+
var count: Int {
35+
get {
36+
return value.count.value
37+
}
38+
set {
39+
value.count = LifetimeTracked(newValue)
40+
}
41+
}
42+
43+
var capacity: Int {
44+
return value.capacity
45+
}
46+
47+
deinit {
48+
teardown()
49+
}
50+
51+
// This doesn't seem to compile properly when embedded directly in
52+
// deinit.
53+
func teardown() {
54+
let count = self.count
55+
56+
withUnsafeMutablePointerToElements {
57+
(x: UnsafeMutablePointer<T>)->() in
58+
for i in stride(from: 0, to: count, by: 2) {
59+
(x + i).destroy()
60+
}
61+
}
62+
}
63+
64+
func append(x: T) {
65+
let count = self.count
66+
precondition(count + 2 <= capacity)
67+
68+
withUnsafeMutablePointerToElements {
69+
(p: UnsafeMutablePointer<T>)->() in
70+
(p + count).initialize(x)
71+
}
72+
self.count = count + 2
73+
}
74+
}
75+
76+
var tests = TestSuite("ManagedBuffer")
77+
78+
tests.test("basic") {
79+
expectEqual(0, LifetimeTracked.instances)
80+
if true {
81+
let s = TestManagedBuffer<LifetimeTracked>.create(0)
82+
expectEqual(1, LifetimeTracked.instances)
83+
}
84+
85+
expectEqual(0, LifetimeTracked.instances)
86+
if true {
87+
let s = TestManagedBuffer<LifetimeTracked>.create(10)
88+
expectEqual(0, s.count)
89+
expectLE(10, s.capacity)
90+
expectGE(12, s.capacity) // allow some over-allocation but not too much
91+
92+
expectEqual(1, LifetimeTracked.instances)
93+
for i in 1..<6 {
94+
s.append(LifetimeTracked(i))
95+
expectEqual(i + 1, LifetimeTracked.instances)
96+
expectEqual(i * 2, s.count)
97+
}
98+
}
99+
expectEqual(0, LifetimeTracked.instances)
100+
}
101+
102+
runAllTests()

0 commit comments

Comments
 (0)