1313//===----------------------------------------------------------------------===//
1414
1515import DistributedActors
16+ import DistributedActorsConcurrencyHelpers
1617
1718// ==== ----------------------------------------------------------------------------------------------------------------
1819// MARK: Actor singleton plugin
@@ -31,26 +32,29 @@ import DistributedActors
3132/// and <a href="https://doc.akka.io/docs/akka/current/cluster-singleton.html">`ClusterSingleton` in Akka</a>.
3233public final class ActorSingletonPlugin {
3334 private var singletons : [ String : BoxedActorSingleton ] = [ : ]
35+ private let singletonsLock = Lock ( )
3436
3537 public init ( ) { }
3638
3739 func ref< Message> ( of type: Message . Type , settings: ActorSingletonSettings , system: ActorSystem , props: Props ? = nil , _ behavior: Behavior < Message > ? = nil ) throws -> ActorRef < Message > {
38- if let existing = self . singletons [ settings. name] {
39- guard let proxy = existing. unsafeUnwrapAs ( Message . self) . proxy else {
40- fatalError ( " Singleton [ \( settings. name) ] not yet initialized " )
40+ try self . singletonsLock. withLock {
41+ if let existing = self . singletons [ settings. name] {
42+ guard let proxy = existing. unsafeUnwrapAs ( Message . self) . proxy else {
43+ fatalError ( " Singleton [ \( settings. name) ] not yet initialized " )
44+ }
45+ return proxy
4146 }
42- return proxy
43- }
4447
45- let singleton = ActorSingleton < Message > ( settings: settings, props: props, behavior)
46- try singleton. spawnAll ( system)
47- self . singletons [ settings. name] = BoxedActorSingleton ( singleton)
48+ let singleton = ActorSingleton < Message > ( settings: settings, props: props, behavior)
49+ try singleton. spawnAll ( system)
50+ self . singletons [ settings. name] = BoxedActorSingleton ( singleton)
4851
49- guard let proxy = singleton. proxy else {
50- fatalError ( " Singleton[ \( settings. name) ] not yet initialized " )
51- }
52+ guard let proxy = singleton. proxy else {
53+ fatalError ( " Singleton[ \( settings. name) ] not yet initialized " )
54+ }
5255
53- return proxy // FIXME: Worried that we never synchronize access to proxy...
56+ return proxy
57+ }
5458 }
5559
5660 func actor < Act: Actorable > ( of type: Act . Type , settings: ActorSingletonSettings , system: ActorSystem , props: Props ? = nil , _ makeInstance: ( ( Actor < Act > . Context ) -> Act ) ? = nil ) throws -> Actor < Act > {
@@ -92,8 +96,10 @@ extension ActorSingletonPlugin: Plugin {
9296
9397 // TODO: Future
9498 public func stop( _ system: ActorSystem ) -> Result < Void , Error > {
95- for (_, singleton) in self . singletons {
96- singleton. stop ( system)
99+ self . singletonsLock. withLock {
100+ for (_, singleton) in self . singletons {
101+ singleton. stop ( system)
102+ }
97103 }
98104 return . success( ( ) )
99105 }
0 commit comments