JezK
Edit File: cdesc-Striped64.ri
U:RDoc::NormalClass[iI"Striped64:EFI",Concurrent::ThreadSafe::Util::Striped64;FI"Object;To:RDoc::Markup::Document:@parts[o;;[o:RDoc::Markup::Paragraph;[I"GA Ruby port of the Doug Lea's jsr166e.Striped64 class version 1.6 ;TI" available in public domain.;To:RDoc::Markup::BlankLine o; ;[I"*Original source code available here: ;TI"`http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/Striped64.java?revision=1.6;T@o; ;[I"NClass holding common representation and mechanics for classes supporting ;TI"&dynamic striping on 64bit values.;T@o; ;[ I"KThis class maintains a lazily-initialized table of atomically updated ;TI"Nvariables, plus an extra +base+ field. The table size is a power of two. ;TI"LIndexing uses masked per-thread hash codes. Nearly all methods on this ;TI"8class are private, accessed directly by subclasses.;T@o; ;[I"JTable entries are of class +Cell+; a variant of AtomicLong padded to ;TI"Nreduce cache contention on most processors. Padding is overkill for most ;TI"OAtomics because they are usually irregularly scattered in memory and thus ;TI"Jdon't interfere much with each other. But Atomic objects residing in ;TI"Larrays will tend to be placed adjacent to each other, and so will most ;TI"Ooften share cache lines (with a huge negative performance impact) without ;TI"this precaution.;T@o; ;[I"PIn part because +Cell+s are relatively large, we avoid creating them until ;TI"Othey are needed. When there is no contention, all updates are made to the ;TI"N+base+ field. Upon first contention (a failed CAS on +base+ update), the ;TI"Ltable is initialized to size 2. The table size is doubled upon further ;TI"Ncontention until reaching the nearest power of two greater than or equal ;TI"Lto the number of CPUS. Table slots remain empty (+nil+) until they are ;TI"needed.;T@o; ;[ I"JA single spinlock (+busy+) is used for initializing and resizing the ;TI"Otable, as well as populating slots with new +Cell+s. There is no need for ;TI"Na blocking lock: When the lock is not available, threads try other slots ;TI"L(or the base). During these retries, there is increased contention and ;TI"?reduced locality, which is still better than alternatives.;T@o; ;[ I"OPer-thread hash codes are initialized to random values. Contention and/or ;TI"Ntable collisions are indicated by failed CASes when performing an update ;TI"Poperation (see method +retry_update+). Upon a collision, if the table size ;TI"Ois less than the capacity, it is doubled in size unless some other thread ;TI"Mholds the lock. If a hashed slot is empty, and lock is available, a new ;TI"O+Cell+ is created. Otherwise, if the slot exists, a CAS is tried. Retries ;TI"Nproceed by "double hashing", using a secondary hash (XorShift) to try to ;TI"find a free slot.;T@o; ;[I"NThe table size is capped because, when there are more threads than CPUs, ;TI"Isupposing that each thread were bound to a CPU, there would exist a ;TI"Pperfect hash function mapping threads to slots that eliminates collisions. ;TI"PWhen we reach capacity, we search for this mapping by randomly varying the ;TI"Ohash codes of colliding threads. Because search is random, and collisions ;TI"Nonly become known via CAS failures, convergence can be slow, and because ;TI"Lthreads are typically not bound to CPUS forever, may not occur at all. ;TI"GHowever, despite these limitations, observed contention rates are ;TI""typically low in these cases.;T@o; ;[I"PIt is possible for a +Cell+ to become unused when threads that once hashed ;TI"Pto it terminate, as well as in the case where doubling the table causes no ;TI"Jthread to hash to it under expanded mask. We do not try to detect or ;TI"Nremove such cells, under the assumption that for long-running instances, ;TI"Lobserved contention levels will recur, so the cells will eventually be ;TI"@needed again; and for short-lived ones, it does not matter.;T@o; ;[I"@!visibility private;T: @fileI"1lib/concurrent/thread_safe/util/striped64.rb;T:0@omit_headings_from_table_of_contents_below0;0;0[ [U:RDoc::Constant[i I"THREAD_LOCAL_KEY;FI">Concurrent::ThreadSafe::Util::Striped64::THREAD_LOCAL_KEY;F00o;;[o; ;[ I"EStatic per-thread hash code key. Shared across all instances to ;TI"Creduce Thread locals pollution and because adjustments due to ;TI">collisions in one table are likely to be appropriate for ;TI"others.;T;@Z;0@Z@cRDoc::NormalClass0[ [[I" class;T[[:public[[I"new;TI"1lib/concurrent/thread_safe/util/striped64.rb;T[:protected[ [:private[ [I" instance;T[[;[[I"retry_update;F@s[;[ [;[[I"cas_base_computed;F@s[I"expand_table_unless_stale;F@s[I" free?;F@s[I"hash_code;F@s[I"hash_code=;F@s[I"internal_reset;F@s[I"try_in_busy;F@s[I"try_initialize_cells;F@s[I"try_to_install_new_cell;F@s[[I" Volatile;To;;[ ;@Z;0@s[U:RDoc::Context::Section[i 0o;;[ ;0;0[@ZI"!Concurrent::ThreadSafe::Util;FcRDoc::NormalModule