GCD со статическими функциями структуры

Как бы вы применили поточно-ориентированную функциональность к статическим функциям структуры

class SingleSome {

    struct Static {
        private static var instance: SingleSome?

        //need barrier sync
        static func getInstance(block: () -> SingleSome) -> SingleSome {
            if instance == nil {
                instance = block()
            }
            return instance!
        }

        static func remove() { //need barrier sync
            instance = nil
        }
    }

}

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

2 ответа

Решение

Вы можете использовать частную последовательную очередь, чтобы гарантировать, что только один поток может быть в любой из критических секций в любой момент.

class SingleSome {

    struct Static {
        private static let queue = dispatch_queue_create("SingleSome.Static.queue", nil)
        private static var instance: SingleSome?

        static func getInstance(block: () -> SingleSome) -> SingleSome {
            var myInstance: SingleSome?
            dispatch_sync(queue) {
                if self.instance == nil {
                    self.instance = block()
                }
                myInstance = self.instance
            }
            // This return has to be outside the dispatch_sync block,
            // so there's a race condition if I return instance directly.
            return myInstance!
        }

        static func remove() {
            dispatch_sync(queue) {
                self.instance = nil
            }
        }
    }

}

Используйте семафор, dispatch_sync не подходит, потому что вам нужно синхронное возвращаемое значение из getInstance:

class SingleSome {

    struct Static {
        private static var instance: SingleSome?
        private static let lock = dispatch_semaphore_create(1)

        //need barrier sync
        static func getInstance(block: () -> SingleSome) -> SingleSome {
            dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER)
            var value = instance
            if value == nil {
                instance = block()
                value = instance
            }
            dispatch_semaphore_signal(lock)
            return value!
        }

        static func remove() { //need barrier sync
            dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER)
            instance = nil
            dispatch_semaphore_signal(lock)
        }
    }

}

Также обратите внимание, что как написано, это может привести к взаимоблокировкам, если блок приводит к удалению или вызову getInstance как dispatch_semaphore_t не является рекурсивным потоком

Другие вопросы по тегам