]> git.proxmox.com Git - ceph.git/blob - ceph/src/arrow/go/arrow/array/data.go
import quincy 17.2.0
[ceph.git] / ceph / src / arrow / go / arrow / array / data.go
1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements. See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership. The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License. You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16
17 package array
18
19 import (
20 "hash/maphash"
21 "math/bits"
22 "sync/atomic"
23 "unsafe"
24
25 "github.com/apache/arrow/go/v6/arrow"
26 "github.com/apache/arrow/go/v6/arrow/internal/debug"
27 "github.com/apache/arrow/go/v6/arrow/memory"
28 )
29
30 // Data represents the memory and metadata of an Arrow array.
31 type Data struct {
32 refCount int64
33 dtype arrow.DataType
34 nulls int
35 offset int
36 length int
37 buffers []*memory.Buffer // TODO(sgc): should this be an interface?
38 childData []*Data // TODO(sgc): managed by ListArray, StructArray and UnionArray types
39 }
40
41 // NewData creates a new Data.
42 func NewData(dtype arrow.DataType, length int, buffers []*memory.Buffer, childData []*Data, nulls, offset int) *Data {
43 for _, b := range buffers {
44 if b != nil {
45 b.Retain()
46 }
47 }
48
49 for _, child := range childData {
50 if child != nil {
51 child.Retain()
52 }
53 }
54
55 return &Data{
56 refCount: 1,
57 dtype: dtype,
58 nulls: nulls,
59 length: length,
60 offset: offset,
61 buffers: buffers,
62 childData: childData,
63 }
64 }
65
66 // Reset sets the Data for re-use.
67 func (d *Data) Reset(dtype arrow.DataType, length int, buffers []*memory.Buffer, childData []*Data, nulls, offset int) {
68 // Retain new buffers before releasing existing buffers in-case they're the same ones to prevent accidental premature
69 // release.
70 for _, b := range buffers {
71 if b != nil {
72 b.Retain()
73 }
74 }
75 for _, b := range d.buffers {
76 if b != nil {
77 b.Release()
78 }
79 }
80 d.buffers = buffers
81
82 // Retain new children data before releasing existing children data in-case they're the same ones to prevent accidental
83 // premature release.
84 for _, d := range childData {
85 if d != nil {
86 d.Retain()
87 }
88 }
89 for _, d := range d.childData {
90 if d != nil {
91 d.Release()
92 }
93 }
94 d.childData = childData
95
96 d.dtype = dtype
97 d.length = length
98 d.nulls = nulls
99 d.offset = offset
100 }
101
102 // Retain increases the reference count by 1.
103 // Retain may be called simultaneously from multiple goroutines.
104 func (d *Data) Retain() {
105 atomic.AddInt64(&d.refCount, 1)
106 }
107
108 // Release decreases the reference count by 1.
109 // When the reference count goes to zero, the memory is freed.
110 // Release may be called simultaneously from multiple goroutines.
111 func (d *Data) Release() {
112 debug.Assert(atomic.LoadInt64(&d.refCount) > 0, "too many releases")
113
114 if atomic.AddInt64(&d.refCount, -1) == 0 {
115 for _, b := range d.buffers {
116 if b != nil {
117 b.Release()
118 }
119 }
120
121 for _, b := range d.childData {
122 b.Release()
123 }
124 d.buffers, d.childData = nil, nil
125 }
126 }
127
128 // DataType returns the DataType of the data.
129 func (d *Data) DataType() arrow.DataType { return d.dtype }
130
131 // NullN returns the number of nulls.
132 func (d *Data) NullN() int { return d.nulls }
133
134 // Len returns the length.
135 func (d *Data) Len() int { return d.length }
136
137 // Offset returns the offset.
138 func (d *Data) Offset() int { return d.offset }
139
140 // Buffers returns the buffers.
141 func (d *Data) Buffers() []*memory.Buffer { return d.buffers }
142
143 // NewSliceData returns a new slice that shares backing data with the input.
144 // The returned Data slice starts at i and extends j-i elements, such as:
145 // slice := data[i:j]
146 // The returned value must be Release'd after use.
147 //
148 // NewSliceData panics if the slice is outside the valid range of the input Data.
149 // NewSliceData panics if j < i.
150 func NewSliceData(data *Data, i, j int64) *Data {
151 if j > int64(data.length) || i > j || data.offset+int(i) > data.offset+data.length {
152 panic("arrow/array: index out of range")
153 }
154
155 for _, b := range data.buffers {
156 if b != nil {
157 b.Retain()
158 }
159 }
160
161 for _, child := range data.childData {
162 if child != nil {
163 child.Retain()
164 }
165 }
166
167 o := &Data{
168 refCount: 1,
169 dtype: data.dtype,
170 nulls: UnknownNullCount,
171 length: int(j - i),
172 offset: data.offset + int(i),
173 buffers: data.buffers,
174 childData: data.childData,
175 }
176
177 if data.nulls == 0 {
178 o.nulls = 0
179 }
180
181 return o
182 }
183
184 func Hash(h *maphash.Hash, a *Data) {
185 h.Write((*[bits.UintSize / 8]byte)(unsafe.Pointer(&a.length))[:])
186 h.Write((*[bits.UintSize / 8]byte)(unsafe.Pointer(&a.length))[:])
187 if len(a.buffers) > 0 && a.buffers[0] != nil {
188 h.Write(a.buffers[0].Bytes())
189 }
190 for _, c := range a.childData {
191 Hash(h, c)
192 }
193 }