public void Echo(string uid, string time) { Interlocked.Increment(ref _totalReceivedEcho); Clients.Client(Context.ConnectionId).SendAsync("echo", _totalReceivedEcho, time); }
public static Object LoadReferenceTypeField(IntPtr address) { return(Interlocked.CompareExchange <Object>(address, null, null)); }
/// <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); }
private void HandleVirtualMachineStart(object sender, ThreadEventArgs e) { if (e.SuspendPolicy == SuspendPolicy.All) { Interlocked.Increment(ref _suspended); } var requestManager = _virtualMachine.GetEventRequestManager(); var threadStartRequest = requestManager.CreateThreadStartRequest(); threadStartRequest.SuspendPolicy = SuspendPolicy.EventThread; threadStartRequest.IsEnabled = true; var threadDeathRequest = requestManager.CreateThreadDeathRequest(); threadDeathRequest.SuspendPolicy = SuspendPolicy.EventThread; threadDeathRequest.IsEnabled = true; var classPrepareRequest = requestManager.CreateClassPrepareRequest(); classPrepareRequest.SuspendPolicy = SuspendPolicy.EventThread; classPrepareRequest.IsEnabled = true; var exceptionRequest = requestManager.CreateExceptionRequest(null, true, true); exceptionRequest.SuspendPolicy = SuspendPolicy.All; exceptionRequest.IsEnabled = true; var virtualMachineDeathRequest = requestManager.CreateVirtualMachineDeathRequest(); virtualMachineDeathRequest.SuspendPolicy = SuspendPolicy.All; virtualMachineDeathRequest.IsEnabled = true; DebugEvent debugEvent = new DebugLoadCompleteEvent(enum_EVENTATTRIBUTES.EVENT_ASYNC_STOP); SetEventProperties(debugEvent, e, false); Callback.Event(DebugEngine, Process, this, null, debugEvent); _isLoaded = true; JavaDebugThread mainThread = null; ReadOnlyCollection <IThreadReference> threads = VirtualMachine.GetAllThreads(); for (int i = 0; i < threads.Count; i++) { bool isMainThread = threads[i].Equals(e.Thread); JavaDebugThread thread = new JavaDebugThread(this, threads[i], isMainThread ? ThreadCategory.Main : ThreadCategory.Worker); if (isMainThread) { mainThread = thread; } lock (this._threads) { this._threads.Add(threads[i].GetUniqueId(), thread); } debugEvent = new DebugThreadCreateEvent(enum_EVENTATTRIBUTES.EVENT_ASYNCHRONOUS); Callback.Event(DebugEngine, Process, this, thread, debugEvent); } if (DebugEngine.VirtualizedBreakpoints.Count > 0) { ReadOnlyCollection <IReferenceType> classes = VirtualMachine.GetAllClasses(); foreach (var type in classes) { if (!type.GetIsPrepared()) { continue; } ReadOnlyCollection <string> sourceFiles = type.GetSourcePaths(type.GetDefaultStratum()); DebugEngine.BindVirtualizedBreakpoints(this, mainThread, type, sourceFiles); } } JavaDebugThread thread2; lock (_threads) { this._threads.TryGetValue(e.Thread.GetUniqueId(), out thread2); } debugEvent = new DebugEntryPointEvent(GetAttributesForEvent(e)); SetEventProperties(debugEvent, e, false); Callback.Event(DebugEngine, Process, this, thread2, debugEvent); }
public int parseFile(ICharStream input, int thread) { Checksum checksum = new CRC32(); Debug.Assert(thread >= 0 && thread < NUMBER_OF_THREADS); try { IParseTreeListener listener = sharedListeners[thread]; if (listener == null) { listener = (IParseTreeListener)Activator.CreateInstance(listenerClass); sharedListeners[thread] = listener; } Lexer lexer = sharedLexers[thread]; if (REUSE_LEXER && lexer != null) { lexer.SetInputStream(input); } else { lexer = (Lexer)lexerCtor.Invoke(new object[] { input }); sharedLexers[thread] = lexer; if (!ENABLE_LEXER_DFA) { lexer.Interpreter = new NonCachingLexerATNSimulator(lexer, lexer.Atn); } else if (!REUSE_LEXER_DFA) { lexer.Interpreter = new LexerATNSimulator(lexer, sharedLexerATNs[thread]); } } lexer.Interpreter.optimize_tail_calls = OPTIMIZE_TAIL_CALLS; if (ENABLE_LEXER_DFA && !REUSE_LEXER_DFA) { lexer.Interpreter.atn.ClearDFA(); } CommonTokenStream tokens = new CommonTokenStream(lexer); tokens.Fill(); Interlocked.Add(ref tokenCount, tokens.Size); if (COMPUTE_CHECKSUM) { foreach (IToken token in tokens.GetTokens()) { updateChecksum(checksum, token); } } if (!RUN_PARSER) { return((int)checksum.Value); } Parser parser = sharedParsers[thread]; if (REUSE_PARSER && parser != null) { parser.SetInputStream(tokens); } else { Parser newParser = (Parser)parserCtor.Invoke(new object[] { tokens }); parser = newParser; sharedParsers[thread] = parser; } parser.RemoveErrorListeners(); if (!TWO_STAGE_PARSING) { parser.AddErrorListener(DescriptiveErrorListener.INSTANCE); parser.AddErrorListener(new SummarizingDiagnosticErrorListener()); } if (!ENABLE_PARSER_DFA) { parser.Interpreter = new NonCachingParserATNSimulator(parser, parser.Atn); } else if (!REUSE_PARSER_DFA) { parser.Interpreter = new ParserATNSimulator(parser, sharedParserATNs[thread]); } if (ENABLE_PARSER_DFA && !REUSE_PARSER_DFA) { parser.Interpreter.atn.ClearDFA(); } parser.Interpreter.PredictionMode = TWO_STAGE_PARSING ? PredictionMode.Sll : PREDICTION_MODE; parser.Interpreter.force_global_context = FORCE_GLOBAL_CONTEXT && !TWO_STAGE_PARSING; parser.Interpreter.always_try_local_context = TRY_LOCAL_CONTEXT_FIRST || TWO_STAGE_PARSING; parser.Interpreter.optimize_ll1 = OPTIMIZE_LL1; parser.Interpreter.optimize_unique_closure = OPTIMIZE_UNIQUE_CLOSURE; parser.Interpreter.optimize_hidden_conflicted_configs = OPTIMIZE_HIDDEN_CONFLICTED_CONFIGS; parser.Interpreter.optimize_tail_calls = OPTIMIZE_TAIL_CALLS; parser.Interpreter.tail_call_preserves_sll = TAIL_CALL_PRESERVES_SLL; parser.Interpreter.treat_sllk1_conflict_as_ambiguity = TREAT_SLLK1_CONFLICT_AS_AMBIGUITY; parser.BuildParseTree = BUILD_PARSE_TREES; if (!BUILD_PARSE_TREES && BLANK_LISTENER) { parser.AddParseListener(listener); } if (BAIL_ON_ERROR || TWO_STAGE_PARSING) { parser.ErrorHandler = new BailErrorStrategy(); } MethodInfo parseMethod = parserClass.GetMethod(entryPoint); object parseResult; IParseTreeListener checksumParserListener = null; try { if (COMPUTE_CHECKSUM) { checksumParserListener = new ChecksumParseTreeListener(checksum); parser.AddParseListener(checksumParserListener); } parseResult = parseMethod.Invoke(parser, null); } catch (TargetInvocationException ex) { if (!TWO_STAGE_PARSING) { throw; } string sourceName = tokens.SourceName; sourceName = !string.IsNullOrEmpty(sourceName) ? sourceName + ": " : ""; Console.Error.WriteLine(sourceName + "Forced to retry with full context."); if (!(ex.InnerException is ParseCanceledException)) { throw; } tokens.Reset(); if (REUSE_PARSER && sharedParsers[thread] != null) { parser.SetInputStream(tokens); } else { Parser newParser = (Parser)parserCtor.Invoke(new object[] { tokens }); parser = newParser; sharedParsers[thread] = parser; } parser.RemoveErrorListeners(); parser.AddErrorListener(DescriptiveErrorListener.INSTANCE); parser.AddErrorListener(new SummarizingDiagnosticErrorListener()); if (!ENABLE_PARSER_DFA) { parser.Interpreter = new NonCachingParserATNSimulator(parser, parser.Atn); } parser.Interpreter.PredictionMode = PREDICTION_MODE; parser.Interpreter.force_global_context = FORCE_GLOBAL_CONTEXT; parser.Interpreter.always_try_local_context = TRY_LOCAL_CONTEXT_FIRST; parser.Interpreter.optimize_ll1 = OPTIMIZE_LL1; parser.Interpreter.optimize_unique_closure = OPTIMIZE_UNIQUE_CLOSURE; parser.Interpreter.optimize_hidden_conflicted_configs = OPTIMIZE_HIDDEN_CONFLICTED_CONFIGS; parser.Interpreter.optimize_tail_calls = OPTIMIZE_TAIL_CALLS; parser.Interpreter.tail_call_preserves_sll = TAIL_CALL_PRESERVES_SLL; parser.Interpreter.treat_sllk1_conflict_as_ambiguity = TREAT_SLLK1_CONFLICT_AS_AMBIGUITY; parser.BuildParseTree = BUILD_PARSE_TREES; if (!BUILD_PARSE_TREES && BLANK_LISTENER) { parser.AddParseListener(listener); } if (BAIL_ON_ERROR) { parser.ErrorHandler = new BailErrorStrategy(); } parseResult = parseMethod.Invoke(parser, null); } finally { if (checksumParserListener != null) { parser.RemoveParseListener(checksumParserListener); } } Assert.IsInstanceOfType(parseResult, typeof(IParseTree)); if (BUILD_PARSE_TREES && BLANK_LISTENER) { ParseTreeWalker.Default.Walk(listener, (ParserRuleContext)parseResult); } } catch (Exception e) { if (!REPORT_SYNTAX_ERRORS && e is ParseCanceledException) { return((int)checksum.Value); } throw; } return((int)checksum.Value); }
internal TaggedObjectId TrackLocalObjectReference(jobject @object, JvmtiEnvironment environment, JniEnvironment nativeEnvironment, bool freeLocalReference) { if (@object == jobject.Null) { return(new TaggedObjectId(Tag.Object, new ObjectId(0), default(TaggedReferenceTypeId))); } long tag; JvmtiErrorHandler.ThrowOnFailure(environment.GetTag(@object, out tag)); TaggedReferenceTypeId type = default(TaggedReferenceTypeId); Tag objectKind; if (tag == 0) { long uniqueTag = Interlocked.Increment(ref _nextTag); /* first figure out what type of object we're dealing with. could be: * - String * - Thread * - ThreadGroup * - ClassLoader * - ClassObject * - Array * - Object */ // check for array jclass objectClass = nativeEnvironment.GetObjectClass(@object); try { type = TrackLocalClassReference(objectClass, environment, nativeEnvironment, false); bool isArray = type.TypeTag == TypeTag.Array; if (isArray) { objectKind = Tag.Array; } else { if (_stringClass != jclass.Null && nativeEnvironment.IsInstanceOf(@object, _stringClass)) { objectKind = Tag.String; } else if (_threadClass != jclass.Null && nativeEnvironment.IsInstanceOf(@object, _threadClass)) { objectKind = Tag.Thread; } else if (_threadGroupClass != jclass.Null && nativeEnvironment.IsInstanceOf(@object, _threadGroupClass)) { objectKind = Tag.ThreadGroup; } else if (_classClass != jclass.Null && nativeEnvironment.IsInstanceOf(@object, _classClass)) { objectKind = Tag.ClassObject; } else if (_classLoaderClass != jclass.Null && nativeEnvironment.IsInstanceOf(@object, _classLoaderClass)) { objectKind = Tag.ClassLoader; } else { objectKind = Tag.Object; } } } finally { nativeEnvironment.DeleteLocalReference(objectClass); } tag = (uniqueTag << 8) | (uint)objectKind; JvmtiErrorHandler.ThrowOnFailure(environment.SetTag(@object, tag)); lock (_objects) { _objects.Add(new ObjectId(tag), nativeEnvironment.NewWeakGlobalReference(@object)); } } else { jclass objectClass = nativeEnvironment.GetObjectClass(@object); type = TrackLocalClassReference(objectClass, environment, nativeEnvironment, true); } if (freeLocalReference) { nativeEnvironment.DeleteLocalReference(@object); } objectKind = (Tag)(tag & 0xFF); return(new TaggedObjectId(objectKind, new ObjectId(tag), type)); }
public T GetAndSet(T value) { return(Interlocked.Exchange(ref _value, value)); }
public static T Write <T>(ref T location, T value) { location = value; MemoryBarrierApi.MemoryBarrier(); return(value); }
public void Echo(string uid, string time, byte[] messageBlob) { Interlocked.Increment(ref _totalReceivedEcho); Clients.Client(Context.ConnectionId).SendAsync("echo", _totalReceivedEcho, time, Context.ConnectionId, null, messageBlob); }
public static void Write(ref long location, long value) { location = value; MemoryBarrierApi.MemoryBarrier(); }
public static void Write(ref int location, int value) { location = value; MemoryBarrierApi.MemoryBarrier(); }
public static int CreateUniqueId() => idGenerator = Interlocked.Increment(ref idGenerator);
public void SendGroup(string groupName, string message) { Interlocked.Increment(ref _totalReceivedGroup); Clients.Group(groupName).SendAsync("SendGroup", 0, message); }
public void Broadcast(string uid, string time) { Interlocked.Increment(ref _totalReceivedBroadcast); Clients.All.SendAsync("broadcast", _totalReceivedBroadcast, time); }
public Program MakeRandomProgram(int lines) { t = new Timer(3000); t.Elapsed += TimerElapsed; symbols.Clear(); GenerateSymbols(lines); var ret = new Program(); t.Start(); ret.Add(new AssemblerDirective(AssemblerDirective.Mnemonic.START) { //Value = r.Next(0, 1 << 12).ToString() Value = "0" }); for (int lineIdx = 0; lineIdx < lines; ++lineIdx) { Line line; // Make a WORD or RESW. if (r.NextDouble() < CHANCE_MEMORY) { AssemblerDirective dir; if (r.NextDouble() < CHANCE_RESW) { dir = new AssemblerDirective(AssemblerDirective.Mnemonic.WORD); } else { dir = new AssemblerDirective(AssemblerDirective.Mnemonic.RESW); } if (r.NextDouble() < CHANCE_USE_SYMBOL) { // The symbol we put here must not have been defined elsewhere. var sym = GetUndefinedSymbol(); dir.Label = sym.Name; sym.Define(); } dir.Value = GetSmallishNumber().ToString(); line = dir; } else { // Make an instruction. //Instruction.Mnemonic. Instruction instr = new Instruction(MNEMONICS[r.Next(MNEMONICS.Length)]); for (int operandIdx = 0; operandIdx < instr.Operands.Count; ++operandIdx) { var operand = instr.Operands[operandIdx]; switch (instr.Format) { case InstructionFormat.Format2: // Choose register. operand.Value = (int)REGISTERS[r.Next(REGISTERS.Length)]; break; case InstructionFormat.Format3: case InstructionFormat.Format4: case InstructionFormat.Format3Or4: // Choose whether a symbol will be referenced. if (r.NextDouble() < CHANCE_USE_SYMBOL) { operand.SymbolName = GetSymbol(); } else { // Use immediate instead of symbol. operand.Value = r.Next(-0x7ff, 0x800); } // Choose direct/indirect. if (r.NextDouble() < CHANCE_INDIRECT) { operand.AddressingMode = AddressingMode.Indirect; } // Choose immediate. if (r.NextDouble() < CHANCE_IMMEDIATE) { operand.AddressingMode |= AddressingMode.Immediate; } // Choose extended. if (r.NextDouble() < CHANCE_EXTENDED) { //operand.AddressingMode |= AddressingMode.Extended; instr.Format = InstructionFormat.Format4; } break; } } // For each operand. line = instr; } // Choose between making this line a WORD or an instruction. ret.Add(line); Interlocked.Increment(ref linesProcessed); } // For each line in output program. // Finally, append any symbols that are still undefined by this point. foreach (var s in symbols) { if (!s.IsDefined) { AssemblerDirective dir; if (r.NextDouble() < CHANCE_RESW) { dir = new AssemblerDirective(AssemblerDirective.Mnemonic.WORD); } else { dir = new AssemblerDirective(AssemblerDirective.Mnemonic.RESW); } dir.Label = s.Name; s.Define(); dir.Value = GetSmallishNumber().ToString(); ret.Add(dir); } } t.Stop(); Console.Error.WriteLine(); return(ret); }
public void Broadcast(string uid, string time, byte[] messageBlob) { Interlocked.Increment(ref _totalReceivedBroadcast); Clients.All.SendAsync("broadcast", _totalReceivedBroadcast, time, Context.ConnectionId, null, messageBlob); }
private bool TryStartCalculation() { var result = Interlocked.CompareExchange(ref _state, Calculating, Invalid); return(result == Invalid); }
public void SendGroup(string groupName, string time, byte[] messageBlob) { Interlocked.Increment(ref _totalReceivedGroup); Clients.Group(groupName).SendAsync("SendGroup", 0, time, groupName, null, messageBlob); }
public bool CompareAndSet(T expect, T update) { return(Interlocked.CompareExchange(ref _value, update, expect) == expect); }
internal static int NewId() { return(Interlocked.Increment(ref msgseq)); }
public int Step(IDebugThread2 pThread, enum_STEPKIND sk, enum_STEPUNIT Step) { JavaDebugThread thread = pThread as JavaDebugThread; if (thread == null) { return(VSConstants.E_INVALIDARG); } StepSize size; StepDepth depth; switch (Step) { case enum_STEPUNIT.STEP_INSTRUCTION: size = StepSize.Instruction; break; case enum_STEPUNIT.STEP_LINE: size = StepSize.Line; break; case enum_STEPUNIT.STEP_STATEMENT: size = VirtualMachine.GetCanStepByStatement() ? StepSize.Statement : StepSize.Line; break; default: throw new NotSupportedException(); } switch (sk) { case enum_STEPKIND.STEP_INTO: depth = StepDepth.Into; break; case enum_STEPKIND.STEP_OUT: depth = StepDepth.Out; break; case enum_STEPKIND.STEP_OVER: depth = StepDepth.Over; break; case enum_STEPKIND.STEP_BACKWARDS: default: throw new NotSupportedException(); } IStepRequest stepRequest = thread.GetStepRequest(size, depth); if (stepRequest == null) { throw new InvalidOperationException(); } Task.Factory.StartNew(() => { // make sure the global "Break All" step request is disabled this._causeBreakRequest.IsEnabled = false; stepRequest.IsEnabled = true; VirtualMachine.Resume(); Interlocked.Decrement(ref _suspended); }).HandleNonCriticalExceptions(); return(VSConstants.S_OK); }
public static void MemoryBarrier() => SystemInterlocked.MemoryBarrier();
internal new UIntPtr CompareExchangeMUW(UIntPtr newValue, UIntPtr oldValue) { return(Interlocked.CompareExchange(ref this.preHeader.muw.value, newValue, oldValue)); }
public static void MemoryBarrierProcessWide() => SystemInterlocked.MemoryBarrierProcessWide();
public static void StoreReferenceTypeField(IntPtr address, Object fieldValue) { // Doing an interlocked exchange makes sure there is a proper memory barrier Interlocked.Exchange <Object>(address, fieldValue); }
public int VisitorJoin() { return(Interlocked.Increment(ref totalVisitors)); }
/// <summary> /// If this table is not full, then just return "this". Otherwise, create and return a new table with /// additional capacity, and rehash all values in the table. /// </summary> public XHashtableState Resize() { // No need to resize if there are open entries if (numEntries < buckets.Length) { return(this); } int newSize = 0; // Determine capacity of resized hash table by first counting number of valid, non-orphaned entries // As this count proceeds, close all linked lists so that no additional entries can be added to them for (int bucketIdx = 0; bucketIdx < buckets.Length; bucketIdx++) { int entryIdx = buckets[bucketIdx]; if (entryIdx == EndOfList) { // Replace EndOfList with FullList, so that any threads still attempting to add will be forced to resize entryIdx = Interlocked.CompareExchange(ref buckets[bucketIdx], FullList, EndOfList); } // Loop until we've guaranteed that the list has been counted and closed to further adds while (entryIdx > EndOfList) { // Count each valid entry if (extractKey(entries[entryIdx].Value) != null) { newSize++; } if (entries[entryIdx].Next == EndOfList) { // Replace EndOfList with FullList, so that any threads still attempting to add will be forced to resize entryIdx = Interlocked.CompareExchange(ref entries[entryIdx].Next, FullList, EndOfList); } else { // Move to next entry in the list entryIdx = entries[entryIdx].Next; } } Debug.Assert(entryIdx == EndOfList, "Resize() should only be called by one thread"); } // Double number of valid entries; if result is less than current capacity, then use current capacity if (newSize < buckets.Length / 2) { newSize = buckets.Length; } else { newSize = buckets.Length * 2; if (newSize < 0) { throw new OverflowException(); } } // Create new hash table with additional capacity XHashtableState newHashtable = new XHashtableState(extractKey, newSize); // Rehash names (TryAdd will always succeed, since we won't fill the new table) // Do not simply walk over entries and add them to table, as that would add orphaned // entries. Instead, walk the linked lists and add each name. for (int bucketIdx = 0; bucketIdx < buckets.Length; bucketIdx++) { int entryIdx = buckets[bucketIdx]; TValue newValue; while (entryIdx > EndOfList) { newHashtable.TryAdd(entries[entryIdx].Value, out newValue); entryIdx = entries[entryIdx].Next; } Debug.Assert(entryIdx == FullList, "Linked list should have been closed when it was counted"); } return(newHashtable); }
public int VisitorLeave() { return(Interlocked.Decrement(ref totalVisitors)); }
public virtual DFAState AddState(DFAState state) { state.stateNumber = Interlocked.Increment(ref nextStateNumber) - 1; return(states.GetOrAdd(state, state)); }
public string this[ILexical element] => element == null ? string.Empty : $"{element?.GetType().Name} {elementIds.GetOrAdd(element, e => Interlocked.Increment(ref idGenerator))}";