示例#1
0
 internal void Unsubscribe(Func <T, CancellationToken, UniTask>?func)
 {
     if (func is null)
     {
         return;
     }
     _lock.Enter();          // ---- enter
     try {
         var funcs = _funcs;
         var count = _count;
         if (count == 0)
         {
             Debug.Assert(_funcs == null);
             return;
         }
         else if (count == 1)
         {
             if (ReferenceEquals(_funcs, func))
             {
                 _count = 0;
                 _funcs = null;
             }
             return;
         }
         else
         {
             var funcSpan = SafeCast.NotNullAs <Func <T, CancellationToken, UniTask>[]>(funcs).AsSpan(0, count);
             for (int i = 0; i < funcSpan.Length; i++)
             {
                 if (funcSpan[i] == func)
                 {
                     _count = count - 1;
                     if (i < _count)
                     {
                         var copyLen = _count - i;
                         funcSpan.Slice(i + 1, copyLen).CopyTo(funcSpan.Slice(i));
                     }
                     funcSpan[_count] = null !;
                     if (_count == 1)
                     {
                         _funcs = funcSpan[0];
                     }
                     return;
                 }
             }
             return;
         }
     }
     finally {
         _lock.Exit();       // ---- exit
     }
 }
示例#2
0
        internal void Subscribe(Action <T> action)
        {
            Debug.Assert(action is not null);
            _lock.Enter();          // ---- enter
            try {
                var count = _count;
                if (count == 0)
                {
                    Debug.Assert(_actions is null);
                    _actions = action;
                }
                else if (count == 1)
                {
                    Debug.Assert(_actions is Action <T>);

                    if (ArrayPoolForEventRaiser.TryGetArray4Fast(out var actions) == false)
                    {
                        actions = new object[DefaultBufferCapacity];
                    }
                    Debug.Assert(actions.Length >= 2);
                    MemoryMarshal.GetArrayDataReference(actions) = _actions;
                    Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(actions), 1) = action;
                    _actions = actions;
                }
                else
                {
                    var actions = SafeCast.NotNullAs <object?[]>(_actions);
                    if (actions.Length == count)
                    {
                        var newActions = new object[actions.Length * 2];
                        actions.AsSpan().CopyTo(newActions);
                        if (actions.Length == ArrayPoolForEventRaiser.LengthOfPoolTargetArray)
                        {
                            actions[0] = null;
                            actions[1] = null;
                            actions[2] = null;
                            actions[3] = null;
                            ArrayPoolForEventRaiser.ReturnArray4Fast(actions);
                        }
                        _actions = newActions;
                        actions  = newActions;
                    }
                    actions[count] = action;
                }
                _count = count + 1;
            }
            finally {
                _lock.Exit();       // ---- exit
            }
        }
示例#3
0
        private UniTask RaiseCore(T arg, CancellationToken cancellationToken, EventRaiseMode mode)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(UniTask.FromCanceled(cancellationToken));
            }

            // When _count == 0, there is no need to perform exclusive locking.
            if (_count == 0)
            {
                return(UniTask.CompletedTask);
            }

            _lock.Enter();          // ---- enter
            // Get _count after exclusive locking.
            var count = _count;

            if (count == 1)
            {
                var func = SafeCast.NotNullAs <Func <T, CancellationToken, UniTask> >(_funcs);
                _lock.Exit();       // ---- exit
                return(func.Invoke(arg, cancellationToken));
            }
            else
            {
                var funcArray = SafeCast.NotNullAs <Func <T, CancellationToken, UniTask>[]>(_funcs);
                var funcs     = funcArray.AsSpan(0, count);
                PooledAsyncEventFuncs <Func <T, CancellationToken, UniTask> > copiedFuncs;
                try {
                    copiedFuncs = new PooledAsyncEventFuncs <Func <T, CancellationToken, UniTask> >(count);
                    funcs.CopyTo(copiedFuncs.AsSpan());
                }
                finally {
                    _lock.Exit();       // ---- exit
                }
                if (mode == EventRaiseMode.Parallel)
                {
                    return(OrderedParallelAsyncEventPromise <T> .CreateTask(copiedFuncs, arg, cancellationToken));
                }
                else
                {
                    Debug.Assert(mode == EventRaiseMode.Sequential);
                    return(OrderedSequentialAsyncEventPromise <T> .CreateTask(copiedFuncs, arg, cancellationToken));
                }
            }
        }
示例#4
0
        public void Raise(T arg)
        {
            // When _count == 0, there is no need to perform exclusive locking.
            if (_count == 0)
            {
                return;
            }

            _lock.Enter();          // ---- enter
            // Get _count after exclusive locking.
            var count = _count;

            if (count == 1)
            {
                var action = SafeCast.NotNullAs <Action <T> >(_actions);
                _lock.Exit();       // ---- exit
                action.Invoke(arg);
                return;
            }
            else
            {
                using var mem = new RefTypeRentMemory <object?>(count);
                Span <object?> memSpan;
                try {
                    var actions = SafeCast.NotNullAs <object?[]>(_actions).AsSpan(0, count);
                    memSpan = mem.AsSpan();
                    actions.CopyTo(memSpan);
                }
                finally {
                    _lock.Exit();   // ---- exit
                }
                foreach (var action in memSpan)
                {
                    SafeCast.NotNullAs <Action <T> >(action).Invoke(arg);
                }
                return;
            }
        }
示例#5
0
 internal void Subscribe(Func <T, CancellationToken, UniTask> func)
 {
     Debug.Assert(func is not null);
     _lock.Enter();          // ---- enter
     try {
         var count = _count;
         if (count == 0)
         {
             Debug.Assert(_funcs is null);
             _funcs = func;
         }
         else if (count == 1)
         {
             var funcs = new Func <T, CancellationToken, UniTask> [DefaultBufferCapacity];
             funcs[0] = SafeCast.NotNullAs <Func <T, CancellationToken, UniTask> >(_funcs);
             funcs[1] = func;
             _funcs   = funcs;
         }
         else
         {
             var funcs = SafeCast.NotNullAs <Func <T, CancellationToken, UniTask>[]>(_funcs);
             if (funcs.Length == count)
             {
                 var newFuncs = new Func <T, CancellationToken, UniTask> [funcs.Length * 2];
                 funcs.AsSpan().CopyTo(newFuncs);
                 _funcs = newFuncs;
                 funcs  = newFuncs;
             }
             funcs[count] = func;
         }
         _count = count + 1;
     }
     finally {
         _lock.Exit();       // ---- exit
     }
     return;
 }
示例#6
0
 internal void Unsubscribe(Action <T>?action)
 {
     if (action is null)
     {
         return;
     }
     _lock.Enter();          // ---- enter
     try {
         var actions = _actions;
         var count   = _count;
         if (count == 0)
         {
             Debug.Assert(actions is null);
             return;
         }
         else if (count == 1)
         {
             if (ReferenceEquals(_actions, action))
             {
                 _count   = 0;
                 _actions = null;
             }
             return;
         }
         else
         {
             var actionSpan = SafeCast.NotNullAs <object?[]>(actions).AsSpan(0, count);
             for (int i = 0; i < actionSpan.Length; i++)
             {
                 if (ReferenceEquals(actionSpan[i], action))
                 {
                     _count = count - 1;
                     if (i < _count)
                     {
                         var copyLen = _count - i;
                         actionSpan.Slice(i + 1, copyLen).CopyTo(actionSpan.Slice(i));
                     }
                     actionSpan[_count] = null;
                     if (_count == 1)
                     {
                         var a            = actionSpan[0];
                         var actionsArray = SafeCast.NotNullAs <object?[]>(actions);
                         if (actionsArray.Length == ArrayPoolForEventRaiser.LengthOfPoolTargetArray)
                         {
                             actionsArray[0] = null;
                             actionsArray[1] = null;
                             actionsArray[2] = null;
                             actionsArray[3] = null;
                             ArrayPoolForEventRaiser.ReturnArray4Fast(actionsArray);
                         }
                         _actions = a;
                     }
                     return;
                 }
             }
             return;
         }
     }
     finally {
         _lock.Exit();       // ---- exit
     }
 }