On Tue, Aug 5, 2014 at 2:50 AM, Nick Wellnhofer <[email protected]> wrote: > On 04/08/2014 22:37, Marvin Humphrey wrote:
>> Could we instead decide that Clone() is not thread safe? And then in the >> context of duplicating `klass->name` and the like we'd use some other >> constructor instead of Clone(). > > OK with me. It will only be surprising for anyone who really needs to clone > a String and doesn't know that String is special in that regard. Yeah, you're right. :\ We have a funny overlap between Clone() and Inc_RefCount(). Both involve taking ownership of a refcount. Both involve optimizations around not-completely independent copies. I feel like we ought to be able to disentangle this situation, and that when we finish there should be fewer methods on Obj. The best answer will probably reveal itself as we add more host languages. > It depends on what guarantees LFReg#Clone should make exactly. I think it's > OK if it returns a clone of the registry in some arbitrary state during the > cloning process. For example, if a single object is inserted during the > cloning process, it would be OK to return a clone without that object. The > registry could change immediately after the final size check anyway. > > But my implementation could return a version of the registry in a completely > different state. If, during cloning, object A is inserted first and then > object B, a version with only object B could be returned. This is clearly a > bug, so let's skip that commit. > >> Iteration, in contrast, simply cannot defend against concurrent >> modifications without locking. And therefore this implementation suffices. >> Very nice, actually! > > Iteration suffers from the same problem mentioned above. This could, for > example, lead to finding a class but not its parent. > > This is all more complicated than I initially thought, so I'll leave LFReg > as is. Check out the caveats in the docs on iteration with Java's ConcurrentHashMap or enumeration with C#'s ConcurrentDictionary. It doesn't matter what kind of engineering resources you throw at this problem -- even exemplary implementations are incredibly hard to reason about and use safely. "All shared state immutable and all mutable state thread-private" ought to be an acceptable model of concurrency for Clownfish. Abstracting a common interface which generalizes the wildly varying multi-threading capabilities of various hosts is not feasible in any case. I'm content to have LockFreeRegistry remain a private implementation detail of the Clownfish runtime forever -- exposing it as a public API is not central to the project's mission. >> One thing to think about is that if we add interfaces to Clownfish, we'll >> have to normalize the various signatures of Next(), perhaps necessitating >> that we access key and value via Get_Key() and Get_Value(). But that >> applies to several other iterators as well, so shouldn't block this commit. > > +1 for Get_Key() and Get_Value(). I'm also for separate Iterator objects in > general. But let's ignore that for now. The iterator you wrote for LockFreeRegistry could easily be adapted for Hash. I talked to my colleague Tim Wilkens about that today and it looks like he's interested in picking up that task. Marvin Humphrey
