/* * Internal worker called by all the public APIs */ internal Match Run(bool quick, int prevlen, string input, int beginning, int length, int startat) { Match match; RegexRunner runner = null; if (startat < 0 || startat > input.Length) { throw new ArgumentOutOfRangeException(nameof(startat), ""); } if (length < 0 || length > input.Length) { throw new ArgumentOutOfRangeException(nameof(length), ""); } // There may be a cached runner; grab ownership of it if we can. runner = (RegexRunner)_runnerref.Get(); // Create a RegexRunner instance if we need to if (runner == null) { if (factory != null) { runner = factory.CreateInstance(); } else { runner = new RegexInterpreter(_code, UseOptionInvariant() ? CultureInfo.InvariantCulture : CultureInfo.CurrentCulture); } } try { // Do the scan starting at the requested position match = runner.Scan(this, input, beginning, beginning + length, startat, prevlen, quick, internalMatchTimeout); } finally { // Release or fill the cache slot _runnerref.Release(runner); } #if DEBUG if (Debug && match != null) { match.Dump(); } #endif return(match); }
/* * Release an object back to the cache * * If the object is the one that's under lock, the lock * is released. * * If there is no cached object, then the lock is obtained * and the object is placed in the cache. * */ internal void Release(object obj) { if (obj == null) { throw new ArgumentNullException(nameof(obj)); } // if this reference owns the lock, release it if (_obj == obj) { _obj = null; _locked = 0; return; } // if no reference owns the lock, try to cache this reference if (_obj == null) { // try to obtain the lock if (0 == Interlocked.Exchange(ref _locked, 1)) { // if there's really no reference, cache this reference if (_ref == null) { _ref = (RegexRunner)obj; } // release the lock _locked = 0; return; } } }