Ejemplo n.º 1
0
        protected override sealed Delegate CombineImpl(Delegate other)
        {
            if (other == null)
            {
                return(this);
            }

            MulticastDelegate o = (MulticastDelegate)other;


            var oInvList = o.InvocationList;
            var oInvLen  = o.InvocationListLength;

            o = o.WithoutInvocationList(); // we flatten the list.

            var newInvList = InvocationList;
            var curInvLen  = InvocationListLength;
            int newInvLen  = curInvLen + 1 + oInvLen;

            bool needNewList = newInvList == null || newInvList.Length < newInvLen;

            // try appending to the current list.
            if (!needNewList)
            {
                //if (Interlocked.CompareExchange(ref lostInvocationList, 1, 0) != 0 /*!TakeInvokationListOwnership()*/)
                // The locking might acually be faster than forcing a field of the class to be volatile,
                // but more measurements are needed.
                lock (InvocationList)
                {
                    if (lostInvocationList != 0)
                    {
                        needNewList = true;
                    }
                    else
                    {
                        lostInvocationList = 1;
                    }
                }

                if (!needNewList)
                {
                    newInvList[curInvLen] = o;
                    for (int i = 0; i < oInvLen; ++i)
                    {
                        newInvList[curInvLen + i + 1] = oInvList[i];
                    }
                }
            }

            if (needNewList)
            {
                // start by 4, duplicate size.
                int len = newInvList == null ? 4 : newInvList.Length;
                while (len < newInvLen)
                {
                    len *= 2;
                }

                MulticastDelegate[] list = new MulticastDelegate[len];

                var curInvList = InvocationList;
                for (int i = 0; i < curInvLen; ++i)
                {
                    list[i] = curInvList[i];
                }

                list[curInvLen] = o;

                for (int i = 0; i < oInvLen; ++i)
                {
                    list[curInvLen + 1 + i] = oInvList[i];
                }

                newInvList = list;
            }

            return(this.CloneWithNewInvocationList(newInvList, newInvLen));
        }