diff options
Diffstat (limited to 'objectivec/GPBMessage_PackagePrivate.h')
-rw-r--r-- | objectivec/GPBMessage_PackagePrivate.h | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/objectivec/GPBMessage_PackagePrivate.h b/objectivec/GPBMessage_PackagePrivate.h index d4c3501a..478db2cf 100644 --- a/objectivec/GPBMessage_PackagePrivate.h +++ b/objectivec/GPBMessage_PackagePrivate.h @@ -62,7 +62,16 @@ typedef struct GPBMessage_Storage *GPBMessage_StoragePtr; // by *read* operations such as getters (autocreation of message fields and // message extensions, not setting of values). Used to guarantee thread safety // for concurrent reads on the message. - OSSpinLock readOnlyMutex_; + // NOTE: OSSpinLock may seem like a good fit here but Apple engineers have + // pointed out that they are vulnerable to live locking on iOS in cases of + // 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_; } // Gets an extension value without autocreating the result if not found. (i.e. @@ -98,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, |