protected override void Initialize() { base.Initialize(); // Subscribe to the solution events this.solutionListeners.Add(new SolutionListenerForProjectReferenceUpdate(this)); this.solutionListeners.Add(new SolutionListenerForProjectOpen(this)); this.solutionListeners.Add(new SolutionListenerForBuildDependencyUpdate(this)); this.solutionListeners.Add(new SolutionListenerForProjectEvents(this)); foreach (SolutionListener solutionListener in this.solutionListeners) { solutionListener.Init(); } try { // this block assumes that the ProjectPackage instances will all be initialized on the same thread, // but doesn't assume that only one ProjectPackage instance exists at a time if (Interlocked.Increment(ref _singleFileGeneratorNodeExtenderReferenceCount) == 1) { ObjectExtenders objectExtenders = (ObjectExtenders)GetService(typeof(ObjectExtenders)); _singleFileGeneratorNodeExtenderProvider = new SingleFileGeneratorNodeExtenderProvider(); string extenderCatId = typeof(FileNodeProperties).GUID.ToString("B"); string extenderName = SingleFileGeneratorNodeExtenderProvider.Name; string localizedName = extenderName; _singleFileGeneratorNodeExtenderCookie = objectExtenders.RegisterExtenderProvider(extenderCatId, extenderName, _singleFileGeneratorNodeExtenderProvider, localizedName); } } finally { _initialized = true; } }
private void HandleThreadDeath(object sender, ThreadEventArgs e) { if (e.SuspendPolicy == SuspendPolicy.All) { Interlocked.Increment(ref _suspended); } JavaDebugThread thread; lock (_threads) { this._threads.TryGetValue(e.Thread.GetUniqueId(), out thread); } //string name = thread.GetName(); DebugEvent debugEvent = new DebugThreadDestroyEvent(GetAttributesForEvent(e), 0); SetEventProperties(debugEvent, e, false); Callback.Event(DebugEngine, Process, this, thread, debugEvent); lock (_threads) { this._threads.Remove(e.Thread.GetUniqueId()); } }
/// <summary> /// Constructor /// </summary> /// <param name="minThreads">The number of threads that will be started initially.</param> /// <param name="maxThreads">The maximum number of threads that will be allowed to grow to.</param> /// <param name="poolName">The name of the thread pool.</param> /// <param name="os">Instance of the OS extraction. Used for getting the UTC date time</param> public BeeEeeThreadPool(int minThreads, int maxThreads, string poolName, Func <DateTime> utcNow) { _poolName = poolName; _threadPoolId = Interlocked.Increment(ref _nextThreadPoolId); _minThreads = minThreads; _maxThreads = maxThreads; if (null == utcNow) { _utcNow = () => DateTime.UtcNow; } else { _utcNow = utcNow; } _availableThreads = new Queue <ThreadPoolThread>(); _allThreads = new ThreadPoolThread[_maxThreads]; _workQueue = new Queue <Action>(); _lock = new object(); for (int i = 0; i < _maxThreads; i++) { var thread = BuildThread(i); if (i < _minThreads) { thread.Start(); } _availableThreads.Enqueue(thread); _allThreads[i] = thread; } _timeoutProcessingThread = new Thread(ProcessTimeouts); _timeoutProcessingThread.Name = string.Format("{0} Timeout", _poolName); _timeoutProcessingThread.Start(); }
/// <summary> /// This puts a work request on the queue to be executed. The logic then immediatly tries to assign a thread the work. /// </summary> /// <param name="work"></param> public void AssignThread(Action work) { ThreadPoolThread thread = null; Action currentWork = null; lock (_lock) { if (IsDisposed) { return; } _workQueue.Enqueue(work); Interlocked.Increment(ref _workQueueSize); if (_availableThreads.Count == 0) { return; } // okay have thread and have work thread = _availableThreads.Dequeue(); Interlocked.Increment(ref _threadsAssigned); currentWork = _workQueue.Dequeue(); // this seems strange to deque right after an enqueue but there could be work waiting on the work queue Interlocked.Decrement(ref _workQueueSize); } // we do it here -- the thread and must not be null and should not according to the above logic thread.AssignWork(currentWork); }
private void HandleClassPrepare(object sender, ClassPrepareEventArgs e) { if (e.SuspendPolicy == SuspendPolicy.All) { Interlocked.Increment(ref _suspended); } JavaDebugThread thread; lock (_threads) { this._threads.TryGetValue(e.Thread.GetUniqueId(), out thread); } try { ReadOnlyCollection <string> sourceFiles = e.Type.GetSourcePaths(e.Type.GetDefaultStratum()); DebugEngine.BindVirtualizedBreakpoints(this, thread, e.Type, sourceFiles); } catch (MissingInformationException) { // Can't bind debug information for classes that don't contain debug information } // The format of the message created by the .NET debugger is this: // 'devenv.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Microsoft.VisualStudio.Windows.Forms\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.Windows.Forms.dll' string message = string.Format("'{0}' ({1}): Loaded '{2}'\n", Process.GetName(enum_GETNAME_TYPE.GN_BASENAME), Java.Constants.JavaLanguageName, e.Type.GetName()); DebugEvent outputEvent = new DebugOutputStringEvent(message); SetEventProperties(outputEvent, e, true); Callback.Event(DebugEngine, Process, this, thread, outputEvent); ManualContinueFromEvent(e); }
private void HandleMonitorContendedWaited(object sender, MonitorWaitedEventArgs e) { if (e.SuspendPolicy == SuspendPolicy.All) { Interlocked.Increment(ref _suspended); } throw new NotImplementedException(); }
public static long Increment(ref long location) { if (CoyoteRuntime.IsExecutionControlled) { CoyoteRuntime.Current.ScheduleNextOperation(); } return(SystemInterlocked.Increment(ref location)); }
private void HandleMethodEntry(object sender, ThreadLocationEventArgs e) { if (e.SuspendPolicy == SuspendPolicy.All) { Interlocked.Increment(ref _suspended); } throw new NotImplementedException(); }
private void HandleFieldModification(object sender, FieldModificationEventArgs e) { if (e.SuspendPolicy == SuspendPolicy.All) { Interlocked.Increment(ref _suspended); } throw new NotImplementedException(); }
private void HandleClassUnload(object sender, ClassUnloadEventArgs e) { if (e.SuspendPolicy == SuspendPolicy.All) { Interlocked.Increment(ref _suspended); } throw new NotImplementedException(); }
private readonly object lock_attemptTolock = new object(); //this will make sure that _counter won't be accessed till _catchOnHandle() finishes protected virtual void OnReadyForModifications() { if (IgnoreOnReadyForModifications) { return; } /*_pool.WaitOne();*/ lock (lock_attemptTolock) { //Set custom properties first, before design! var _i = Interlocked.Increment(ref _onready_invokeCounts); if (_i == 1) { SuspendLayout(); var dic = Columns.Cast <Column>().Combine(_customizeColumns, (key, val) => key.Name == val.Key); foreach (var kvp in dic) { kvp.Value.Value.ApplyProperties(kvp.Key); } ResumeLayout(); } //Call event, also invoked PreDisplay() (design core). if (ReadyForModifications != null) { ReadyForModifications.Invoke(this, _i); //add then return } #region AutoDesigners if (_i == 1) { SuspendLayout(); foreach (var _cName in _customNames) { foreach (Column column in Columns) { if (_cName.Key != column.Name) { continue; } column.HeaderText = _cName.Value; } } ResumeLayout(); } if (FillColumnsToFitControl && Adapter == null && MathTools.PrecentageDifferences(Width, GetDisplayedColumns().Sum(dis => dis.Width + dis.DividerWidth / 2d), Width / 80d) == false) { AutoSizeColumns(); } //_pool.Release(1); } }
private void HandleException(object sender, ExceptionEventArgs e) { if (e.SuspendPolicy == SuspendPolicy.All) { Interlocked.Increment(ref _suspended); } JavaDebugThread thread; lock (_threads) { this._threads.TryGetValue(e.Thread.GetUniqueId(), out thread); } bool stop; bool firstChance = e.CatchLocation != null; EXCEPTION_INFO exceptionInfo; if (DebugEngine.TryGetException(e.Exception.GetReferenceType().GetName(), out exceptionInfo)) { if (firstChance && (exceptionInfo.dwState & enum_EXCEPTION_STATE.EXCEPTION_STOP_FIRST_CHANCE) != 0) { stop = true; } else if (!firstChance && (exceptionInfo.dwState & enum_EXCEPTION_STATE.EXCEPTION_STOP_SECOND_CHANCE) != 0) { stop = true; } else { stop = !firstChance; } } else { stop = !firstChance; } JavaDebugExceptionEvent exceptionEvent = new JavaDebugExceptionEvent(GetAttributesForEvent(e), this, e.Thread, e.Exception, e.Location, e.CatchLocation); if (stop) { SetEventProperties(exceptionEvent, e, false); Callback.Event(DebugEngine, Process, this, thread, exceptionEvent); } else { string message = exceptionEvent.GetDescription() + Environment.NewLine; DebugEvent debugEvent = new DebugOutputStringEvent(message); SetEventProperties(debugEvent, e, true); Callback.Event(DebugEngine, Process, this, thread, debugEvent); ManualContinueFromEvent(e); } }
private void HandleVirtualMachineDeath(object sender, VirtualMachineEventArgs e) { if (e.SuspendPolicy == SuspendPolicy.All) { Interlocked.Increment(ref _suspended); } DebugEvent debugEvent = new DebugProgramDestroyEvent(GetAttributesForEvent(e), 0); SetEventProperties(debugEvent, e, false); Callback.Event(DebugEngine, Process, this, null, debugEvent); }
public NameInfo(string name, EventTags tags, int typeMetadataSize) { this.name = name; this.tags = tags & Statics.EventTagsMask; this.identity = Interlocked.Increment(ref lastIdentity); int tagsPos = 0; Statics.EncodeTags((int)this.tags, ref tagsPos, null); this.nameMetadata = Statics.MetadataForString(name, tagsPos, 0, typeMetadataSize); tagsPos = 2; Statics.EncodeTags((int)this.tags, ref tagsPos, this.nameMetadata); }
/// <summary> /// Attempts to return an object from the beginning of the <see cref="ConcurrentQueue{T}"/> /// without removing it. /// </summary> /// <param name="result">When this method returns, <paramref name="result"/> contains an object from /// the beginning of the <see cref="T:System.Collections.Concurrent.ConcurrentQueue{T}"/> or an /// unspecified value if the operation failed.</param> /// <returns>true if and object was returned successfully; otherwise, false.</returns> public bool TryPeek(out T result) { Interlocked.Increment(ref _numSnapshotTakers); while (!IsEmpty) { Segment head = _head; if (head.TryPeek(out result)) { Interlocked.Decrement(ref _numSnapshotTakers); return(true); } //since method IsEmpty spins, we don't need to spin in the while loop } result = default(T); Interlocked.Decrement(ref _numSnapshotTakers); return(false); }
/// <summary> /// Try to append an element at the end of this segment. /// </summary> /// <param name="value">the element to append</param> /// <param name="tail">The tail.</param> /// <returns>true if the element is appended, false if the current segment is full</returns> /// <remarks>if appending the specified element succeeds, and after which the segment is full, /// then grow the segment</remarks> internal bool TryAppend(T value) { //quickly check if _high is already over the boundary, if so, bail out if (_high >= SEGMENT_SIZE - 1) { return(false); } //Now we will use a CAS to increment _high, and store the result in newhigh. //Depending on how many free spots left in this segment and how many threads are doing this Increment //at this time, the returning "newhigh" can be // 1) < SEGMENT_SIZE - 1 : we took a spot in this segment, and not the last one, just insert the value // 2) == SEGMENT_SIZE - 1 : we took the last spot, insert the value AND grow the segment // 3) > SEGMENT_SIZE - 1 : we failed to reserve a spot in this segment, we return false to // Queue.Enqueue method, telling it to try again in the next segment. int newhigh = SEGMENT_SIZE; //initial value set to be over the boundary //We need do Interlocked.Increment and value/state update in a finally block to ensure that they run //without interuption. This is to prevent anything from happening between them, and another dequeue //thread maybe spinning forever to wait for _state[] to be true; try { } finally { newhigh = Interlocked.Increment(ref _high); if (newhigh <= SEGMENT_SIZE - 1) { _array[newhigh] = value; _state[newhigh]._value = true; } //if this thread takes up the last slot in the segment, then this thread is responsible //to grow a new segment. Calling Grow must be in the finally block too for reliability reason: //if thread abort during Grow, other threads will be left busy spinning forever. if (newhigh == SEGMENT_SIZE - 1) { Grow(); } } //if newhigh <= SEGMENT_SIZE-1, it means the current thread successfully takes up a spot return(newhigh <= SEGMENT_SIZE - 1); }
private void HandleSingleStep(object sender, ThreadLocationEventArgs e) { if (e.SuspendPolicy == SuspendPolicy.All) { Interlocked.Increment(ref _suspended); } IStepRequest request = e.Request as IStepRequest; if (request == null) { throw new ArgumentException(); } JavaDebugThread thread; lock (_threads) { this._threads.TryGetValue(e.Thread.GetUniqueId(), out thread); } if (e.Request == _causeBreakRequest) { _causeBreakRequest.IsEnabled = false; DebugEvent debugEvent = new DebugBreakEvent(GetAttributesForEvent(e)); SetEventProperties(debugEvent, e, false); Callback.Event(DebugEngine, Process, this, thread, debugEvent); return; } else if (thread != null) { bool wasThreadStepRequest = thread.StepRequests.Contains(request); if (wasThreadStepRequest) { e.Request.IsEnabled = false; DebugEvent debugEvent = new DebugStepCompleteEvent(GetAttributesForEvent(e)); SetEventProperties(debugEvent, e, false); Callback.Event(DebugEngine, Process, this, thread, debugEvent); return; } } }
private void HandleBreakpoint(object sender, ThreadLocationEventArgs e) { if (e.SuspendPolicy == SuspendPolicy.All) { Interlocked.Increment(ref _suspended); } List <IDebugBoundBreakpoint2> breakpoints = new List <IDebugBoundBreakpoint2>(); foreach (var pending in DebugEngine.PendingBreakpoints) { if (pending.GetState() != enum_PENDING_BP_STATE.PBPS_ENABLED) { continue; } foreach (var breakpoint in pending.EnumBoundBreakpoints().OfType <JavaDebugBoundBreakpoint>()) { if (breakpoint.EventRequest.Equals(e.Request) && breakpoint.GetState() == enum_BP_STATE.BPS_ENABLED) { breakpoints.Add(breakpoint); } } } if (breakpoints.Count == 0) { ManualContinueFromEvent(e); return; } JavaDebugThread thread; lock (_threads) { this._threads.TryGetValue(e.Thread.GetUniqueId(), out thread); } DebugEvent debugEvent = new DebugBreakpointEvent(GetAttributesForEvent(e), new EnumDebugBoundBreakpoints(breakpoints)); SetEventProperties(debugEvent, e, false); Callback.Event(DebugEngine, Process, this, thread, debugEvent); }
public override AbstractEdgeMap <T> Put(int key, T value) { if (key >= minIndex && key <= maxIndex) { T existing = Interlocked.Exchange(ref arrayData[key - minIndex], value); if (existing == null && value != null) { Interlocked.Increment(ref size); } else { if (existing != null && value == null) { Interlocked.Decrement(ref size); } } } return(this); }
private void HandleThreadStart(object sender, ThreadEventArgs e) { if (e.SuspendPolicy == SuspendPolicy.All) { Interlocked.Increment(ref _suspended); } // nothing to do if this thread is already started JavaDebugThread thread; if (_threads.TryGetValue(e.Thread.GetUniqueId(), out thread)) { switch (e.SuspendPolicy) { case SuspendPolicy.All: Continue(thread); break; case SuspendPolicy.EventThread: Task.Factory.StartNew(e.Thread.Resume).HandleNonCriticalExceptions(); break; case SuspendPolicy.None: break; } return; } thread = new JavaDebugThread(this, e.Thread, ThreadCategory.Worker); lock (this._threads) { this._threads.Add(e.Thread.GetUniqueId(), thread); } DebugEvent debugEvent = new DebugThreadCreateEvent(GetAttributesForEvent(e)); SetEventProperties(debugEvent, e, true); Callback.Event(DebugEngine, Process, this, thread, debugEvent); ManualContinueFromEvent(e); }
private async Task StartConnect(HubConnection connection) { if (connection == null) { return; } try { Interlocked.Increment(ref cnt); await connection.StartAsync(); Interlocked.Decrement(ref cnt); } catch (Exception ex) { Util.Log($"start connection exception: {ex}"); Environment.Exit(1); //debug _tk.Counters.IncreaseConnectionError(); } }
/// <summary> /// Checks for a data race. /// </summary> internal void CheckDataRace(bool isWriteAccess) { var runtime = CoyoteRuntime.Current; if (isWriteAccess) { runtime.Assert(this.WriterCount is 0, $"Found write/write data race on '{typeof(SystemGenerics.List<T>)}'."); runtime.Assert(this.ReaderCount is 0, $"Found read/write data race on '{typeof(SystemGenerics.List<T>)}'."); SystemInterlocked.Increment(ref this.WriterCount); if (runtime.SchedulingPolicy is SchedulingPolicy.Systematic) { runtime.ScheduleNextOperation(AsyncOperationType.Default); } else if (runtime.SchedulingPolicy is SchedulingPolicy.Fuzzing) { runtime.DelayOperation(); } SystemInterlocked.Decrement(ref this.WriterCount); } else { runtime.Assert(this.WriterCount is 0, $"Found read/write data race on '{typeof(SystemGenerics.List<T>)}'."); SystemInterlocked.Increment(ref this.ReaderCount); if (runtime.SchedulingPolicy is SchedulingPolicy.Systematic) { runtime.ScheduleNextOperation(AsyncOperationType.Default); } else if (runtime.SchedulingPolicy is SchedulingPolicy.Fuzzing) { runtime.DelayOperation(); } SystemInterlocked.Decrement(ref this.ReaderCount); } }
/** * Handles a new client connecting to the server and starts reading from the client if the client limit has not been reached. * * @param client * The new client. */ private void Heard(TcpClient client) { Connection connection = new Connection { Client = client, }; if (clients >= capacity && capacity != 0) { throw new Exceptions.ServerFullException("Server full, rejecting client with IP '" + connection.Address + "'.", connection); } Interlocked.Increment(ref clients); Limits.IpTable.Add(connection); if (timeout != 0) { connection.Timer.Interval = timeout; connection.Timer.Elapsed += OnTimeout; connection.Timer.Start(); } OnConnect(connection); BeginRead(connection); }
#pragma warning disable 0420 // No warning for Interlocked.xxx if compiled with new managed compiler (Roslyn) /// <summary> /// Copies the <see cref="ConcurrentQueue{T}"/> elements to a new <see /// cref="T:System.Collections.Generic.List{T}"/>. /// </summary> /// <returns>A new <see cref="T:System.Collections.Generic.List{T}"/> containing a snapshot of /// elements copied from the <see cref="ConcurrentQueue{T}"/>.</returns> private List <T> ToList() { // Increments the number of active snapshot takers. This increment must happen before the snapshot is // taken. At the same time, Decrement must happen after list copying is over. Only in this way, can it // eliminate race condition when Segment.TryRemove() checks whether _numSnapshotTakers == 0. Interlocked.Increment(ref _numSnapshotTakers); List <T> list = new List <T>(); try { //store head and tail positions in buffer, Segment head, tail; int headLow, tailHigh; GetHeadTailPositions(out head, out tail, out headLow, out tailHigh); if (head == tail) { head.AddToList(list, headLow, tailHigh); } else { head.AddToList(list, headLow, SEGMENT_SIZE - 1); Segment curr = head.Next; while (curr != tail) { curr.AddToList(list, 0, SEGMENT_SIZE - 1); curr = curr.Next; } //Add tail segment tail.AddToList(list, 0, tailHigh); } } finally { // This Decrement must happen after copying is over. Interlocked.Decrement(ref _numSnapshotTakers); } return(list); }
public virtual uint Add(HierarchyNode node) { if (node == null) { throw new ArgumentNullException("node"); } _syncObject.EnterWriteLock(); try { uint itemId = (uint)Interlocked.Increment(ref _nextNode); _itemIds.Add(node, itemId); _nodes.Add(itemId, node); // always add the node as non-cacheable since the canonical name may not be initialized when this method is called. _nonCacheableCanonicalNameNodes.Add(node); return(itemId); } finally { _syncObject.ExitWriteLock(); } }
static void Main(string[] args) { //NN_Test(); //Console.ReadKey(false); MalockClient malock = Malock.GetClient("test013", "127.0.0.1:6800", "127.0.0.1:6801").Run(); malock.Ready += delegate { Monitor m = Monitor.New("OMFG", malock); int num = 0; for (int i = 0; i < 5; i++) { EventWaitHandle.Run(() => { for (int k = 0; k < 10; k++) { try { Stopwatch sw = new Stopwatch(); sw.Start(); if (m.TryEnter()) { sw.Stop(); Console.WriteLine("n: {0}, time: {1}ms", Interlocked.Increment(ref num), sw.ElapsedMilliseconds); m.Exit(); } } catch (Exception e) { Console.WriteLine(e.Message); } } }); } }; Console.ReadKey(false); }
public jvmtiError TagClassLoader(jobject classLoaderHandle, out long tag) { if (classLoaderHandle == jobject.Null) { tag = 0; return(jvmtiError.None); } var error = GetTag(classLoaderHandle, out tag); if (error != jvmtiError.None) { return(error); } if (tag != 0) { return(jvmtiError.None); } tag = Interlocked.Increment(ref _nextClassLoaderTag); error = SetTag(classLoaderHandle, tag); return(error); }
/// <summary> /// Returns an enumerator that iterates through the <see /// cref="ConcurrentQueue{T}"/>. /// </summary> /// <returns>An enumerator for the contents of the <see /// cref="ConcurrentQueue{T}"/>.</returns> /// <remarks> /// The enumeration represents a moment-in-time snapshot of the contents /// of the queue. It does not reflect any updates to the collection after /// <see cref="GetEnumerator"/> was called. The enumerator is safe to use /// concurrently with reads from and writes to the queue. /// </remarks> public IEnumerator <T> GetEnumerator() { // Increments the number of active snapshot takers. This increment must happen before the snapshot is // taken. At the same time, Decrement must happen after the enumeration is over. Only in this way, can it // eliminate race condition when Segment.TryRemove() checks whether _numSnapshotTakers == 0. Interlocked.Increment(ref _numSnapshotTakers); // Takes a snapshot of the queue. // A design flaw here: if a Thread.Abort() happens, we cannot decrement _numSnapshotTakers. But we cannot // wrap the following with a try/finally block, otherwise the decrement will happen before the yield return // statements in the GetEnumerator (head, tail, headLow, tailHigh) method. Segment head, tail; int headLow, tailHigh; GetHeadTailPositions(out head, out tail, out headLow, out tailHigh); //If we put yield-return here, the iterator will be lazily evaluated. As a result a snapshot of // the queue is not taken when GetEnumerator is initialized but when MoveNext() is first called. // This is inconsistent with existing generic collections. In order to prevent it, we capture the // value of _head in a buffer and call out to a helper method. //The old way of doing this was to return the ToList().GetEnumerator(), but ToList() was an // unnecessary performance hit. return(GetEnumerator(head, tail, headLow, tailHigh)); }
public DisableRefreshHandle(SccProviderService service) { _service = service; Interlocked.Increment(ref _service._disableRefresh); }
/// <summary> /// Attempt to add "value" to the table, hashed by an embedded string key. If a value having the same key already exists, /// then return the existing value in "newValue". Otherwise, return the newly added value in "newValue". /// /// If the hash table is full, return false. Otherwise, return true. /// </summary> public bool TryAdd(TValue value, out TValue newValue) { int newEntry, entryIndex; string key; int hashCode; // Assume "value" will be added and returned as "newValue" newValue = value; // Extract the key from the value. If it's null, then value is invalid and does not need to be added to table. key = extractKey(value); if (key == null) { return(true); } // Compute hash code over entire length of key hashCode = ComputeHashCode(key, 0, key.Length); // Assume value is not yet in the hash table, and prepare to add it (if table is full, return false). // Use the entry index returned from Increment, which will never be zero, as zero conflicts with EndOfList. // Although this means that the first entry will never be used, it avoids the need to initialize all // starting buckets to the EndOfList value. newEntry = Interlocked.Increment(ref numEntries); if (newEntry < 0 || newEntry >= buckets.Length) { return(false); } entries[newEntry].Value = value; entries[newEntry].HashCode = hashCode; // Ensure that all writes to the entry can't be reordered past this barrier (or other threads might see new entry // in list before entry has been initialized!). #if !SILVERLIGHT Thread.MemoryBarrier(); #else // SILVERLIGHT // According to this document "http://my/sites/juddhall/ThreadingFeatureCrew/Shared Documents/System.Threading - FX Audit Proposal.docx" // The MemoryBarrier method usage is busted (mostly - don't know about ours) and should be removed. // Replacing with Interlocked.CompareExchange for now (with no effect) // which will do a very similar thing to MemoryBarrier (it's just slower) System.Threading.Interlocked.CompareExchange <Entry[]>(ref entries, null, null); #endif // SILVERLIGHT // Loop until a matching entry is found, a new entry is added, or linked list is found to be full entryIndex = 0; while (!FindEntry(hashCode, key, 0, key.Length, ref entryIndex)) { // PUBLISH (buckets slot) // No matching entry found, so add the new entry to the end of the list ("entryIndex" is index of last entry) if (entryIndex == 0) { entryIndex = Interlocked.CompareExchange(ref buckets[hashCode & (buckets.Length - 1)], newEntry, EndOfList); } else { entryIndex = Interlocked.CompareExchange(ref entries[entryIndex].Next, newEntry, EndOfList); } // Return true only if the CompareExchange succeeded (happens when replaced value is EndOfList). // Return false if the linked list turned out to be full because another thread is currently resizing // the hash table. In this case, entries[newEntry] is orphaned (not part of any linked list) and the // Add needs to be performed on the new hash table. Otherwise, keep looping, looking for new end of list. if (entryIndex <= EndOfList) { return(entryIndex == EndOfList); } } // Another thread already added the value while this thread was trying to add, so return that instance instead. // Note that entries[newEntry] will be orphaned (not part of any linked list) in this case newValue = entries[entryIndex].Value; return(true); }