classdef TicBytesResult
%

% Copyright 2016-2020 The MathWorks, Inc.

    % Hide the internal properties of this object
    properties (SetAccess  = immutable, GetAccess = private)
        PoolID
        Values
    end

    methods (Static, Access = ?parallel.Pool)
        function obj = createForEmptyPool()
            obj = parallel.pool.TicBytesResult([]);
        end
    end
    
    % Only allow methods of this class to be called from methods of
    % parallel.Pool so that a user can't make them
    methods (Access = ?parallel.Pool)
        function obj = TicBytesResult(pool)
            % Construction needs to differentiate between an empty pool
            % input (which means there is no current pool) and a fully
            % connected pool.
            if ~isempty(pool) && pool.Connected
                obj.PoolID = pool.ID;
                obj.Values = iGetCurrentValuesFromPool(pool);
            else
                obj.PoolID = 0;
                obj.Values = zeros(0, 2);
            end
        end
        
        function r = minus(A, B)
            % Implementation of difference between 2 TicBytesResult objects
            % which returns a matrix with the bytes transferred between the
            % retrieval of the objects
            if ~isequal(A.PoolID, B.PoolID)
                error(message('MATLAB:parallel:pool:TicBytesDifferentPool'));
            end
            r = A.Values - B.Values;
        end
        
        function dispMinus(A, B)
            % Display variant of difference between 2 TicBytesResults
            % objects.
            r = A - B;
            iDisplayTocBytesAsTable(r);
        end
    end
    
end

function o = iGetCurrentValuesFromPool(p)
% Internal helper function to interrogate a pool and extract how many bytes
% have been sent and received from workers. The internal helper method is
% on the underlying session object.
c = p.hGetClient;
s = c.Session;
m = s.getCurrentBytesTransferredToInstances;

o = zeros(p.NumWorkers, 2);
instances = m.keySet.toArray;
for ii = 1:numel(instances)
    index = instances(ii).getLabIndex;
    % The client might be included in the list of instances and will have a
    % labindex of -1. Ignore this when building the list of data.
    if index < 1
        continue
    end
    pair = m.get(instances(ii));
    % Order the information as BytesSentToWorkers followed by
    % BytesReceivedFromWorkers.
    o(index, 1:2) = [pair.getSecond pair.getFirst]; 
end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function  iDisplayTocBytesAsTable(o)
nLabs = size(o, 1);
if nLabs > 0
    labsNames = cellstr(num2str((1:nLabs).'));
else
    labsNames = {};
end
rowNames = [labsNames ; {'Total'}];
c = [o ; sum(o, 1)];
t = table( c(:, 1), c(:, 2), ...
    'VariableNames', {'BytesSentToWorkers', 'BytesReceivedFromWorkers'}, ...
    'RowNames', rowNames );
disp(t);
end
