function delete( poolOrPools, varargin )
%DELETE Deletes the parallel pool of workers
%   DELETE(POOL) deletes the parallel pool object and all associated
%   resources. It stops the worker pool, destroys the communicating job. If
%   parallel preferences you have disabled auto-creation of parallel pools
%   then all parallel language features revert to using the MATLAB client
%   to compute their results. When the pool is deleted, references to it
%   become invalid. Invalid objects should be removed from the workspace
%   with the CLEAR command. If multiple references to an object exist in
%   the workspace, deleting one reference to that object invalidates the
%   remaining references to it. These remaining references should be
%   cleared from the workspace with the CLEAR command.
%
%   Examples:
%   % Delete the parallel pool, myPool.
%   delete(myPool);
%
%   % Delete the current parallel pool. If no pool is running, gcp starts
%   % one, which is immediately deleted.
%   delete(gcp)
%
%   % Delete the current parallel pool if there is one, without creating one.
%   delete(gcp('nocreate'))
%
%   See also parpool, gcp, parallel.Cluster/parpool

%   Copyright 2013-2021 The MathWorks, Inc.

narginchk(1, 2);

overrideExitArgs = {};
deleteHandle = true;
if nargin == 2
    switch varargin{1}
        case 'exitLeaveGuiOpen'
            overrideExitArgs = {'leaveguiopen'};
        case 'leaveHandleValid'
            deleteHandle = false;
        otherwise
            error(message('parallel:lang:pool:InvalidDeleteSyntax'));
    end
end


numberOfPools = numel(poolOrPools);
dctSchedulerMessage(5, 'In parallel.Pool.delete() with %d pool(s).', numberOfPools);
parallel.internal.logging.logStack(5, 'parallel.Pool.delete()');
for ii = 1:numberOfPools
    aPool = poolOrPools(ii);
    if isvalid(aPool)
        if ~aPool.IsDeleteAllowed
            break;
        end
        aPool.IsDeleteAllowed = false;
        cleanupObj = onCleanup(@() iAllowDeletion(aPool));
        client = aPool.Client;
        if isempty(overrideExitArgs) && isa(client, 'parallel.internal.pool.AbstractInteractiveClient')
            exitArgs = {};
        else
            exitArgs = overrideExitArgs;
        end
        try
            aPool.Listeners = [];
            aPool.Client.stopLabsAndDisconnect(exitArgs{:});
            parallel.internal.pool.PoolArrayManager.remove(aPool);
            if deleteHandle
                delete@handle(aPool);
            end
        catch err
            throw(err);
        end
        % Need to explicitly do cleanup here to account for the situation
        % where we are deleting an array of (different) pools and leaving
        % the handle Valid. In this situation the delete method on this
        % pool has been successful and we need to run the onCleanup for it
        % before proceeding to the next one.
        delete(cleanupObj);
    end
end
end

function iAllowDeletion(aPool)
if isvalid(aPool)
    aPool.IsDeleteAllowed = true;
end
end
