
%

%   Copyright 2011-2020 The MathWorks, Inc.

classdef ( Hidden ) MJSFinishedCallbackMixin < parallel.internal.cluster.MJSCallbackMixin
    
    properties( Dependent )
        %FinishedFcn Callback executed when the job or task finishes
        FinishedFcn
    end
    
    properties( Transient, Access = private )
        % The "raw" callback function specified by the user.
        UserSpecifiedFinishedFcn
        
        % Listens to Finished event and calls the Callback fcn
        CallbackListener

        % Listens to Finished event and calls the Support Callback fcn
        SupportCallbackListener
        
        % Listens to Finished event and, since no more events can be fired,
        % unregisters this object for events.
        AutoEventUnregistrationListener
    end
    
    events( Hidden, ListenAccess = public, NotifyAccess = protected )
        Finished
    end
    
    properties ( Constant, Access = protected )
        FinishedEventName = 'Finished';
    end
    
    methods
        function val = get.FinishedFcn( obj )
            val = obj.UserSpecifiedFinishedFcn;
        end
        
        function set.FinishedFcn( obj, val )
            try
                if isempty(obj.CallbackListener)
                    obj.CallbackListener = event.listener( obj, obj.FinishedEventName, obj.NoOpCallback );
                    obj.CallbackListener.Enabled = false;
                end
                val = obj.setCallbackFcn( 'FinishedFcn', obj.CallbackListener, val );
                obj.UserSpecifiedFinishedFcn = val;
            catch err
                % Get the internal details off the stack
                throw(err);
            end            
        end
    end
    methods ( Hidden, Access = ?parallel.internal.cluster.MJSSupport )
        function setSupportFinishedCallbackFcn( obj, val )
            % Allow MJSSupport to set additional finished event listener
            try
                if isempty(obj.SupportCallbackListener)
                    obj.SupportCallbackListener = event.listener( obj, obj.FinishedEventName, obj.NoOpCallback );
                    obj.SupportCallbackListener.Enabled = false;
                end
                obj.setCallbackFcn( 'FinishedFcn', obj.SupportCallbackListener, val );
            catch err
                % Get the internal details off the stack
                throw(err);
            end
        end
    end
    
    methods( Access = protected )
        function enableAutoEventUnregistration( obj )
            if isempty(obj.AutoEventUnregistrationListener)
                obj.AutoEventUnregistrationListener = event.listener( obj, obj.FinishedEventName, @obj.unregisterForAllEvents );
            end
            obj.AutoEventUnregistrationListener.Enabled = true;
        end
        
        function disableAutoEventUnregistration( obj )
            if ~isempty(obj.AutoEventUnregistrationListener)
                obj.AutoEventUnregistrationListener.Enabled = false;
            end
        end
        
        function unregisterForAllEvents( obj, varargin )
            % varargin because it is used as a listener callback and so
            % will be passed source and event.
            if obj.RegistrationCount > 0
                obj.doUnregisterForEvents();
                obj.RegistrationCount = 0;
            end
        end
    end
    
end

