 
 import Foundation
 
-private struct TypeCapacity {
-    let type: Any.Type
-    let capacity: Int
+private class CapacitiesHolder {
+    private struct TypeCapacity {
+        let type: Any.Type
+        let capacity: Int
+    }
+
+    private var capacities = [TypeCapacity]()
+    private static let capacityReadQueue = dispatch_queue_create("Cereal Queue", DISPATCH_QUEUE_SERIAL)
+    private static let specificKey: UnsafePointer<Void> = CapacitiesHolder.assignSpesificKey(capacityReadQueue)
+
+    private static func assignSpesificKey(queue: dispatch_queue_t) -> UnsafePointer<Void> {
+        let opPtr = Unmanaged <dispatch_queue_t>.passUnretained(queue).toOpaque()
+        let result = UnsafeMutablePointer<Void>(opPtr)
+        dispatch_queue_set_specific(queue, result, result, nil)
+
+        return UnsafePointer<Void>(result)
+    }
+
+    private func sync(block: () -> ()) {
+        if dispatch_get_specific(CapacitiesHolder.specificKey) != nil {
+            block()
+        } else {
+            dispatch_sync(CapacitiesHolder.capacityReadQueue, block)
+        }
+    }
+
+    func capacity(forType type: Any.Type) -> Int? {
+        var result: Int? = nil
+        self.sync {
+            for item in self.capacities where item.type == type.dynamicType {
+                result = item.capacity
+                break
+            }
+        }
+
+        return result
+    }
+
+    func save(capacity capacity: Int, forType: Any.Type) {
+        self.sync {
+            self.capacities.append(TypeCapacity(type: forType.dynamicType, capacity: capacity))
+        }
+    }
 }
-private var capacities = [TypeCapacity]()
+
+private let capacitiesHolder = CapacitiesHolder()
 
 /**
     A CerealEncoder handles encoding items into a format that can be stored in a simple format, such as NSData or String.

            return try encodeItem(value)
            
        case let value as CerealType :
            var capacity: Int? = nil
            for item in capacities where item.type == value.dynamicType {
                capacity = item.capacity
                break;
            }
            var cereal = CerealEncoder(capacity: capacity ?? 20)
            try value.encodeWithCereal(&cereal)

            if capacity == nil {
                capacities.append(TypeCapacity(type: value.dynamicType, capacity: cereal.items.count))
            }
            return .SubTree(cereal.items)
            

    }

    private func encodeItem(item: IdentifyingCerealType) throws -> CoderTreeValue {
        let capacity = capacitiesHolder.capacity(forType: item.dynamicType)

        var cereal = CerealEncoder(capacity: capacity ?? 20)
        try item.encodeWithCereal(&cereal)
        let ident = item.dynamicType.initializationIdentifier

        if capacity == nil {
            capacitiesHolder.save(capacity: cereal.items.count, forType: item.dynamicType)
        }
        return .IdentifyingTree(ident, cereal.items)
    }
