internal void SwitchProcess(PythonProcess process, bool verbose)
        {
            var newEvaluator = _evaluators[process.Id];

            if (newEvaluator != _activeEvaluator)
            {
                _activeEvaluator = newEvaluator;
                ActiveProcessChanged();
                if (verbose)
                {
                    CurrentWindow.WriteLine(Strings.DebugReplSwitchProcessOutput.FormatUI(process.Id));
                }
            }
        }
        internal void SwitchProcess(PythonProcess process, bool verbose)
        {
            var newEvaluator = _evaluators[process.Id];

            if (newEvaluator != _activeEvaluator)
            {
                _activeEvaluator = newEvaluator;
                ActiveProcessChanged();
                if (verbose)
                {
                    _window.WriteLine(String.Format("Current process changed to {0}", process.Id));
                }
            }
        }
        internal void SwitchProcess(PythonProcess process, bool verbose)
        {
            var newEvaluator = _evaluators[process.Id];

            if (newEvaluator != _activeEvaluator)
            {
                _activeEvaluator = newEvaluator;
                ActiveProcessChanged();
                if (verbose)
                {
                    CurrentWindow.WriteLine(Strings.DebugReplSwitchProcessOutput.FormatUI(process.Id));
                }
            }
            else if (CustomDebugAdapterProtocolExtension.CanUseExperimental())
            {
                NotSupported();
            }
        }
        internal void DetachProcess(PythonProcess process)
        {
            int id = process.Id;
            PythonDebugProcessReplEvaluator evaluator;

            if (_evaluators.TryGetValue(id, out evaluator))
            {
                evaluator.AvailableScopesChanged      -= new EventHandler <EventArgs>(evaluator_AvailableScopesChanged);
                evaluator.MultipleScopeSupportChanged -= new EventHandler <EventArgs>(evaluator_MultipleScopeSupportChanged);
                process.DisconnectRepl();
                _evaluators.Remove(id);
                if (_activeEvaluator == evaluator)
                {
                    _activeEvaluator = null;
                }

                ActiveProcessChanged();
            }
        }
        internal void AttachProcess(PythonProcess process, IThreadIdMapper threadIdMapper)
        {
            if (_evaluators.ContainsKey(process.Id))
            {
                // Process is already attached, so just switch to it if needed
                SwitchProcess(process, false);
                return;
            }

            process.ProcessExited += new EventHandler <ProcessExitedEventArgs>(OnProcessExited);
            var evaluator = new PythonDebugProcessReplEvaluator(_serviceProvider, process, _pyService, threadIdMapper);

            evaluator.Window = _window;
            evaluator.AvailableScopesChanged      += new EventHandler <EventArgs>(evaluator_AvailableScopesChanged);
            evaluator.MultipleScopeSupportChanged += new EventHandler <EventArgs>(evaluator_MultipleScopeSupportChanged);
            _evaluators.Add(process.Id, evaluator);

            _activeEvaluator = evaluator;
        }
        internal async Task DetachProcessAsync(PythonProcess process)
        {
            _serviceProvider.GetUIThread().MustBeCalledFromUIThread();

            int id = process.Id;
            PythonDebugProcessReplEvaluator evaluator;

            if (_evaluators.TryGetValue(id, out evaluator))
            {
                evaluator.AvailableScopesChanged      -= new EventHandler <EventArgs>(evaluator_AvailableScopesChanged);
                evaluator.MultipleScopeSupportChanged -= new EventHandler <EventArgs>(evaluator_MultipleScopeSupportChanged);
                _evaluators.Remove(id);
                if (_activeEvaluator == evaluator)
                {
                    _activeEvaluator = null;
                }

                ActiveProcessChanged();
            }
        }
Beispiel #7
0
        internal async Task AttachProcessAsync(PythonProcess process, IThreadIdMapper threadIdMapper)
        {
            _serviceProvider.GetUIThread().MustBeCalledFromUIThread();

            if (_evaluators.ContainsKey(process.Id))
            {
                // Process is already attached, so just switch to it if needed
                SwitchProcess(process, false);
                return;
            }

            process.ProcessExited += new EventHandler <ProcessExitedEventArgs>(OnProcessExited);
            var evaluator = new PythonDebugProcessReplEvaluator(_serviceProvider, process, threadIdMapper);

            evaluator.CurrentWindow = CurrentWindow;
            await evaluator.InitializeAsync();

            evaluator.AvailableScopesChanged      += new EventHandler <EventArgs>(evaluator_AvailableScopesChanged);
            evaluator.MultipleScopeSupportChanged += new EventHandler <EventArgs>(evaluator_MultipleScopeSupportChanged);
            _evaluators.Add(process.Id, evaluator);

            _activeEvaluator = evaluator;
        }
        internal async Task AttachProcessAsync(PythonProcess process, IThreadIdMapper threadIdMapper)
        {
            // The fact that this is only called from UI thread is no guarantee
            // that there won't be more than one "instance" of this method in
            // progress at any time (though only one is executing while others are paused).

            // It's possible because this is an async method with await(s), and
            // UI thread execution will temporarily continue somewhere else when
            // await is used, and that somewhere else can be code that calls
            // into this method with the same process id!

            // The more relevant trigger for this cooperative multitasking is
            // the await on evaluator.InitializeAsync, and when that happens
            // the evaluator is not in the _evaluators dictionary yet.

            // If a second caller comes in (on the same UI thread) during that
            // await, it gets past the first check because it's not in _evaluators,
            // and then checks the _attachingTasks dictionary and know to wait
            // for that instead of creating a new evaluator.

            // Note that adding the uninitialized evaluator to the _evaluators
            // dictionary would be a potentially bug prone solution, as other
            // code may try to use it before it's fully initialized.
            _serviceProvider.GetUIThread().MustBeCalledFromUIThread();

            if (_evaluators.ContainsKey(process.Id))
            {
                // Process is already attached, so just switch to it if needed
                SwitchProcess(process, false);
                return;
            }

            // Keep track of evaluators that are in progress of attaching, and if
            // we are getting called to attach for one that is already in progress,
            // just wait for it to finish before returning.
            // Important: dictionary must be checked (and updated) before any
            // await call to avoid race condition.
            Task attachingTask;
            TaskCompletionSource <object> attachingTcs = null;

            if (_attachingTasks.TryGetValue(process.Id, out attachingTask))
            {
                await attachingTask;
                return;
            }
            else
            {
                attachingTcs = new TaskCompletionSource <object>();
                _attachingTasks.Add(process.Id, attachingTcs.Task);
            }

            process.ProcessExited += new EventHandler <ProcessExitedEventArgs>(OnProcessExited);
            var evaluator = new PythonDebugProcessReplEvaluator(_serviceProvider, process, threadIdMapper)
            {
                CurrentWindow = CurrentWindow
            };

            evaluator.AvailableScopesChanged      += new EventHandler <EventArgs>(evaluator_AvailableScopesChanged);
            evaluator.MultipleScopeSupportChanged += new EventHandler <EventArgs>(evaluator_MultipleScopeSupportChanged);
            await evaluator.InitializeAsync();

            _evaluators.Add(process.Id, evaluator);

            _activeEvaluator = evaluator;

            // Only refresh available scopes after the active evaluator has
            // been changed, because that's where the UI will look.
            await evaluator.RefreshAvailableScopes();

            attachingTcs.SetResult(null);
            _attachingTasks.Remove(process.Id);
        }
        internal void DetachProcess(PythonProcess process) {
            int id = process.Id;
            PythonDebugProcessReplEvaluator evaluator;
            if (_evaluators.TryGetValue(id, out evaluator)) {
                evaluator.AvailableScopesChanged -= new EventHandler<EventArgs>(evaluator_AvailableScopesChanged);
                evaluator.MultipleScopeSupportChanged -= new EventHandler<EventArgs>(evaluator_MultipleScopeSupportChanged);
                process.DisconnectRepl();
                _evaluators.Remove(id);
                if (_activeEvaluator == evaluator) {
                    _activeEvaluator = null;
                }

                ActiveProcessChanged();
            }
        }
        internal void AttachProcess(PythonProcess process, IThreadIdMapper threadIdMapper) {
            if (_evaluators.ContainsKey(process.Id)) {
                // Process is already attached, so just switch to it if needed
                SwitchProcess(process, false);
                return;
            }

            process.ProcessExited += new EventHandler<ProcessExitedEventArgs>(OnProcessExited);
            var evaluator = new PythonDebugProcessReplEvaluator(_serviceProvider, process, _pyService, threadIdMapper);
            evaluator.Window = _window;
            evaluator.InitializeAsync().WaitAndUnwrapExceptions();
            evaluator.AvailableScopesChanged += new EventHandler<EventArgs>(evaluator_AvailableScopesChanged);
            evaluator.MultipleScopeSupportChanged += new EventHandler<EventArgs>(evaluator_MultipleScopeSupportChanged);
            _evaluators.Add(process.Id, evaluator);

            _activeEvaluator = evaluator;
        }
 internal void SwitchProcess(PythonProcess process, bool verbose) {
     var newEvaluator = _evaluators[process.Id];
     if (newEvaluator != _activeEvaluator) {
         _activeEvaluator = newEvaluator;
         ActiveProcessChanged();
         if (verbose) {
             _window.WriteLine(String.Format("Current process changed to {0}", process.Id));
         }
     }
 }