@@ -35,9 +35,8 @@ public class ManagedProtoBuffer<Value, Element> : NonObjectiveCBase {
35
35
/// idea to store this information in the "value" area when
36
36
/// an instance is created.
37
37
public final var allocatedElementCount : Int {
38
- return (
39
- _allocatedByteCount &- ManagedProtoBuffer . _elementOffset &+ sizeof ( Element) &- 1
40
- ) &/ sizeof ( Element)
38
+ let p = ManagedBufferPointer < Value , Element > ( self )
39
+ return p. allocatedElementCount
41
40
}
42
41
43
42
/// Call `body` with an `UnsafeMutablePointer` to the stored `Value`
@@ -59,12 +58,7 @@ public class ManagedProtoBuffer<Value, Element> : NonObjectiveCBase {
59
58
public final func withUnsafeMutablePointers< R> (
60
59
body: ( _: UnsafeMutablePointer < Value > , _: UnsafeMutablePointer < Element > ) -> R
61
60
) -> R {
62
- let result = body (
63
- UnsafeMutablePointer ( _address + ManagedProtoBuffer. _valueOffset) ,
64
- UnsafeMutablePointer ( _address + ManagedProtoBuffer. _elementOffset)
65
- )
66
- _fixLifetime ( self )
67
- return result
61
+ return ManagedBufferPointer ( self ) . withUnsafeMutablePointers ( body)
68
62
}
69
63
70
64
//===--- internal/private API -------------------------------------------===//
@@ -73,41 +67,6 @@ public class ManagedProtoBuffer<Value, Element> : NonObjectiveCBase {
73
67
internal init ( _doNotCallMe: ( ) ) {
74
68
_sanityCheckFailure ( " Only initialize these by calling create " )
75
69
}
76
-
77
- /// The required alignment for allocations of this type, minus 1
78
- internal final class var _alignmentMask : Int {
79
- return max (
80
- alignof ( _HeapObject. self) ,
81
- max ( alignof ( Value . self) , alignof ( Element . self) ) ) &- 1
82
- }
83
-
84
- /// The actual number of bytes allocated for this object.
85
- internal final var _allocatedByteCount : Int {
86
- return Int ( bitPattern: malloc_size ( unsafeAddressOf ( self ) ) )
87
- }
88
-
89
- /// The address of this instance in a convenient pointer-to-bytes form
90
- internal final var _address : UnsafePointer < UInt8 > {
91
- return UnsafePointer ( unsafeAddressOf ( self ) )
92
- }
93
-
94
- /// Offset from the allocated storage for `self` to the stored `Value`
95
- internal final class var _valueOffset : Int {
96
- return _roundUpToAlignment ( sizeof ( _HeapObject. self) , alignof ( Value . self) )
97
- }
98
-
99
- /// Offset from the allocated storage for `self` to the `Element` storage
100
- internal final class var _elementOffset : Int {
101
- return _roundUpToAlignment (
102
- _valueOffset + sizeof( Value . self) , alignof ( Element . self) )
103
- }
104
-
105
- /// A hack that gives the deallocator information about our
106
- /// allocated size. Probably completely unused per
107
- /// <rdar://problem/18156440>
108
- internal final func __getInstanceSizeAndAlignMask( ) -> ( Int , Int ) {
109
- return ( _allocatedByteCount, ManagedProtoBuffer . _alignmentMask)
110
- }
111
70
}
112
71
113
72
/// A class whose instances contain a property of type `Value` and raw
@@ -125,58 +84,255 @@ public class ManagedBuffer<Value, Element>
125
84
: ManagedProtoBuffer < Value , Element > {
126
85
127
86
/// Create a new instance of the most-derived class, calling
128
- /// `initialize` on the partially-constructed object to generate an
129
- /// initial `Value`.
130
- ///
131
- /// Note, in particular, accessing `value` inside the `initialize`
132
- /// function is undefined.
87
+ /// `initializeValue` on the partially-constructed object to
88
+ /// generate an initial `Value`.
133
89
public final class func create(
134
- minimumCapacity: Int , initialize: ( ManagedProtoBuffer < Value , Element > ) -> Value
135
- ) -> ManagedBuffer {
90
+ minimumCapacity: Int ,
91
+ initialValue: ( ManagedProtoBuffer < Value , Element > ) -> Value
92
+ ) -> ManagedBuffer < Value , Element > {
93
+
94
+ let p = ManagedBufferPointer < Value , Element > (
95
+ bufferClass: self ,
96
+ minimumCapacity: minimumCapacity,
97
+ { buffer, _ in initialValue (
98
+ // FIXME: should be an unsafeDowncast <rdar://problem/18618169>
99
+ Builtin . bridgeFromRawPointer ( Builtin . bridgeToRawPointer ( buffer) ) )
100
+ } )
101
+
102
+ // FIXME: should be an unsafeDowncast <rdar://problem/18618169>
103
+ return Builtin . bridgeFromRawPointer ( Builtin . bridgeToRawPointer ( p. buffer) )
104
+ }
105
+
106
+ /// Destroy the stored Value
107
+ deinit {
108
+ ManagedBufferPointer ( self ) . withUnsafeMutablePointerToValue { $0. destroy ( ) }
109
+ }
110
+
111
+ /// The stored `Value` instance.
112
+ public final var value : Value {
113
+ address {
114
+ return ManagedBufferPointer ( self ) . withUnsafeMutablePointerToValue {
115
+ UnsafePointer ( $0)
116
+ }
117
+ }
118
+ mutableAddress {
119
+ return ManagedBufferPointer ( self ) . withUnsafeMutablePointerToValue { $0 }
120
+ }
121
+ }
122
+ }
123
+
124
+ /// Contains a buffer object, and provides access to an instance of
125
+ /// `Value` and contiguous storage for an arbitrary number of
126
+ /// `Element` instances stored in that buffer.
127
+ ///
128
+ /// For most purposes, the `ManagedBuffer` class works fine for this
129
+ /// purpose, and can simply be used on its own. However, in cases
130
+ /// where objects of various different classes must serve as storage,
131
+ /// `ManagedBufferPointer` is needed.
132
+ ///
133
+ /// A valid buffer class is non-`@objc`, with no declared stored
134
+ /// properties. Its `deinit` must destroy its
135
+ /// stored `Value` and any constructed `Elements`.
136
+ ///
137
+ /// Example Buffer Class
138
+ /// --------------------
139
+ ///
140
+ /// ::
141
+ ///
142
+ /// class MyBuffer<Element> { // non-@objc
143
+ /// typealias Manager = ManagedBufferPointer<(Int,String), Element>
144
+ /// deinit {
145
+ /// Manager(unsafeBufferObject: self).withUnsafeMutablePointers {
146
+ /// (pointerToValue, pointerToElements)->Void in
147
+ /// pointerToElements.destroy(self.count)
148
+ /// pointerToValue.destroy()
149
+ /// }
150
+ /// }
151
+ ///
152
+ /// // All properties are *computed* based on members of the Value
153
+ /// var count : Int {
154
+ /// return Manager(unsafeBufferObject: self).value.0
155
+ /// }
156
+ /// var name : String {
157
+ /// return Manager(unsafeBufferObject: self).value.1
158
+ /// }
159
+ /// }
160
+ ///
161
+ public struct ManagedBufferPointer < Value, Element> : Equatable {
162
+
163
+ /// Create with new storage containing an initial `Value` and space
164
+ /// for at least `minimumCapacity` `element`\ s.
165
+ ///
166
+ /// :param: `bufferClass` - the class of the object used for storage.
167
+ /// :param: `minimumCapacity` - the minimum number of `Elements` that
168
+ /// must be able to be stored in the new buffer.
169
+ /// :param: `initialValue` - a function that produces the initial
170
+ /// `Value` instance stored in the buffer, given the `buffer`
171
+ /// object and a function that can be called on it to get the actual
172
+ /// number of allocated elements.
173
+ ///
174
+ /// Requires: minimumCapacity >= 0, and the type indicated by
175
+ /// `bufferClass` is a non-`@objc` class with no declared stored
176
+ /// properties. The `deinit` of `bufferClass` must destroy its
177
+ /// stored `Value` and any constructed `Elements`.
178
+ public init (
179
+ bufferClass: AnyClass ,
180
+ minimumCapacity: Int ,
181
+ initialValue: ( buffer: AnyObject , allocatedCount: ( AnyObject ) -> Int ) -> Value
182
+ ) {
183
+ ManagedBufferPointer . _checkValidBufferClass ( bufferClass)
136
184
_precondition (
137
185
minimumCapacity >= 0 ,
138
- " ManagedBuffer must have non-negative capacity" )
186
+ " ManagedBufferPointer must have non-negative capacity" )
139
187
140
- let totalSize = ManagedBuffer . _elementOffset
188
+ let totalSize = _My . _elementOffset
141
189
+ minimumCapacity * strideof( Element . self)
142
190
143
- let alignMask = ManagedBuffer . _alignmentMask
191
+ let newBuffer : AnyObject = _swift_bufferAllocate (
192
+ bufferClass, totalSize, _My. _alignmentMask)
144
193
145
- let result : ManagedBuffer = unsafeDowncast (
146
- _swift_bufferAllocate ( self , totalSize, alignMask)
147
- )
148
-
149
- result. withUnsafeMutablePointerToValue {
150
- $0. initialize ( initialize ( result) )
151
- }
152
- return result
153
- }
194
+ self . _nativeBuffer = Builtin . castToNativeObject ( newBuffer)
154
195
155
- /// Destroy the stored Value
156
- deinit {
157
- // FIXME: doing the work in a helper is a workaround for
158
- // <rdar://problem/18158010>
159
- _deinit ( )
196
+ // initialize the value field
197
+ withUnsafeMutablePointerToValue {
198
+ $0. initialize (
199
+ initialValue (
200
+ buffer: newBuffer,
201
+ allocatedCount: {
202
+ ManagedBufferPointer ( unsafeBufferObject: $0) . allocatedElementCount
203
+ } ) )
204
+ }
160
205
}
161
206
162
- // FIXME: separating this from the real deinit is a workaround for
163
- // <rdar://problem/18158010>
164
- /// The guts of deinit(); do not call
165
- internal final func _deinit( ) {
166
- withUnsafeMutablePointerToValue { $0. destroy ( ) }
207
+ /// Manage the given `buffer`.
208
+ ///
209
+ /// Requires: `buffer` is an instance of a non-`@objc` class with no
210
+ /// declared stored properties, whose `deinit` destroys its
211
+ /// stored `Value` and any constructed `Elements`.
212
+ public init ( unsafeBufferObject buffer: AnyObject ) {
213
+ ManagedBufferPointer . _checkValidBufferClass ( buffer. dynamicType)
214
+ self . _nativeBuffer = Builtin . castToNativeObject ( buffer)
167
215
}
168
216
169
217
/// The stored `Value` instance.
170
- ///
171
- /// Note: this value must not be accessed during instance creation.
172
- public final var value : Value {
218
+ public var value : Value {
219
+ /*
173
220
address {
174
221
return withUnsafeMutablePointerToValue { UnsafePointer($0) }
175
222
}
176
223
mutableAddress {
177
224
return withUnsafeMutablePointerToValue { $0 }
178
225
}
226
+ */
227
+ // FIXME: <rdar://problem/18619176> replace get/set with
228
+ // addressors => link error
229
+ get { return withUnsafeMutablePointerToValue { $0. memory } }
230
+ set { withUnsafeMutablePointerToValue { $0. memory = newValue } }
179
231
}
232
+
233
+ /// Return the object instance being used for storage.
234
+ public var buffer : AnyObject {
235
+ return Builtin . castFromNativeObject ( _nativeBuffer)
236
+ }
237
+
238
+ /// The actual number of elements that can be stored in this object.
239
+ ///
240
+ /// This value may be nontrivial to compute; it is usually a good
241
+ /// idea to store this information in the "value" area when
242
+ /// an instance is created.
243
+ public var allocatedElementCount : Int {
244
+ return (
245
+ _allocatedByteCount &- _My. _elementOffset &+ sizeof ( Element) &- 1
246
+ ) &/ sizeof ( Element)
247
+ }
248
+
249
+ /// Call `body` with an `UnsafeMutablePointer` to the stored `Value`
250
+ public func withUnsafeMutablePointerToValue< R> (
251
+ body: ( UnsafeMutablePointer < Value > ) -> R
252
+ ) -> R {
253
+ return withUnsafeMutablePointers { ( v, e) in return body ( v) }
254
+ }
255
+
256
+ /// Call body with an `UnsafeMutablePointer` to the `Element` storage
257
+ public func withUnsafeMutablePointerToElements< R> (
258
+ body: ( UnsafeMutablePointer < Element > ) -> R
259
+ ) -> R {
260
+ return withUnsafeMutablePointers { return body ( $0. 1 ) }
261
+ }
262
+
263
+ /// Call body with `UnsafeMutablePointer`\ s to the stored `Value`
264
+ /// and raw `Element` storage
265
+ public func withUnsafeMutablePointers< R> (
266
+ body: ( _: UnsafeMutablePointer < Value > , _: UnsafeMutablePointer < Element > ) -> R
267
+ ) -> R {
268
+ let result = body (
269
+ UnsafeMutablePointer ( _address + _My. _valueOffset) ,
270
+ UnsafeMutablePointer ( _address + _My. _elementOffset)
271
+ )
272
+ _fixLifetime ( _nativeBuffer)
273
+ return result
274
+ }
275
+
276
+ //===--- internal/private API -------------------------------------------===//
277
+
278
+ /// Manage the given `buffer`.
279
+ ///
280
+ /// **Note:** it is an error to use the `value` property of the resulting
281
+ /// instance unless it has been initialized.
282
+ internal init ( _ buffer: ManagedProtoBuffer < Value , Element > ) {
283
+ _nativeBuffer = Builtin . castToNativeObject ( buffer)
284
+ }
285
+
286
+ internal typealias _My = ManagedBufferPointer
287
+
288
+ internal static func _checkValidBufferClass( bufferClass: AnyClass ) {
289
+ _debugPrecondition (
290
+ _class_getInstanceSize ( bufferClass)
291
+ == _class_getInstanceSize ( ManagedBuffer< Int, Int> . self ) ,
292
+ " ManagedBufferPointer buffer class has declared stored properties "
293
+ )
294
+ _debugPrecondition (
295
+ _usesNativeSwiftReferenceCounting ( bufferClass) ,
296
+ " ManagedBufferPointer buffer class must be non-@objc "
297
+ )
298
+ }
299
+
300
+ /// The required alignment for allocations of this type, minus 1
301
+ internal static var _alignmentMask : Int {
302
+ return max (
303
+ alignof ( _HeapObject. self) ,
304
+ max ( alignof ( Value . self) , alignof ( Element . self) ) ) &- 1
305
+ }
306
+
307
+ /// The actual number of bytes allocated for this object.
308
+ internal var _allocatedByteCount : Int {
309
+ return Int ( bitPattern: malloc_size ( _address) )
310
+ }
311
+
312
+ /// The address of this instance in a convenient pointer-to-bytes form
313
+ internal var _address : UnsafePointer < UInt8 > {
314
+ return UnsafePointer ( Builtin . bridgeToRawPointer ( _nativeBuffer) )
315
+ }
316
+
317
+ /// Offset from the allocated storage for `self` to the stored `Value`
318
+ internal static var _valueOffset : Int {
319
+ return _roundUpToAlignment ( sizeof ( _HeapObject. self) , alignof ( Value . self) )
320
+ }
321
+
322
+ /// Offset from the allocated storage for `self` to the `Element` storage
323
+ internal static var _elementOffset : Int {
324
+ return _roundUpToAlignment (
325
+ _valueOffset + sizeof( Value . self) , alignof ( Element . self) )
326
+ }
327
+
328
+ internal var _nativeBuffer : Builtin . NativeObject
329
+ }
330
+
331
+ public func == < Value, Element> (
332
+ lhs: ManagedBufferPointer < Value , Element > ,
333
+ rhs: ManagedBufferPointer < Value , Element >
334
+ ) -> Bool {
335
+ return lhs. _address == rhs. _address
180
336
}
181
337
182
338
// FIXME: when our calling convention changes to pass self at +0,
0 commit comments