• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Are immutable singletons thread safe?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Are immutable singletons thread safe?


  • Subject: Re: Are immutable singletons thread safe?
  • From: Shawn Erickson <email@hidden>
  • Date: Sun, 9 May 2004 09:22:33 -0700

On May 8, 2004, at 10:22 PM, Ken Tozier wrote:

Several of my classes and categories use immutable singletons to store stuff and I'm wondering, if these classes are used in a thread, if I would run into problems.

It depends on what you mean by "use". The singleton creation/fetching aspects or concurrent method calls on the singleton, etc.. If the former you likely can avoid locking by insuring your singletons are allocated and initialized early on before secondary thread get going. For the later you will need to use mutexes/locks in concurrence issues exist (shared access to data structures, etc.).

The following is an example of abstract singleton class that can be sub-classed to make concrete singleton instances... it is something that I am using in a project (but it hasn't been fully tested yet....). It provides thread safe lazy initialization of singletons. Feel free to copy, hack, improve, or ignore.

#import "FTSWAbstractSingleton.h"

#import <objc/objc-runtime.h>

@implementation FTSWAbstractSingleton

static NSMutableDictionary *s_FTSWAbstractSingleton_singletons = nil;

+ (void)initialize
{
@synchronized(self) {
if (s_FTSWAbstractSingleton_singletons == nil) {
s_FTSWAbstractSingleton_singletons = [[NSMutableDictionary alloc] init];
}
}
}

// Should be considered private to the abstract singleton class, wrap with a "sharedXxx" class method
+ (id)singleton
{
return [self singletonWithZone:[self zone]];
}

// Should be considered private to the abstract singleton class
+ (id)singletonWithZone:(NSZone*)zone
{
id singleton = nil;
Class class = [self class];

if (class == [FTSWAbstractSingleton class]) {
[NSException raise:NSInternalInconsistencyException
format:@"Not valid to request the abstract singleton."];
}

@synchronized(self) {
singleton = [s_FTSWAbstractSingleton_singletons objectForKey:class];
if (singleton == nil) {
singleton = class_createInstanceFromZone(class, 0U, zone);
if ((singleton = [singleton initSingleton]) != nil) {
[s_FTSWAbstractSingleton_singletons setObject:singleton forKey:class];
}
}
}

return singleton;
}

// Designated initializer for instances. If subclasses override they must call this implementation.
- (id)initSingleton
{
return [super init];
}

// Disallow the normal default initializer for instances.
- (id)init
{
[self doesNotRecognizeSelector:_cmd];
return nil;
}

// ------------------------------------------------------------------------ ---------------------------------------------
// The following overrides attempt to enforce singleton behavior.

+ (id)new
{
return [self singleton];
}

+ (id)allocWithZone:(NSZone *)zone
{
return [self singletonWithZone:zone];
}

+ (id)alloc
{
return [self singleton];
}

- (id)copy
{
[self doesNotRecognizeSelector:_cmd];
return self;
}

- (id)copyWithZone:(NSZone *)zone
{
[self doesNotRecognizeSelector:_cmd];
return self;
}

- (id)mutableCopy
{
[self doesNotRecognizeSelector:_cmd];
return self;
}

- (id)mutableCopyWithZone:(NSZone *)zone
{
[self doesNotRecognizeSelector:_cmd];
return self;
}

- (unsigned)retainCount
{
return UINT_MAX;
}

- (oneway void)release
{
}

- (id)retain
{
return self;
}

- (id)autorelease
{
return self;
}

- (void)dealloc
{
[self doesNotRecognizeSelector:_cmd];
}
// ------------------------------------------------------------------------ ---------------------------------------------

@end


Example of a sub-class....

@interface FTSWSerialPortRegistry : FTSWAbstractSingleton
...

@implementation FTSWSerialPortRegistry

+ (FTSWSerialPortRegistry*)sharedRegistry
{
static FTSWSerialPortRegistry *s_FTSW_sharedSerialPortRegistry = nil;

@synchronized(self) {
if (s_FTSW_sharedSerialPortRegistry == nil) {
s_FTSW_sharedSerialPortRegistry = [self singleton];
}
}

return s_FTSW_sharedSerialPortRegistry;
}

- (id)initSingleton
{
if (self = [super initSingleton]) {
knownPorts = [[NSMutableDictionary alloc] initWithCapacity:2];
currentPorts = [[NSMutableDictionary alloc] initWithCapacity:2];
[self setDynamicDiscovery:YES];
}

return self;
}


-Shawn
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.


References: 
 >Are immutable singletons thread safe? (From: Ken Tozier <email@hidden>)

  • Prev by Date: Distinguishing between table row/column double click?
  • Next by Date: Can NSImage use image masks?
  • Previous by thread: Re: Are immutable singletons thread safe?
  • Next by thread: Re: Are immutable singletons thread safe?
  • Index(es):
    • Date
    • Thread