% PoolFactory - This class is only used on Workers and provides helpers relating to setting up parallel pool.

% Copyright 2011-2019 The MathWorks, Inc.

classdef ( Hidden, Sealed ) PoolFactory
    methods ( Hidden, Static )
        function [isPoolTask, poolOrSessionObj] = instantiate( isInteractive, ...
            labIdx, numberOfLabs, broadcastFunctor, args )
        % We need to decide what sort of parallel pool job we are. There are
        % interactive and batch pool jobs. If we are interactive then all
        % workers will be connecting back to the client - whose socket address will be
        % provided in the input args to the task. If we are batch then lab 1 needs
        % to become the client and all the rest need to communicate back to them

            if isInteractive
                interactiveWorker = parallel.internal.pool.InteractiveWorker( labIdx, numberOfLabs, broadcastFunctor );
                interactiveWorker.start(args{:});
                parallel.internal.pool.workerSession(interactiveWorker);
                poolOrSessionObj = interactiveWorker;
                isPoolTask = true;
            else
                % Starting the parallel pool client and labs
                leadingTaskNum = 1;
                if labIdx == 1
                    % Only if we have more than 1 worker in the CommunicatingJob (pool type)
                    % do we need to set up a pool object.
                    if numberOfLabs > 1
                        poolOrSessionObj = parallel.internal.pool.AbstractClusterPool.hBuildBatchMode(leadingTaskNum);
                    else
                        poolClient = parallel.internal.pool.PoolClient();
                        poolClient.start(leadingTaskNum);
                        % Only 1 worker. This situation is just like
                        % desktop MATLAB with no pool open, therefore we do
                        % not need to store any object in workerSession
                        % and we should return an empty pool
                        poolOrSessionObj = parallel.Pool.empty();
                    end
                    isPoolTask = false;
                else
                    poolWorker = parallel.internal.pool.PoolWorker();
                    poolWorker.start(leadingTaskNum);
                    parallel.internal.pool.workerSession(poolWorker);
                    poolOrSessionObj = poolWorker;
                    isPoolTask = true;
                end
            end
        end
    end
end
