diff options
author | alien <the-alien@live.ru> | 2016-03-29 20:58:23 +0300 |
---|---|---|
committer | alien <the-alien@live.ru> | 2016-03-29 20:58:23 +0300 |
commit | af34538aca9d91b86826223624018a69370caa1d (patch) | |
tree | e946d75326662d0e2f72a4379de098fa61c25705 /objectivec | |
parent | 6f8dd2115b3ed07819a48dfa78b15770dfa2c450 (diff) | |
parent | 261ee021f640ea6fe67aaf1f53e1518ed154cad0 (diff) | |
download | protobuf-af34538aca9d91b86826223624018a69370caa1d.tar.gz protobuf-af34538aca9d91b86826223624018a69370caa1d.tar.bz2 protobuf-af34538aca9d91b86826223624018a69370caa1d.zip |
Merge branch 'master' of https://github.com/google/protobuf into csharp_json_name
Diffstat (limited to 'objectivec')
-rw-r--r-- | objectivec/GPBMessage.m | 11 | ||||
-rw-r--r-- | objectivec/GPBMessage_PackagePrivate.h | 12 | ||||
-rw-r--r-- | objectivec/GPBUtilities.m | 1 |
3 files changed, 19 insertions, 5 deletions
diff --git a/objectivec/GPBMessage.m b/objectivec/GPBMessage.m index 94d179be..0e1599dc 100644 --- a/objectivec/GPBMessage.m +++ b/objectivec/GPBMessage.m @@ -556,6 +556,7 @@ static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); if (!array) { // Check again after getting the lock. + GPBPrepareReadOnlySemaphore(self); dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER); array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); if (!array) { @@ -586,6 +587,7 @@ static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); if (!dict) { // Check again after getting the lock. + GPBPrepareReadOnlySemaphore(self); dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER); dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); if (!dict) { @@ -791,8 +793,6 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { if ((self = [super init])) { messageStorage_ = (GPBMessage_StoragePtr)( ((uint8_t *)self) + class_getInstanceSize([self class])); - - readOnlySemaphore_ = dispatch_semaphore_create(1); } return self; @@ -868,7 +868,9 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { - (void)dealloc { [self internalClear:NO]; NSCAssert(!autocreator_, @"Autocreator was not cleared before dealloc."); - dispatch_release(readOnlySemaphore_); + if (readOnlySemaphore_) { + dispatch_release(readOnlySemaphore_); + } [super dealloc]; } @@ -1706,6 +1708,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { } // Check for an autocreated value. + GPBPrepareReadOnlySemaphore(self); dispatch_semaphore_wait(readOnlySemaphore_, DISPATCH_TIME_FOREVER); value = [autocreatedExtensionMap_ objectForKey:extension]; if (!value) { @@ -1917,7 +1920,6 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { } } @catch (NSException *exception) { - [message release]; message = nil; if (errorPtr) { *errorPtr = MessageErrorWithReason(GPBMessageErrorCodeMalformedData, @@ -1926,7 +1928,6 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { } #ifdef DEBUG if (message && !message.initialized) { - [message release]; message = nil; if (errorPtr) { *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil); diff --git a/objectivec/GPBMessage_PackagePrivate.h b/objectivec/GPBMessage_PackagePrivate.h index b7e24fc9..478db2cf 100644 --- a/objectivec/GPBMessage_PackagePrivate.h +++ b/objectivec/GPBMessage_PackagePrivate.h @@ -67,6 +67,10 @@ typedef struct GPBMessage_Storage *GPBMessage_StoragePtr; // priority inversion: // http://mjtsai.com/blog/2015/12/16/osspinlock-is-unsafe/ // https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20151214/000372.html + // Use of readOnlySemaphore_ must be prefaced by a call to + // GPBPrepareReadOnlySemaphore to ensure it has been created. This allows + // readOnlySemaphore_ to be only created when actually needed. + dispatch_once_t readOnlySemaphoreCreationOnce_; dispatch_semaphore_t readOnlySemaphore_; } @@ -103,6 +107,14 @@ typedef struct GPBMessage_Storage *GPBMessage_StoragePtr; CF_EXTERN_C_BEGIN + +// Call this before using the readOnlySemaphore_. This ensures it is created only once. +NS_INLINE void GPBPrepareReadOnlySemaphore(GPBMessage *self) { + dispatch_once(&self->readOnlySemaphoreCreationOnce_, ^{ + self->readOnlySemaphore_ = dispatch_semaphore_create(1); + }); +} + // Returns a new instance that was automatically created by |autocreator| for // its field |field|. GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass, diff --git a/objectivec/GPBUtilities.m b/objectivec/GPBUtilities.m index 3e9d11c0..447c749a 100644 --- a/objectivec/GPBUtilities.m +++ b/objectivec/GPBUtilities.m @@ -412,6 +412,7 @@ id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { return field.defaultValue.valueMessage; } + GPBPrepareReadOnlySemaphore(self); dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER); GPBMessage *result = GPBGetObjectIvarWithFieldNoAutocreate(self, field); if (!result) { |