Re: How to implement readonly property

2013-05-01 Thread Andreas Grosam
This is a somewhat older but quite interesting thread - nonetheless I felt the 
final conclusion was still too vague.


So, I did my best to put up a simple worst case sample and tried to trick 
dispatch_once into a race. But I failed. That is, dispatch_once was doing what 
one would like to expect. While this is eventually no proof, it at least 
increases the probability that certain use cases are quite safe, for a given 
environment.

Maybe someone else will detect a race? Or perhaps, somebody is able to find an 
even worser worst case? ;)


Note: if a race has been occurred, it would print x to stdout.


#include iostream
#include new
#include type_traits
#include dispatch/dispatch.h
struct Bar {

void setResult(long value) {
dispatch_once(_once, ^{
_result = value;
});
}

long getResult() const {
return _result;
}

dispatch_once_t _once;
long _result;
};


int main(int argc, const char * argv[])
{
dispatch_semaphore_t finished_sem = dispatch_semaphore_create(0);

const int N = 100;
int n = N;
typedef std::aligned_storagesizeof(Bar), 
std::alignment_ofBar::value::type storage_t;
storage_t storage;

while (n) {
//memset(storage, -1, sizeof(storage));
Bar* bar = new (storage) Bar();
dispatch_async(dispatch_get_global_queue(0, 0), ^{
bar-setResult(n);
dispatch_semaphore_signal(finished_sem);
});
dispatch_semaphore_wait(finished_sem, DISPATCH_TIME_FOREVER);
if (bar-getResult() != n) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
printf(x);
});
}
--n;
}

printf(finished);

return 0;
}



Andreas





On 09.12.2012, at 17:52, Ken Thomases wrote:

 On Dec 9, 2012, at 10:37 AM, Kyle Sluder wrote:
 
 On Dec 9, 2012, at 6:53 AM, Ken Thomases k...@codeweavers.com wrote:
 
 On Dec 9, 2012, at 1:27 AM, Kyle Sluder wrote:
 
 If dispatch_once() really is unsuitable for use with a dispatch_once_t
 stored in Objective-C instance storage, then the correct example in the
 paper I've cited might be a sufficient workaround.
 
 I thought we had established that, in all sane use cases, an instance 
 variable once predicate is fine.
 
 Hence the hedge. ;-)
 
 The cases where an instance variable once predicate would be unsafe are 
 exactly the cases where it would be unsafe to access any instance variable, 
 including the isa pointer.  So, if you're using the instance in any way, 
 you've already assumed conditions that make the once predicate fine. (And, 
 hopefully, you've more than assumed it, you've ensured it by proper 
 inter-thread communication of the object pointer.)
 
 Yes, but as Greg pointed out the real danger comes from not understanding 
 all the nuances of this, and assuming that dispatch_once is a more powerful 
 synchronization primitive than it really is.
 
 I'm still not understanding the circumspection.  The use of dispatch_once() 
 never _contributes_ to unsafe access.  It is unsafe if the situation is 
 already unsafe.  If you try to avoid using dispatch_once() using other 
 techniques like @synchronized(self), etc., that doesn't help anything.
 
 Intellectually, I understand the concern that people will assume that 
 dispatch_once() introduces safety where it doesn't, but as a practical matter 
 I'm finding it hard to imagine a scenario where a) that comes up or b) 
 avoiding dispatch_once() for some vague (to the naive developer) notion that 
 it's unsafe would lead to better safety.  Can you or Greg illustrate with an 
 example?
 
 I feel that dispatch_once() with an instance variable once predicate _is_ the 
 right answer for the class of problems where people would be tempted to use 
 it and that we should be encouraging developers to rely on it rather than 
 invariably worse alternatives.
 
 Regards,
 Ken
 
 
 ___
 
 Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
 
 Please do not post admin requests or moderator comments to the list.
 Contact the moderators at cocoa-dev-admins(at)lists.apple.com
 
 Help/Unsubscribe/Update your Subscription:
 https://lists.apple.com/mailman/options/cocoa-dev/agrosam%40onlinehome.de
 
 This email sent to agro...@onlinehome.de


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-12-10 Thread Matt Neuburg
On Sat, 08 Dec 2012 16:45:37 -0800, Greg Parker gpar...@apple.com said:
Source: me, the author of the current @synchronized implementation. 
@synchronized performs the same synchronization as a pthread mutex.

Wow, this is just like that scene in the Woody Allen movie where Marshall 
McLuhan shows up!!! :) m.

--
matt neuburg, phd = m...@tidbits.com, http://www.apeth.net/matt/
A fool + a tool + an autorelease pool = cool!
Programming iOS 5! http://shop.oreilly.com/product/0636920023562.do
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-12-09 Thread Jean-Daniel Dupas

Le 9 déc. 2012 à 02:27, Richard Heard heard...@gmail.com a écrit :

 Greg, 
 
 So, from what you are saying, either of these snippets should be valid, right?
 
 +(id)sharedInstance{
static id _sharedInstance = nil;
 
   …

OSMemoryBarrier();
return _sharedInstance;
 }

OSMemoryBarrier are not cheap. If dispatch_once uses it only on the write side, 
then it should be faster than forcing a full barrier at each access.

By the way, as nobody mention it until then, all this discussion look like to 
me as pointless premature optimization. If accessing your singleton is a 
bottleneck (and nothing tell us it is), there is probably simpler way to avoid 
this cost.

 vs
 
 +(id)sharedInstance{
static id _sharedInstance = nil;
 
static dispatch_once_t onceToken;
dispatch_once(onceToken, ^{
_sharedInstance = [[super allocWithZone:NULL] init];
});
 
return _sharedInstance;
 }
 
 
 Any massive advantages / disadvantages with either approach?
 
 -Richard
 
 On 08/12/2012, at 4:45:37 PM, Greg Parker gpar...@apple.com wrote:
 
 On Dec 8, 2012, at 11:17 AM, Steve Sisak sgs-li...@codewell.com wrote:
 At 10:24 AM -0800 12/8/12, Kyle Sluder wrote:
 On Dec 8, 2012, at 10:06 AM, Steve Sisak sgs-li...@codewell.com wrote:
 
 Further, if writes were not complete at the end of the block, the 
 construct would besentially useless for its intended purpose.
 
 By the way, you're wrong about this too. All @synchronized does is act as 
 a mutex around a code block. It does not cause the compiler to reorder 
 instructions and issue memory barriers in such a way that initialization 
 is guaranteed to precede assignment from the perspective of all threads.
 
 Please cite a source for this assertion.
 
 Source: me, the author of the current @synchronized implementation. 
 @synchronized performs the same synchronization as a pthread mutex.
 
 
 From:
 
 https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html
 
 If you are already using a mutex to protect a section of code, do not 
 automatically assume you need to use the volatile keyword to protect 
 important variables inside that section. A mutex includes a memory barrier 
 to ensure the proper ordering of load and store operations.
 
 To a close approximation, you should pretend that `volatile` does not exist 
 in C-based languages.
 
 The above says that if you already have mutexes then you do not need 
 `volatile`. The mutex alone does all of the work. 
 
 Conversely, `volatile` with no mutex is also not a safe multithreading 
 pattern.
 
 
 I acknowledge that, without proper memory barriers, double-checked locking 
 is problematic, but am providing an example using a construct which I'm 
 fairly sure uses proper memory barriers.
 
 - (NSDictionary *)someDictionary;
 {
 if (!_someDictionary)
 {
 @synchronized (self)
 {
   if (!_someDictionary)
   {
 // create a temp dictionary (might take some time)
  _someDictionary = temp;
   }
 }
 }
 
 return _someDictionary;
 }
 
 
 The example provided does not use proper memory barriers. 
 
 In general, memory barriers need to occur in pairs, one on each thread. The 
 coordination of the two memory barriers achieves the desired 
 synchronization, so that both sides observe events occurring in the same 
 order.
 
 Mutexes and similar constructs achieve this. The mutex lock() and unlock() 
 procedures form a barrier pair. Code running with the mutex held is 
 therefore correctly synchronized with respect to other code that runs with 
 the mutex held. But code running outside the mutex is not protected, because 
 it didn't call the barrier inside the lock() procedure.
 
 In faulty double-checked locking code, the problem is that the writer has a 
 memory barrier but the reader does not. Because it has no barriers, the 
 reader may observe events occur out of the desired order. That's why it 
 fails. (Here the writer is the thread actually calling the initializer and 
 the reader is a second thread simultaneously performing the double-check 
 sequence.)
 
 (Faulty double-checked locking code has a second problem because the 
 writer-side barrier inside the mutex unlock is the wrong barrier to use with 
 a reader that is not locking the mutex.)
 
 You need to do one of two things to fix the reader side of a double-checked 
 lock:
 * add appropriate barriers to the reader side, or 
 * cheat in a way that is guaranteed to work on all architectures you care 
 about.
 
 dispatch_once() actually cheats. It performs a very expensive barrier on the 
 writer side (much more expensive than the barriers used in ordinary mutexes 
 and @synchronized), which guarantees that no barrier is needed on the reader 
 side on the CPUs that run OS X and iOS. The expensive barrier on the reader 
 side is an acceptable trade-off because the writer path runs only once.
 
 
 -- 
 Greg Parker gpar...@apple.com Runtime Wrangler
 
 
 
 

Re: How to implement readonly property

2012-12-09 Thread Ken Thomases
On Dec 9, 2012, at 1:27 AM, Kyle Sluder wrote:

 If dispatch_once() really is unsuitable for use with a dispatch_once_t
 stored in Objective-C instance storage, then the correct example in the
 paper I've cited might be a sufficient workaround.

I thought we had established that, in all sane use cases, an instance variable 
once predicate is fine.  The cases where an instance variable once predicate 
would be unsafe are exactly the cases where it would be unsafe to access any 
instance variable, including the isa pointer.  So, if you're using the instance 
in any way, you've already assumed conditions that make the once predicate 
fine. (And, hopefully, you've more than assumed it, you've ensured it by proper 
inter-thread communication of the object pointer.)

Regards,
Ken


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-12-09 Thread Kyle Sluder
On Dec 9, 2012, at 6:53 AM, Ken Thomases k...@codeweavers.com wrote:

 On Dec 9, 2012, at 1:27 AM, Kyle Sluder wrote:
 
 If dispatch_once() really is unsuitable for use with a dispatch_once_t
 stored in Objective-C instance storage, then the correct example in the
 paper I've cited might be a sufficient workaround.
 
 I thought we had established that, in all sane use cases, an instance 
 variable once predicate is fine.

Hence the hedge. ;-)

 The cases where an instance variable once predicate would be unsafe are 
 exactly the cases where it would be unsafe to access any instance variable, 
 including the isa pointer.  So, if you're using the instance in any way, 
 you've already assumed conditions that make the once predicate fine. (And, 
 hopefully, you've more than assumed it, you've ensured it by proper 
 inter-thread communication of the object pointer.)

Yes, but as Greg pointed out the real danger comes from not understanding all 
the nuances of this, and assuming that dispatch_once is a more powerful 
synchronization primitive than it really is.

--Kyle Sluder

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-12-09 Thread Ken Thomases
On Dec 9, 2012, at 10:37 AM, Kyle Sluder wrote:

 On Dec 9, 2012, at 6:53 AM, Ken Thomases k...@codeweavers.com wrote:
 
 On Dec 9, 2012, at 1:27 AM, Kyle Sluder wrote:
 
 If dispatch_once() really is unsuitable for use with a dispatch_once_t
 stored in Objective-C instance storage, then the correct example in the
 paper I've cited might be a sufficient workaround.
 
 I thought we had established that, in all sane use cases, an instance 
 variable once predicate is fine.
 
 Hence the hedge. ;-)
 
 The cases where an instance variable once predicate would be unsafe are 
 exactly the cases where it would be unsafe to access any instance variable, 
 including the isa pointer.  So, if you're using the instance in any way, 
 you've already assumed conditions that make the once predicate fine. (And, 
 hopefully, you've more than assumed it, you've ensured it by proper 
 inter-thread communication of the object pointer.)
 
 Yes, but as Greg pointed out the real danger comes from not understanding all 
 the nuances of this, and assuming that dispatch_once is a more powerful 
 synchronization primitive than it really is.

I'm still not understanding the circumspection.  The use of dispatch_once() 
never _contributes_ to unsafe access.  It is unsafe if the situation is already 
unsafe.  If you try to avoid using dispatch_once() using other techniques like 
@synchronized(self), etc., that doesn't help anything.

Intellectually, I understand the concern that people will assume that 
dispatch_once() introduces safety where it doesn't, but as a practical matter 
I'm finding it hard to imagine a scenario where a) that comes up or b) avoiding 
dispatch_once() for some vague (to the naive developer) notion that it's unsafe 
would lead to better safety.  Can you or Greg illustrate with an example?

I feel that dispatch_once() with an instance variable once predicate _is_ the 
right answer for the class of problems where people would be tempted to use it 
and that we should be encouraging developers to rely on it rather than 
invariably worse alternatives.

Regards,
Ken


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-12-08 Thread Kyle Sluder
On Dec 7, 2012, at 8:38 PM, Marco S Hyman m...@snafu.org wrote:

 On Dec 7, 2012, at 8:18 PM, Steve Sisak sgs-li...@codewell.com wrote:
 
 I'm interested if there are an any issued I'm missing in the Obj-C, 
 @synchronized(self), instance variable case.
 
 
 Your pattern can fail if this line
_someDictionary = temp;
 isn't atomic.

The real issue with double-checked locking is whether the compiler promises to 
generate the proper memory barriers such that other threads are guaranteed to 
see the assignment to _someDictionary *after* the object has been constructed. 
C makes no such guarantee; other threads might see a non-nil value for 
_someDictionary before the first thread is done constructing the object.

--Kyle Sluder
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-12-08 Thread Steve Sisak

At 8:35 AM -0800 12/8/12, Kyle Sluder wrote:

On Dec 7, 2012, at 8:38 PM, Marco S Hyman m...@snafu.org wrote:


 On Dec 7, 2012, at 8:18 PM, Steve Sisak sgs-li...@codewell.com wrote:

 I'm interested if there are an any issued I'm missing in the 
Obj-C, @synchronized(self), instance variable case.



 Your pattern can fail if this line
_someDictionary = temp;
 isn't atomic.


The real issue with double-checked locking is whether the compiler 
promises to generate the proper memory barriers such that other 
threads are guaranteed to see the assignment to _someDictionary 
*after* the object has been constructed. C makes no such guarantee; 
other threads might see a non-nil value for _someDictionary before 
the first thread is done constructing the object.


I'm fairly sure that @synchronized, being a compiler built-in, rather 
than a function, makes that guarantee -- specifically the the values 
of instance variables can change across entry and exit of an 
@synchronized block.


Further, if writes were not complete at the end of the block, the 
construct would be essentially useless for its intended purpose.


In any case, removing the outer check makes the code correct 
regardless of compiler guarantees.

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-12-08 Thread Kyle Sluder
On Dec 8, 2012, at 10:06 AM, Steve Sisak sgs-li...@codewell.com wrote:

 At 8:35 AM -0800 12/8/12, Kyle Sluder wrote:
 On Dec 7, 2012, at 8:38 PM, Marco S Hyman m...@snafu.org wrote:
 
 On Dec 7, 2012, at 8:18 PM, Steve Sisak sgs-li...@codewell.com wrote:
 
 I'm interested if there are an any issued I'm missing in the Obj-C, 
 @synchronized(self), instance variable case.
 
 
 Your pattern can fail if this line
_someDictionary = temp;
 isn't atomic.
 
 The real issue with double-checked locking is whether the compiler promises 
 to generate the proper memory barriers such that other threads are 
 guaranteed to see the assignment to _someDictionary *after* the object has 
 been constructed. C makes no such guarantee; other threads might see a 
 non-nil value for _someDictionary before the first thread is done 
 constructing the object.
 
 I'm fairly sure that @synchronized, being a compiler built-in, rather than a 
 function, makes that guarantee -- specifically the the values of instance 
 variables can change across entry and exit of an @synchronized block.

If you actually understood the problem with double-checked locking, you'd 
understand that the problem is with the early return that happens before the 
@synchronized block.

Please reread the Wikipedia article Ken linked to; the Java example exhibits 
*exactly* the same flaw as your Objective-C code.

 
 Further, if writes were not complete at the end of the block, the construct 
 would be essentially useless for its intended purpose.

Again, the problem exists *before* entering the @synchronized block.


 
 In any case, removing the outer check makes the code correct regardless of 
 compiler guarantees.

Yes, which is why your optimization is a classic anti-pattern.

--Kyle Sluder
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-12-08 Thread Kyle Sluder
On Dec 8, 2012, at 10:06 AM, Steve Sisak sgs-li...@codewell.com wrote:

 
 Further, if writes were not complete at the end of the block, the construct 
 would be essentially useless for its intended purpose.

By the way, you're wrong about this too. All @synchronized does is act as a 
mutex around a code block. It does not cause the compiler to reorder 
instructions and issue memory barriers in such a way that initialization is 
guaranteed to precede assignment from the perspective of all threads.

--Kyle Sluder

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-12-08 Thread Steve Sisak

At 10:24 AM -0800 12/8/12, Kyle Sluder wrote:

On Dec 8, 2012, at 10:06 AM, Steve Sisak sgs-li...@codewell.com wrote:

  Further, if writes were not complete at the end of the block, the 
construct would be essentially useless for its intended purpose.


By the way, you're wrong about this too. All @synchronized does is 
act as a mutex around a code block. It does not cause the compiler 
to reorder instructions and issue memory barriers in such a way that 
initialization is guaranteed to precede assignment from the 
perspective of all threads.


Please cite a source for this assertion.

From:

https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html

If you are already using a mutex to protect a section of code, do 
not automatically assume you need to use the volatile keyword to 
protect important variables inside that section. A mutex includes a 
memory barrier to ensure the proper ordering of load and store 
operations.


I acknowledge that, without proper memory barriers, double-checked 
locking is problematic, but am providing an example using a construct 
which I'm fairly sure uses proper memory barriers.


-Steve
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-12-08 Thread Ken Thomases
On Dec 8, 2012, at 1:17 PM, Steve Sisak wrote:

 At 10:24 AM -0800 12/8/12, Kyle Sluder wrote:
 On Dec 8, 2012, at 10:06 AM, Steve Sisak sgs-li...@codewell.com wrote:
 
  Further, if writes were not complete at the end of the block, the 
  construct would be essentially useless for its intended purpose.
 
 By the way, you're wrong about this too. All @synchronized does is act as a 
 mutex around a code block. It does not cause the compiler to reorder 
 instructions and issue memory barriers in such a way that initialization is 
 guaranteed to precede assignment from the perspective of all threads.
 
 Please cite a source for this assertion.
 
 From:
 
 https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html
 
 If you are already using a mutex to protect a section of code, do not 
 automatically assume you need to use the volatile keyword to protect 
 important variables inside that section. A mutex includes a memory barrier to 
 ensure the proper ordering of load and store operations.
 
 I acknowledge that, without proper memory barriers, double-checked locking is 
 problematic, but am providing an example using a construct which I'm fairly 
 sure uses proper memory barriers.

The memory barrier is only at the boundaries of the @synchronized block.  Your 
extra check is not protected by the memory barriers of the @synchronized block 
because it's not within it.

If you search for examples of fixed double-checked locking using explicit 
memory barriers, you'll see that one of the barriers occurs in the always-taken 
code path.  Your code does not have that.

Regards,
Ken


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-12-08 Thread Jean Suisse
Speaking of Double-Checked Locking, there is this interesting article from 
Scott Meyers and Andrei Alexandrescu, written in 2004, which states: 
This article explains why Singleton isn’t thread safe, how DCLP attempts to 
address that problem, why DCLP may fail on both uni- and multiprocessor 
ar-chitectures, and why you can’t (portably) do anything about it. Along the 
way, it clarifies the relationships among statement ordering in source code, 
sequence points, compiler and hardware optimizations, and the actual order of 
statement execution. Finally, it concludes with some suggestions regarding how 
to add thread-safety to Singleton (and similar constructs) such that the 
resulting code is both reliable and efficient.

DCLP = Double-Checked Locking Pattern
Link: http://erdani.com/publications/DDJ_Jul_Aug_2004_revised.pdf

Jean






---
Jean Suisse
Institut de Chimie Moléculaire de l’Université de Bourgogne
(ICMUB) — UMR 6302

U.F.R. Sciences et Techniques, Bâtiment Mirande
Aile B, bureau 413
9, avenue Alain Savary — B.P. 47870
21078 DIJON CEDEX












___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: How to implement readonly property

2012-12-08 Thread Greg Parker
On Dec 8, 2012, at 11:17 AM, Steve Sisak sgs-li...@codewell.com wrote:
 At 10:24 AM -0800 12/8/12, Kyle Sluder wrote:
 On Dec 8, 2012, at 10:06 AM, Steve Sisak sgs-li...@codewell.com wrote:
 
 Further, if writes were not complete at the end of the block, the construct 
 would besentially useless for its intended purpose.
 
 By the way, you're wrong about this too. All @synchronized does is act as a 
 mutex around a code block. It does not cause the compiler to reorder 
 instructions and issue memory barriers in such a way that initialization is 
 guaranteed to precede assignment from the perspective of all threads.
 
 Please cite a source for this assertion.

Source: me, the author of the current @synchronized implementation. 
@synchronized performs the same synchronization as a pthread mutex.


 From:
 
 https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html
 
 If you are already using a mutex to protect a section of code, do not 
 automatically assume you need to use the volatile keyword to protect 
 important variables inside that section. A mutex includes a memory barrier to 
 ensure the proper ordering of load and store operations.

To a close approximation, you should pretend that `volatile` does not exist in 
C-based languages.

The above says that if you already have mutexes then you do not need 
`volatile`. The mutex alone does all of the work. 

Conversely, `volatile` with no mutex is also not a safe multithreading pattern.


 I acknowledge that, without proper memory barriers, double-checked locking is 
 problematic, but am providing an example using a construct which I'm fairly 
 sure uses proper memory barriers.
 
 - (NSDictionary *)someDictionary;
 {
 if (!_someDictionary)
 {
   @synchronized (self)
   {
 if (!_someDictionary)
 {
   // create a temp dictionary (might take some time)
_someDictionary = temp;
 }
   }
 }
 
 return _someDictionary;
 }


The example provided does not use proper memory barriers. 

In general, memory barriers need to occur in pairs, one on each thread. The 
coordination of the two memory barriers achieves the desired synchronization, 
so that both sides observe events occurring in the same order.

Mutexes and similar constructs achieve this. The mutex lock() and unlock() 
procedures form a barrier pair. Code running with the mutex held is therefore 
correctly synchronized with respect to other code that runs with the mutex 
held. But code running outside the mutex is not protected, because it didn't 
call the barrier inside the lock() procedure.

In faulty double-checked locking code, the problem is that the writer has a 
memory barrier but the reader does not. Because it has no barriers, the reader 
may observe events occur out of the desired order. That's why it fails. (Here 
the writer is the thread actually calling the initializer and the reader is 
a second thread simultaneously performing the double-check sequence.)

(Faulty double-checked locking code has a second problem because the 
writer-side barrier inside the mutex unlock is the wrong barrier to use with a 
reader that is not locking the mutex.)

You need to do one of two things to fix the reader side of a double-checked 
lock:
* add appropriate barriers to the reader side, or 
* cheat in a way that is guaranteed to work on all architectures you care about.

dispatch_once() actually cheats. It performs a very expensive barrier on the 
writer side (much more expensive than the barriers used in ordinary mutexes and 
@synchronized), which guarantees that no barrier is needed on the reader side 
on the CPUs that run OS X and iOS. The expensive barrier on the reader side is 
an acceptable trade-off because the writer path runs only once.


-- 
Greg Parker gpar...@apple.com Runtime Wrangler



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-12-08 Thread Richard Heard
Greg, 

So, from what you are saying, either of these snippets should be valid, right?

 +(id)sharedInstance{
 static id _sharedInstance = nil;
 
 if (!_sharedInstance){
 @synchronized([self class]){
 if (!_sharedInstance){
 id sharedInstance = [[super allocWithZone:NULL] init];
 OSMemoryBarrier();
 _sharedInstance = sharedInstance;
 }
 }
 }
 
 OSMemoryBarrier();
 return _sharedInstance;
 }

vs

 +(id)sharedInstance{
 static id _sharedInstance = nil;
 
 static dispatch_once_t onceToken;
 dispatch_once(onceToken, ^{
 _sharedInstance = [[super allocWithZone:NULL] init];
 });
 
 return _sharedInstance;
 }


Any massive advantages / disadvantages with either approach?

-Richard

On 08/12/2012, at 4:45:37 PM, Greg Parker gpar...@apple.com wrote:

 On Dec 8, 2012, at 11:17 AM, Steve Sisak sgs-li...@codewell.com wrote:
 At 10:24 AM -0800 12/8/12, Kyle Sluder wrote:
 On Dec 8, 2012, at 10:06 AM, Steve Sisak sgs-li...@codewell.com wrote:
 
 Further, if writes were not complete at the end of the block, the 
 construct would besentially useless for its intended purpose.
 
 By the way, you're wrong about this too. All @synchronized does is act as a 
 mutex around a code block. It does not cause the compiler to reorder 
 instructions and issue memory barriers in such a way that initialization is 
 guaranteed to precede assignment from the perspective of all threads.
 
 Please cite a source for this assertion.
 
 Source: me, the author of the current @synchronized implementation. 
 @synchronized performs the same synchronization as a pthread mutex.
 
 
 From:
 
 https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html
 
 If you are already using a mutex to protect a section of code, do not 
 automatically assume you need to use the volatile keyword to protect 
 important variables inside that section. A mutex includes a memory barrier 
 to ensure the proper ordering of load and store operations.
 
 To a close approximation, you should pretend that `volatile` does not exist 
 in C-based languages.
 
 The above says that if you already have mutexes then you do not need 
 `volatile`. The mutex alone does all of the work. 
 
 Conversely, `volatile` with no mutex is also not a safe multithreading 
 pattern.
 
 
 I acknowledge that, without proper memory barriers, double-checked locking 
 is problematic, but am providing an example using a construct which I'm 
 fairly sure uses proper memory barriers.
 
 - (NSDictionary *)someDictionary;
 {
 if (!_someDictionary)
 {
  @synchronized (self)
  {
if (!_someDictionary)
{
  // create a temp dictionary (might take some time)
   _someDictionary = temp;
}
  }
 }
 
 return _someDictionary;
 }
 
 
 The example provided does not use proper memory barriers. 
 
 In general, memory barriers need to occur in pairs, one on each thread. The 
 coordination of the two memory barriers achieves the desired synchronization, 
 so that both sides observe events occurring in the same order.
 
 Mutexes and similar constructs achieve this. The mutex lock() and unlock() 
 procedures form a barrier pair. Code running with the mutex held is therefore 
 correctly synchronized with respect to other code that runs with the mutex 
 held. But code running outside the mutex is not protected, because it didn't 
 call the barrier inside the lock() procedure.
 
 In faulty double-checked locking code, the problem is that the writer has a 
 memory barrier but the reader does not. Because it has no barriers, the 
 reader may observe events occur out of the desired order. That's why it 
 fails. (Here the writer is the thread actually calling the initializer and 
 the reader is a second thread simultaneously performing the double-check 
 sequence.)
 
 (Faulty double-checked locking code has a second problem because the 
 writer-side barrier inside the mutex unlock is the wrong barrier to use with 
 a reader that is not locking the mutex.)
 
 You need to do one of two things to fix the reader side of a double-checked 
 lock:
 * add appropriate barriers to the reader side, or 
 * cheat in a way that is guaranteed to work on all architectures you care 
 about.
 
 dispatch_once() actually cheats. It performs a very expensive barrier on the 
 writer side (much more expensive than the barriers used in ordinary mutexes 
 and @synchronized), which guarantees that no barrier is needed on the reader 
 side on the CPUs that run OS X and iOS. The expensive barrier on the reader 
 side is an acceptable trade-off because the writer path runs only once.
 
 
 -- 
 Greg Parker gpar...@apple.com Runtime Wrangler
 
 
 
 ___
 
 Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
 
 Please do not post admin requests or moderator comments to the list.
 Contact the 

Re: How to implement readonly property

2012-12-08 Thread Greg Parker

On Dec 8, 2012, at 5:27 PM, Richard Heard heard...@gmail.com wrote:

 Greg, 
 
 So, from what you are saying, either of these snippets should be valid, right?
 
 +(id)sharedInstance{
 static id _sharedInstance = nil;
 
 if (!_sharedInstance){
 @synchronized([self class]){
 if (!_sharedInstance){
 id sharedInstance = [[super allocWithZone:NULL] init];
 OSMemoryBarrier();
 _sharedInstance = sharedInstance;
 }
 }
 }
 
 OSMemoryBarrier();
 return _sharedInstance;
 }
 
 vs
 
 +(id)sharedInstance{
 static id _sharedInstance = nil;
 
 static dispatch_once_t onceToken;
 dispatch_once(onceToken, ^{
 _sharedInstance = [[super allocWithZone:NULL] init];
 });
 
 return _sharedInstance;
 }
 
 
 Any massive advantages / disadvantages with either approach?

Use dispatch_once(). It is shorter, simpler, and more obviously correct. The 
memory barrier implementation may also be correct, but why take the risk?


-- 
Greg Parker gpar...@apple.com Runtime Wrangler


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-12-08 Thread Rick Mann

On Dec 8, 2012, at 18:51 , Greg Parker gpar...@apple.com wrote:

 Use dispatch_once(). It is shorter, simpler, and more obviously correct. The 
 memory barrier implementation may also be correct, but why take the risk?

What about for similar non-static properties?

-- 
Rick




___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-12-08 Thread Kyle Sluder
On Sat, Dec 8, 2012, at 05:27 PM, Richard Heard wrote:
 Greg, 
 
 So, from what you are saying, either of these snippets should be valid,
 right?
 
  +(id)sharedInstance{
  static id _sharedInstance = nil;
  
  if (!_sharedInstance){
  @synchronized([self class]){
  if (!_sharedInstance){
  id sharedInstance = [[super allocWithZone:NULL] init];
  OSMemoryBarrier();
  _sharedInstance = sharedInstance;
  }
  }
  }
  
  OSMemoryBarrier();
  return _sharedInstance;
  }

Greg's advice notwithstanding, I'm not certain this is correct. You need
to ensure Thread B's read of _sharedInstance is atomic with respect to
both Thread A's assignment to _sharedInstance *and* the construction of
the object to which _sharedInstance points. By putting the always-taken
memory barrier _after_ the conditional, you've failed to guarantee the
order of Thread B's branch relative to Thread A's assignment to
_sharedInstance.

The first example of corrected double-checked locking in this paper
issues the memory barrier before reading the value of _sharedInstance
from outside the critical section:
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

If dispatch_once() really is unsuitable for use with a dispatch_once_t
stored in Objective-C instance storage, then the correct example in the
paper I've cited might be a sufficient workaround.

Of course, it's just as simple to push the entire contents of your
+sharedInstance method into the critical section and not have to worry
about memory barriers at all by relying on the coarser, higher-order
synchronization primitive @synchronized provides. The performance hit is
probably negligible.

--Kyle Sluder
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-12-07 Thread Greg Parker
On Dec 7, 2012, at 7:03 AM, Jeremy Pereira jere...@jeremyp.net wrote:
 On 12 Nov 2012, at 20:45, Greg Parker gpar...@apple.com wrote:
 There is something special about statically-allocated memory. 
 Statically-allocated memory has always been zero for the life of the 
 process. Dynamically-allocated memory may have been non-zero at some point 
 in the past (i.e. if it was previously part of a now-freed allocation).
 
 The problem is your condition #2. If the memory was previously non-zero and 
 you set it to zero, you need appropriate memory barriers on some 
 architectures to prevent a race where the caller of dispatch_once() sees the 
 old non-zero value. Neither dispatch_once() nor the malloc system nor the 
 Objective-C runtime promise to provide the correct barriers.
 
 In some cases you might be able to add an appropriate memory barrier to your 
 -init... method, assuming that no calls to dispatch_once() occur before 
 then. 
 
 In practice this is a difficult race to hit, but it's not impossible.
 
 Sorry, I'm a bit late to the party here but I've just read this and I don't 
 understand it.  
 
 If this race condition really exists, you couldn't assume that *any* instance 
 variables of a newly initialised object have been zeroed out.
 
 What am I missing?

Your statement is missing the additional requirements to hit the race:

You can't assume that any instance variables of a newly initialized object have 
been zeroed out when
* you are reading them from threads other than the one that allocated the 
object and 
* there is no synchronization between the allocating thread and the reading 
thread.

In ordinary code there is only one thread involved, or there is already some 
thread synchronization somewhere. 

For example, the allocating thread acquires a lock before writing the new 
object's pointer somewhere that the reading thread can see it, and the reading 
thread takes the same lock before reading the object pointer. That lock is 
sufficient synchronization to make it work.

You'll only run into trouble if you are trying to use lock-free multiprocessing 
techniques and you don't use enough memory barriers.


-- 
Greg Parker gpar...@apple.com Runtime Wrangler



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-12-07 Thread Ken Thomases
On Dec 7, 2012, at 3:08 PM, Greg Parker wrote:

 On Dec 7, 2012, at 7:03 AM, Jeremy Pereira jere...@jeremyp.net wrote:
 On 12 Nov 2012, at 20:45, Greg Parker gpar...@apple.com wrote:
 There is something special about statically-allocated memory. 
 Statically-allocated memory has always been zero for the life of the 
 process. Dynamically-allocated memory may have been non-zero at some point 
 in the past (i.e. if it was previously part of a now-freed allocation).
 
 The problem is your condition #2. If the memory was previously non-zero and 
 you set it to zero, you need appropriate memory barriers on some 
 architectures to prevent a race where the caller of dispatch_once() sees 
 the old non-zero value. Neither dispatch_once() nor the malloc system nor 
 the Objective-C runtime promise to provide the correct barriers.
 
 In some cases you might be able to add an appropriate memory barrier to 
 your -init... method, assuming that no calls to dispatch_once() occur 
 before then. 
 
 In practice this is a difficult race to hit, but it's not impossible.
 
 Sorry, I'm a bit late to the party here but I've just read this and I don't 
 understand it.  
 
 If this race condition really exists, you couldn't assume that *any* 
 instance variables of a newly initialised object have been zeroed out.
 
 What am I missing?
 
 Your statement is missing the additional requirements to hit the race:
 
 You can't assume that any instance variables of a newly initialized object 
 have been zeroed out when
 * you are reading them from threads other than the one that allocated the 
 object and 
 * there is no synchronization between the allocating thread and the reading 
 thread.
 
 In ordinary code there is only one thread involved, or there is already some 
 thread synchronization somewhere. 
 
 For example, the allocating thread acquires a lock before writing the new 
 object's pointer somewhere that the reading thread can see it, and the 
 reading thread takes the same lock before reading the object pointer. That 
 lock is sufficient synchronization to make it work.
 
 You'll only run into trouble if you are trying to use lock-free 
 multiprocessing techniques and you don't use enough memory barriers.

But this means that dispatch_once() is not uniquely unsafe.  It can fail only 
in the exact same scenarios where a thread other than the one which allocated 
an object might see uninitialized values for generic instance variables.  Such 
scenarios are, of course, unacceptable and so proper synchronization is 
necessary when passing object pointers between threads, full stop.  There's no 
special care necessary to make dispatch_once() safe, there's just the ordinary 
care necessary to make passing of object pointers between threads sane.

You said that dispatch_once() doesn't promise to provide memory barriers, but, 
since the use of GCD hasn't brought catastrophe down on all of our heads, I 
assume that dispatch_async() and the like do provide such memory barriers.  
Likewise, NSOperationQueue, -performSelector:onThread:..., and the like must 
also.  Is that right?

If you wanted to be paranoid about using an instance variable as a once 
predicate, is it sufficient to use OSMemoryBarrier() in the -init method of the 
object?  Or perhaps there needs to be another call to OSMemoryBarrier() 
immediate before the dispatch_once() call, too.

Regards,
Ken


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-12-07 Thread Jeremy Pereira

On 12 Nov 2012, at 20:45, Greg Parker gpar...@apple.com wrote:

 
 
 There is something special about statically-allocated memory. 
 Statically-allocated memory has always been zero for the life of the process. 
 Dynamically-allocated memory may have been non-zero at some point in the past 
 (i.e. if it was previously part of a now-freed allocation).
 
 The problem is your condition #2. If the memory was previously non-zero and 
 you set it to zero, you need appropriate memory barriers on some 
 architectures to prevent a race where the caller of dispatch_once() sees the 
 old non-zero value. Neither dispatch_once() nor the malloc system nor the 
 Objective-C runtime promise to provide the correct barriers.
 
 In some cases you might be able to add an appropriate memory barrier to your 
 -init... method, assuming that no calls to dispatch_once() occur before then. 
 
 In practice this is a difficult race to hit, but it's not impossible.
 

Sorry, I'm a bit late to the party here but I've just read this and I don't 
understand it.  

If this race condition really exists, you couldn't assume that *any* instance 
variables of a newly initialised object have been zeroed out.

What am I missing?


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-12-07 Thread Greg Parker
On Dec 7, 2012, at 2:04 PM, Ken Thomases k...@codeweavers.com wrote:
 On Dec 7, 2012, at 3:08 PM, Greg Parker wrote:
 
 You can't assume that any instance variables of a newly initialized object 
 have been zeroed out when
 * you are reading them from threads other than the one that allocated the 
 object and 
 * there is no synchronization between the allocating thread and the reading 
 thread.
 
 In ordinary code there is only one thread involved, or there is already some 
 thread synchronization somewhere. 
 
 For example, the allocating thread acquires a lock before writing the new 
 object's pointer somewhere that the reading thread can see it, and the 
 reading thread takes the same lock before reading the object pointer. That 
 lock is sufficient synchronization to make it work.
 
 You'll only run into trouble if you are trying to use lock-free 
 multiprocessing techniques and you don't use enough memory barriers.
 
 But this means that dispatch_once() is not uniquely unsafe.  It can fail only 
 in the exact same scenarios where a thread other than the one which allocated 
 an object might see uninitialized values for generic instance variables.  
 Such scenarios are, of course, unacceptable and so proper synchronization is 
 necessary when passing object pointers between threads, full stop.  There's 
 no special care necessary to make dispatch_once() safe, there's just the 
 ordinary care necessary to make passing of object pointers between threads 
 sane.

That's right. The problem specific to dispatch_once() is that people sometimes 
use dispatch_once() in lieu of other synchronization expecting dispatch_once() 
itself to provide more synchronization than it actually does. 


 You said that dispatch_once() doesn't promise to provide memory barriers, 
 but, since the use of GCD hasn't brought catastrophe down on all of our 
 heads, I assume that dispatch_async() and the like do provide such memory 
 barriers.  Likewise, NSOperationQueue, -performSelector:onThread:..., and the 
 like must also.  Is that right?

I would expect that any multiprocessing primitive that does not provide 
sufficient memory barriers for some uses would document that fact loudly. 
dispatch_once()'s storage is one documented example of missing barriers. Some 
of the OSAtomic functions are another example. But pretty much everything 
heavier-weight than that ought to provide complete memory barriers for any 
clients.


 If you wanted to be paranoid about using an instance variable as a once 
 predicate, is it sufficient to use OSMemoryBarrier() in the -init method of 
 the object?  Or perhaps there needs to be another call to OSMemoryBarrier() 
 immediate before the dispatch_once() call, too.

Maybe. It depends on the architecture and the precise implementation of 
dispatch_once(). 

My guess is that OSMemoryBarrier() in -init is sufficient for 
dispatch_once(ivar) on all current OS X and iOS architectures and any other 
reasonable architectures, and is required on some of them.

(As usual, the unreasonable architecture is the DEC Alpha, whose memory 
consistency rules were too loose for mere humans to manage correctly. It looks 
like everyone learned since then that putting zero data-dependency enforcement 
in the CPU was a step too far.)


-- 
Greg Parker gpar...@apple.com Runtime Wrangler



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-12-07 Thread Steve Sisak

At 7:56 PM +0700 11/12/12, Gerriet M. Denkmann wrote:

- (NSDictionary *)someDictionary;
{
static NSDictionary *someDictionary;
static dispatch_once_t justOnce;
dispatch_once( justOnce, ^
{
// create a temp dictionary (might take some time)
someDictionary = temp;
}
);

return someDictionary;
}


Here's what I usually do:

assume that _someDictionary is an instance variable initialized to 
nil and never changed once initialized to non-nil


- (NSDictionary *)someDictionary;
{
  if (!_someDictionary)
  {
@synchronized (self)
{
  if (!_someDictionary)
  {
// create a temp dictionary (might take some time)
 _someDictionary = temp;
  }
}
  }

  return _someDictionary;
}

the outer if avoids the overhead of @synchronized if _someDictionary 
is already created -- this is just an optimization


the inner if is necessary to resolve the race condition if multiple 
threads make it past the outer one


HTH,

-Steve
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-12-07 Thread Ken Thomases
On Dec 7, 2012, at 8:01 PM, Steve Sisak wrote:

 Here's what I usually do:
 
 assume that _someDictionary is an instance variable initialized to nil and 
 never changed once initialized to non-nil
 
 - (NSDictionary *)someDictionary;
 {
  if (!_someDictionary)
  {
@synchronized (self)
{
  if (!_someDictionary)
  {
// create a temp dictionary (might take some time)
 _someDictionary = temp;
  }
}
  }
 
  return _someDictionary;
 }
 
 the outer if avoids the overhead of @synchronized if _someDictionary is 
 already created -- this is just an optimization
 
 the inner if is necessary to resolve the race condition if multiple threads 
 make it past the outer one

This is a classic anti-pattern called double-checked locking.  It is not safe.  
Don't rely on it.
https://en.wikipedia.org/wiki/Double-checked_locking
http://erdani.com/publications/DDJ_Jul_Aug_2004_revised.pdf

Regards,
Ken


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-12-07 Thread Steve Sisak

At 8:57 PM -0600 12/7/12, Ken Thomases wrote:
  the outer if avoids the overhead of 
@synchronized if _someDictionary is already 
created -- this is just an optimization


 the inner if is necessary to resolve the race 
condition if multiple threads make it past the 
outer one


This is a classic anti-pattern called 
double-checked locking.  It is not safe.  Don't 
rely on it.

https://en.wikipedia.org/wiki/Double-checked_locking
http://erdani.com/publications/DDJ_Jul_Aug_2004_revised.pdf


Hi Ken,

From the first link you cite:

The pattern, when implemented in some 
language/hardware combinations, can be unsafe. 
At times, it can be considered an 
anti-pattern.[2]


That is far different from being a a classic anti-pattern.

In this example:

1) The language is Obj-C
2) I explicitly used @synchronized(self) and an instance variable

So, in this case, what I'm doing is explicitly supported by the language.

Your second article is explicitly focused on C++ 
(and singletons) -- it's also dated 2004.


On Mac OS X, the correct implementation of a 
singleton is dispatch_once() -- in fact, that is 
the function's raison d'être.


So, while I support the position that 
double-checked locking can be unsafe in con 
language/hardware combination, in this case we're 
using language features specifically designed for 
the purpose.


That said, it's worth noting that you need to 
understand your complier when dealing with 
synchronization.


I'm interested if there are an any issued I'm 
missing in the Obj-C, @synchronized(self), 
instance variable case.


-Steve



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: How to implement readonly property

2012-12-07 Thread Marco S Hyman
On Dec 7, 2012, at 8:18 PM, Steve Sisak sgs-li...@codewell.com wrote:

 I'm interested if there are an any issued I'm missing in the Obj-C, 
 @synchronized(self), instance variable case.


Your pattern can fail if this line
_someDictionary = temp;
isn't atomic.



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-11-12 Thread Marco Tabini
Looking at the docs, dispatch_once takes care of the synchronization for you:

https://developer.apple.com/library/mac/ipad/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html

It should therefore be thread safe to use without any additional 
synchronization code. 

Sent from my New iPad. I blame all typos on the Fruit Company. May have been 
dictated. 

On 2012-11-12, at 7:56 AM, Gerriet M. Denkmann gerr...@mdenkmann.de wrote:

 I have a property:
 
 @property (readonly)  NSDictionary *someDictionary;
 
 This property should be computed on demand, and should be accessible by 
 several threads.
 
 My current implementation is:
 
 - (NSDictionary *)someDictionary;
 {
static NSDictionary *someDictionary;
static dispatch_once_t justOnce;
dispatch_once( justOnce, ^
{
// create a temp dictionary (might take some time)
someDictionary = temp;
}
);
 
return someDictionary;
 }
 
 The first thread which needs someDictionary will trigger its creation. Ok.
 
 But what happens when another thread wants to access someDictionary while it 
 is still being created? I guess it will receive just nil.
 This would be not correct; it really should wait until the dictionary is 
 ready.
 
 How to achieve this? Use a lock? Use @synchronize?
 
 10.8.2 with Arc.
 
 
 Gerriet.
 
 
 ___
 
 Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
 
 Please do not post admin requests or moderator comments to the list.
 Contact the moderators at cocoa-dev-admins(at)lists.apple.com
 
 Help/Unsubscribe/Update your Subscription:
 https://lists.apple.com/mailman/options/cocoa-dev/mtabini%40me.com
 
 This email sent to mtab...@me.com
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-11-12 Thread Tom Davie

On 12 Nov 2012, at 12:56, Gerriet M. Denkmann gerr...@mdenkmann.de wrote:

 I have a property:
 
 @property (readonly)  NSDictionary *someDictionary;   
 
 This property should be computed on demand, and should be accessible by 
 several threads.
 
 My current implementation is:
 
 - (NSDictionary *)someDictionary;
 {
   static NSDictionary *someDictionary;
   static dispatch_once_t justOnce;
   dispatch_once( justOnce, ^
   {
   // create a temp dictionary (might take some time)
   someDictionary = temp;
   }
   );
 
   return someDictionary;
 }
 
 The first thread which needs someDictionary will trigger its creation. Ok.
 
 But what happens when another thread wants to access someDictionary while it 
 is still being created? I guess it will receive just nil.
 This would be not correct; it really should wait until the dictionary is 
 ready.
 
 How to achieve this? Use a lock? Use @synchronize?

This is completely the wrong way to implement a property.  The static variable 
will be shared between all instances.  Here's how you should be doing a lazy 
loaded var:

@implementation MyClass
{
NSDictionary *_someDictionary
}

- (NSDictionary *)someDictionary
{
static dispatch_once_t justOnce;
dispatch_once(justOnce, ^
{
someDictionary = [[NSDictionary alloc] initWithObjectsAndKeys: …… 
nil];
});
return someDictionary;
}

In answer to your threading question.  If multiple threads ask for the 
dictionary at once, the second one to hit the dispatch_once will block until 
the first one has finished the dispatch_once block, and then continue to 
execute (without touching the contents).  Thus, both threads will receive the 
same dictionary (assuming it's the same instance it's called on), and it will 
be allocated only once.

Tom Davie
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: How to implement readonly property

2012-11-12 Thread Marco Tabini
 This is completely the wrong way to implement a property.  The static 
 variable will be shared between all instances.  Here's how you should be 
 doing a lazy loaded var:
 
 @implementation MyClass
 {
NSDictionary *_someDictionary
 }
 
 - (NSDictionary *)someDictionary
 {
static dispatch_once_t justOnce;
dispatch_once(justOnce, ^
{
someDictionary = [[NSDictionary alloc] initWithObjectsAndKeys: …… 
 nil];
});
return someDictionary;
 }

I don't think this does what you think it does; my understanding is that 
dispatch_once will execute only once for the lifetime of an app, so the code 
you posted will only run once for the first object that requires is, and then 
never run again, resulting in _dictionary being Nil in all other instances.

I understood the OP's request as wanting to implement a singleton, which, based 
on your reading, may not be the case. dispatch_once will be fine for a 
singleton, but if you need a thread-safe, lazily-instantiated read-only 
property, maybe something like this will do the trick:

@implementation MyClass {
  NSDictionary *_someDictionary
}

- (NSDictionary *) someDictionary {
  @synchronized(self) {
if (!_someDictionary) {
  _someDictionary = [[NSDictionary alloc] initWith… ]
}
  }

  return _someDictionary;
}
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: How to implement readonly property

2012-11-12 Thread Tom Davie

On 12 Nov 2012, at 13:39, Marco Tabini mtab...@me.com wrote:

 This is completely the wrong way to implement a property.  The static 
 variable will be shared between all instances.  Here's how you should be 
 doing a lazy loaded var:
 
 @implementation MyClass
 {
   NSDictionary *_someDictionary
 }
 
 - (NSDictionary *)someDictionary
 {
   static dispatch_once_t justOnce;
   dispatch_once(justOnce, ^
   {
   someDictionary = [[NSDictionary alloc] initWithObjectsAndKeys: …… 
 nil];
   });
   return someDictionary;
 }
 
 I don't think this does what you think it does; my understanding is that 
 dispatch_once will execute only once for the lifetime of an app, so the code 
 you posted will only run once for the first object that requires is, and then 
 never run again, resulting in _dictionary being Nil in all other instances.

Very good point!  My bad.

 I understood the OP's request as wanting to implement a singleton, which, 
 based on your reading, may not be the case. dispatch_once will be fine for a 
 singleton, but if you need a thread-safe, lazily-instantiated read-only 
 property, maybe something like this will do the trick:

I'm pretty sure he doesn't want a singleton, as he was talking about a 
property.  And yeh, sorry about the misinformation there!

 
 @implementation MyClass {
  NSDictionary *_someDictionary
 }
 
 - (NSDictionary *) someDictionary {
  @synchronized(self) {
if (!_someDictionary) {
  _someDictionary = [[NSDictionary alloc] initWith… ]
}
  }
 
  return _someDictionary;
 }


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: How to implement readonly property

2012-11-12 Thread Joerg Simon
You can use dispatch_sync. The blog post of oliver dobnigg (cocoanetics) summs 
that up quite nicely:
http://www.cocoanetics.com/2012/02/threadsafe-lazy-property-initialization/

Cheers, Jörg
On Nov 12, 2012, at 2:44 PM, Tom Davie tom.da...@gmail.com wrote:

 
 On 12 Nov 2012, at 13:39, Marco Tabini mtab...@me.com wrote:
 
 This is completely the wrong way to implement a property.  The static 
 variable will be shared between all instances.  Here's how you should be 
 doing a lazy loaded var:
 
 @implementation MyClass
 {
  NSDictionary *_someDictionary
 }
 
 - (NSDictionary *)someDictionary
 {
  static dispatch_once_t justOnce;
  dispatch_once(justOnce, ^
  {
  someDictionary = [[NSDictionary alloc] initWithObjectsAndKeys: …… 
 nil];
  });
  return someDictionary;
 }
 
 I don't think this does what you think it does; my understanding is that 
 dispatch_once will execute only once for the lifetime of an app, so the code 
 you posted will only run once for the first object that requires is, and 
 then never run again, resulting in _dictionary being Nil in all other 
 instances.
 
 Very good point!  My bad.
 
 I understood the OP's request as wanting to implement a singleton, which, 
 based on your reading, may not be the case. dispatch_once will be fine for a 
 singleton, but if you need a thread-safe, lazily-instantiated read-only 
 property, maybe something like this will do the trick:
 
 I'm pretty sure he doesn't want a singleton, as he was talking about a 
 property.  And yeh, sorry about the misinformation there!
 
 
 @implementation MyClass {
 NSDictionary *_someDictionary
 }
 
 - (NSDictionary *) someDictionary {
 @synchronized(self) {
   if (!_someDictionary) {
 _someDictionary = [[NSDictionary alloc] initWith… ]
   }
 }
 
 return _someDictionary;
 }
 
 
 ___
 
 Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
 
 Please do not post admin requests or moderator comments to the list.
 Contact the moderators at cocoa-dev-admins(at)lists.apple.com
 
 Help/Unsubscribe/Update your Subscription:
 https://lists.apple.com/mailman/options/cocoa-dev/j_simon%40mac.com
 
 This email sent to j_si...@mac.com


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: How to implement readonly property

2012-11-12 Thread Tom Davie

On 12 Nov 2012, at 14:18, Joerg Simon j_si...@mac.com wrote:

 You can use dispatch_sync. The blog post of oliver dobnigg (cocoanetics) 
 summs that up quite nicely:
 http://www.cocoanetics.com/2012/02/threadsafe-lazy-property-initialization/

Or you can use dispatch_once, but make sure the once token is an ivar, unlike I 
did.

Tom Davie
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-11-12 Thread Joerg Simon
As you can read in the blog too, the developer documentation of dispatch_once 
states:

The predicate must point to a variable stored in global or static scope. The 
result of using a predicate with automatic or dynamic storage is undefined.

so, no, you can not. Actually it works most of the time, but you can not rely 
on it...

Cheers, Jörg

On Nov 12, 2012, at 3:33 PM, Tom Davie tom.da...@gmail.com wrote:

 
 On 12 Nov 2012, at 14:18, Joerg Simon j_si...@mac.com wrote:
 
 You can use dispatch_sync. The blog post of oliver dobnigg (cocoanetics) 
 summs that up quite nicely:
 http://www.cocoanetics.com/2012/02/threadsafe-lazy-property-initialization/
 
 Or you can use dispatch_once, but make sure the once token is an ivar, unlike 
 I did.
 
 Tom Davie


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: How to implement readonly property

2012-11-12 Thread Ken Thomases
On Nov 12, 2012, at 8:41 AM, Joerg Simon wrote:

 On Nov 12, 2012, at 3:33 PM, Tom Davie tom.da...@gmail.com wrote:
 
 On 12 Nov 2012, at 14:18, Joerg Simon j_si...@mac.com wrote:
 
 You can use dispatch_sync. The blog post of oliver dobnigg (cocoanetics) 
 summs that up quite nicely:
 http://www.cocoanetics.com/2012/02/threadsafe-lazy-property-initialization/
 
 Or you can use dispatch_once, but make sure the once token is an ivar, 
 unlike I did.
 
 As you can read in the blog too, the developer documentation of dispatch_once 
 states:
 
 The predicate must point to a variable stored in global or static scope. The 
 result of using a predicate with automatic or dynamic storage is undefined.
 
 so, no, you can not. Actually it works most of the time, but you can not rely 
 on it...

Far be it from me to discourage people from paying attention to the docs, but 
I'm pretty sure that the docs are excessively restrictive in this case.

From working with similar constructs in other APIs, I believe the actual 
requirements are:

1) All of the threads which are to coordinate on doing a task exactly once must 
be referring to the same storage for the once predicate.

2) The predicate storage has to be guaranteed to have been allocated and 
initialized to zero before any threads access it.

3) The storage must not be deallocated until after it is guaranteed that no 
threads will reference it again.

Obviously, automatic storage violates rule 1.  Most schemes which try to 
dynamically allocate the storage just before it's needed would normally run 
into the same race condition that dispatch_once() is trying to solve.  And the 
most common anticipated use case is for ensuring that a given task is only 
performed once, globally.  So, avoiding dynamic storage is a nice simple rule.  
(It's also easy to forget to set dynamically allocated storage to zero before 
using it.)

But an instance variable still satisfies all three requirements for the case 
where a task needs to be performed only once per instance.

And the blog's speculation that there's some special characteristic of 
statically allocated memory vs. dynamically allocated memory that is important 
to dispatch_once()'s synchronization strikes me as very, very improbable.

Regards,
Ken


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to implement readonly property

2012-11-12 Thread Greg Parker
On Nov 12, 2012, at 8:36 AM, Ken Thomases k...@codeweavers.com wrote:
 Far be it from me to discourage people from paying attention to the docs, but 
 I'm pretty sure that the docs are excessively restrictive in this case.
 
 From working with similar constructs in other APIs, I believe the actual 
 requirements are:
 
 1) All of the threads which are to coordinate on doing a task exactly once 
 must be referring to the same storage for the once predicate.
 
 2) The predicate storage has to be guaranteed to have been allocated and 
 initialized to zero before any threads access it.
 
 3) The storage must not be deallocated until after it is guaranteed that no 
 threads will reference it again.
 
 Obviously, automatic storage violates rule 1.  Most schemes which try to 
 dynamically allocate the storage just before it's needed would normally run 
 into the same race condition that dispatch_once() is trying to solve.  And 
 the most common anticipated use case is for ensuring that a given task is 
 only performed once, globally.  So, avoiding dynamic storage is a nice simple 
 rule.  (It's also easy to forget to set dynamically allocated storage to zero 
 before using it.)
 
 But an instance variable still satisfies all three requirements for the case 
 where a task needs to be performed only once per instance.
 
 And the blog's speculation that there's some special characteristic of 
 statically allocated memory vs. dynamically allocated memory that is 
 important to dispatch_once()'s synchronization strikes me as very, very 
 improbable.


There is something special about statically-allocated memory. 
Statically-allocated memory has always been zero for the life of the process. 
Dynamically-allocated memory may have been non-zero at some point in the past 
(i.e. if it was previously part of a now-freed allocation).

The problem is your condition #2. If the memory was previously non-zero and you 
set it to zero, you need appropriate memory barriers on some architectures to 
prevent a race where the caller of dispatch_once() sees the old non-zero value. 
Neither dispatch_once() nor the malloc system nor the Objective-C runtime 
promise to provide the correct barriers.

In some cases you might be able to add an appropriate memory barrier to your 
-init... method, assuming that no calls to dispatch_once() occur before then. 

In practice this is a difficult race to hit, but it's not impossible.


-- 
Greg Parker gpar...@apple.com Runtime Wrangler



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com