2017-05-17 3 views
0

Comment synchroniser l'accès d'une propriété utilisant didSet (en utilisant GCD ou objc_sync_enter)?Comment synchroniser l'accès à une propriété avec didSet?

J'ai une propriété qui a un observateur de propriété. Comment puis-je utiliser une file d'attente privée pour synchroniser get/ensemble de la propriété

var state: State = .disconnected { 
    // Q: How to sync get/set access here? 
    didSet { 
    // do something 
    } 
} 

Répondre

0

façon la plus simple utilise une file d'attente série

import Dispatch 

struct S { 
    private var i: Int = 0 { 
     didSet { 
      print("someone did set new value:", i) 
     } 
    } 
    private let queue = DispatchQueue(label: "private", qos: .userInteractive) // high priority 
    var value: Int { 
     get { 
      return queue.sync { 
       return i 
      } 
     } 
     set { 
      if newValue == value { 
       return 
      } 
      queue.sync { 
       i = newValue 
      } 
     } 
    } 
} 

exemple plus utiliser la lecture simultanée et la barrière de synchronisation pour l'écriture

Dans le cas d'une propriété de classe, vous pouvez utiliser une file d'attente privée simultanée et lire des threads différents simultanément et répartir l'écriture de manière asynchrone avec une barrière
import Dispatch 

class S { 
    private var i: Int = 0 { 
     didSet { 
      print("someone did set new value:", i) 
     } 
    } 
    private let queue = DispatchQueue(label: "private", qos: .userInteractive, attributes: .concurrent) // high priority 
    var value: Int { 
     get { 
      return queue.sync { 
       return i 
      } 
     } 
     set { 
      if newValue == value { 
       return 
      } 
      queue.async(flags: .barrier) { [unowned self] in 
       self.i = newValue 
      } 
     } 
    } 
} 
+0

Donc, pour appliquer la synchronisation Je dois créer une autre propriété calculée? – Boon

+0

@Boon vous devez "isoler" votre stockage "privé", donc l'utilisation de la propriété calculée semble être une étape logique, n'est-ce pas? – user3441734

+0

@Boon Je ne sais pas, quel est exactement votre scénario d'utilisation, mais je recommande fortement de vérifier cette bonne lecture https://www.mikeash.com/pyblog/friday-qa-2015-02-06-locks-thread -safety-and-swift.html – user3441734

0

Autre (en utilisant objc_sync_enter):

class MyUtil { 

    class func synchronize(_ blockObj: AnyObject!, closure:() -> Void) { 
    objc_sync_enter(blockObj) 
    closure() 
    objc_sync_exit(blockObj) 
    } 
    class func synchronize<T>(_ blockObj: AnyObject!, closure:() -> T) -> T { 
    objc_sync_enter(blockObj) 
    let retVal:T = closure() 
    objc_sync_exit(blockObj) 
    return retVal 
    } 
} 

struct S { 
    private var i: Int = 0 { 
    didSet { 
     print("someone did set new value:", i) 
    } 
    } 
    var value: Int { 
    get { 
     return MyUtil.synchronize(i as AnyObject) { 
      return i 
     } 
    } 
    set { 
     MyUtil.synchronize(i as AnyObject) { 
      if newValue == value { 
       return 
      } 
      i = newValue 
     } 
    } 
}