| 207 | } |
| 208 | |
| 209 | array::~array() { |
| 210 | if (array_desc_ == nullptr) { |
| 211 | return; |
| 212 | } |
| 213 | |
| 214 | // Detached/detaching |
| 215 | if (array_desc_->primitive == nullptr) { |
| 216 | return; |
| 217 | } |
| 218 | |
| 219 | // Break circular reference for non-detached arrays with siblings |
| 220 | if (auto n = siblings().size(); n > 0) { |
| 221 | bool do_detach = true; |
| 222 | // If all siblings have siblings.size() references except |
| 223 | // the one we are currently destroying (which has siblings.size() + 1) |
| 224 | // then there are no more external references |
| 225 | do_detach &= (array_desc_.use_count() == (n + 1)); |
| 226 | for (auto& s : siblings()) { |
| 227 | do_detach &= (s.array_desc_.use_count() == n); |
| 228 | if (!do_detach) { |
| 229 | break; |
| 230 | } |
| 231 | } |
| 232 | if (do_detach) { |
| 233 | for (auto& s : siblings()) { |
| 234 | for (auto& ss : s.siblings()) { |
| 235 | // Set to null here to avoid descending into array destructor |
| 236 | // for siblings |
| 237 | ss.array_desc_ = nullptr; |
| 238 | } |
| 239 | s.array_desc_->siblings.clear(); |
| 240 | } |
| 241 | } |
| 242 | } |
| 243 | } |
| 244 | |
| 245 | void array::ArrayDesc::init() { |
| 246 | strides.resize(shape.size()); |