## Side Tables (боковая таблица)

1. [Side Tables](https://itnan.ru/post.php?c=1&p=592385)
2. [Apple Opensource Code](https://github.com/apple/swift/blob/main/stdlib/public/SwiftShims/swift/shims/RefCount.h)

Side tables — это механизм для реализации [слабых ссылок](./3.1.3.1.4.4%20Weak.md) Swift.

> Слабые ссылки указывают на  side table. [Unowned](./3.1.3.1.4.3%20Unowned.md) и [Strong](./3.1.3.1.4.2%20Strong.md) ссылки указывают на объект.

Объекты изначально начинаются без боковой таблицы. Объекты могут получить боковую таблицу когда: 
1) формируется [слабая ссылка](./3.1.3.1.4.4%20Weak.md);
2) также может создаваться, когда происходит переполнение [сильных](./3.1.3.1.4.2%20Strong.md) или [бесхозных](./3.1.3.1.4.3%20Unowned.md) счетчиков, и он уже не помещается в поле (счетчики ссылок будут маленькими на 32-битных машинах);

Получение записи в боковой таблице - это односторонняя операция; Объект получив однажды запись в боковой таблице никогда ее не теряет - [ссылка](https://alexdremov.me/dive-into-swifts-memory-management/). Это предотвращает некоторые [гонки потоков](/3%20Memory%20and%20Concurrency/3.2%20Multithreading/3.2.2%20ProblemsOfMultithreading.md).

![side table](https://alexdremov.me/content/images/2023/01/Screenshot-2023-01-08-at-15.20.34.png)

Как только мы начинаем ссылаться на объект слабо ([weak reference](./3.1.3.1.4.4%20Weak.md)), то создается боковая таблица, и теперь объект вместо сильного счетчика ссылок хранит ссылку на боковую таблицу. Сама боковая таблица также имеет ссылку на объект.

> Слабые переменные указывают на боковую таблицу объекта. Указывая не на объект, а на боковую таблицу, сам объект может быть деинициализирован и полностью деаллоцирован. Эта идея является основополагающей для понимания того, как работают слабые ссылки. 

Таким образом, Side Table — это просто счетчик ссылок + указатель на объект. Они объявлены в Swift Runtime следующим образом (код C ++):

```swift
class HeapObjectSideTableEntry {
  std::atomic<HeapObject*> object;
  SideTableRefCounts refCounts;
  // Operations to increment and decrement reference counts
}
```

## Старая реализация

1. [Слабые ссылки до Swift 4](https://mikeash.com/pyblog/friday-qa-2017-09-22-swift-4-weak-references.html)

До Swift 4, счетчики ссылок располагались до свойств класса прямо в объекте. Класс имел только два счетчика  —  [weak](./3.1.3.1.4.4%20Weak.md) и [strong](./3.1.3.1.4.2%20Strong.md). 

### Проблемы

1) В один момент времени объект с сильной ссылкой удаляется из памяти, и теперь у нас осталась только одна слабая ссылка. Что происходит в этот момент? 

Данные объекта уничтожаются (деинициализируются), но память не освобождается (free), так как счетчик еще требуется хранить. В памяти остается так называемый «зомби объект», на который ссылается слабая ссылка. Только при обращении по слабой ссылке в runtime будет выполнена проверка: «зомби» (NSZombie) этот объект или нет. Если да, счетчик ссылок уменьшается.

Данный подход достаточно прозрачный, но главный минус в том, что так объекты могут долго оставаться в памяти, занимая лишнее место, хотя не несут никакой пользы.

2) Встречался еще один достаточно [критичный баг](https://github.com/apple/swift/issues/42814): получение (загрузка) объекта по слабой ссылке было не потокобезопасным!

```swift
class Target {}

class WeakHolder {
   weak var: Target?
}

for i in 0..<1000000 {
   print(i)
   let holder = WeakHolder()
   holder.weak = Target()
   dispatch_async(dispatch_get_global_queue(0, 0), {
       let _ = holder.weak
   })
   dispatch_async(dispatch_get_global_queue(0, 0), {
       let _ = holder.weak
   })
}
```

Данный кусок кода может получить ошибку в Runtime. Суть именно в том механизме, который был рассмотрен ранее. Два потока могут одновременно обратиться к объекту по слабой ссылке. Перед тем, как получить объект, они проверяют, является ли проверяемый объект «зомби». И если оба потока получат ответ true, они отнимут счётчик и постараются освободить память. Один из них сделает это, а второй просто вызовет краш, так как попытается освободить уже освобожденный участок памяти.

---

Также стоит ознакомиться: [Жизненный цикл объекта Swift](/5%20Swift/5.3%20DataRepresentations/5.3.1%20DataTypes/5.3.1.3%20ReferenceTypes/Class/ObjectLifeCycle.md)

---

[3.1.3.1.4.4 Weak Reference Theme](./3.1.3.1.4.3%20Unowned.md) | [Back To iTWiki Contents](https://github.com/eldaroid/iTWiki) | [3.1.3.2 Garbage Collector Theme](../../3.1.3.2%20GarbageCollector.md)
