VisualProxy.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / System / Windows / Media / VisualProxy.cs / 1305600 / VisualProxy.cs

                            //------------------------------------------------------------------------------ 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
//      Mapping between a visual and its handles on different channels. 
//
//----------------------------------------------------------------------------- 

namespace System.Windows.Media.Composition
{
    using System; 
    using System.Collections;
    using System.Collections.Generic; 
    using System.Diagnostics; 
    using System.Windows;
    using System.Windows.Media; 


    /// 
    /// Mapping between a visual and its handles on different channels. 
    /// 
    internal struct VisualProxy 
    { 
        // -------------------------------------------------------------------
        // 
        //   Private Types
        //
        // -------------------------------------------------------------------
 
        #region Private Types
 
        ///  
        /// Tuple binding a channel to a set of flags and a resource handle.
        ///  
        /// 
        /// Note that DUCE.Channel is a reference type.
        /// 
        private struct Proxy 
        {
            internal DUCE.Channel Channel; 
            internal VisualProxyFlags Flags; 
            internal DUCE.ResourceHandle Handle;
        } 

        #endregion Private Types

 
        // --------------------------------------------------------------------
        // 
        //   Internal Properties 
        //
        // ------------------------------------------------------------------- 

        #region Internal Properties

        ///  
        /// Returns the number of channels this resource is marshaled to.
        ///  
        internal int Count 
        {
            get 
            {
                if (_tail == null)
                {
                    return _head.Channel == null ? 0 : 1; 
                }
                else 
                { 
                    //
                    // The logic here is simple: we keep at most one entry 
                    // in the tail free. Heads has to be occupied and adds one.
                    //

                    int tailLength = _tail.Length; 

                    bool lastTailIsEmpty = 
                        _tail[tailLength - 1].Channel == null; 

                    return 1 + tailLength - (lastTailIsEmpty ? 1 : 0); 
                }
            }
        }
 

        ///  
        /// Returns true if the parent resource is marshaled to at least 
        /// one channel.
        ///  
        internal bool IsOnAnyChannel
        {
            get
            { 
                return Count != 0;
            } 
        } 

        #endregion Internal Properties 



        // -------------------------------------------------------------------- 
        //
        //   Internal Methods 
        // 
        // --------------------------------------------------------------------
 
        #region Internal Methods

        /// 
        /// Returns true if the visual is marshaled to the 
        /// specified channel.
        ///  
        internal bool IsOnChannel(DUCE.Channel channel) 
        {
            int index = Find(channel); 

            if (index == PROXY_NOT_FOUND)
            {
                return false; 
            }
            else if (index == PROXY_STORED_INLINE) 
            { 
                return !_head.Handle.IsNull;
            } 
            else
            {
                return !_tail[index].Handle.IsNull;
            } 
        }
 
        ///  
        /// If the visual is on channel, its reference count is increased.
        /// Otherwise, a new resource is created on that channel. 
        /// 
        internal bool CreateOrAddRefOnChannel(
            object instance,
            DUCE.Channel channel, 
            DUCE.ResourceType resourceType)
        { 
            int index = Find(channel); 
            int count = Count;
 
            if (index == PROXY_NOT_FOUND)
            {
                //
                // This is the case where we have to create a new resource. 
                //
 
                if (_head.Channel == null) 
                {
                    // 
                    // We're adding the first proxy.
                    //
                    // Before:        [empty]
                    // After insert:  [ head] 
                    //
 
                    Debug.Assert(count == 0); 

                    _head.Channel = channel; 
                    _head.Flags = VisualProxyFlags.None;

                    channel.CreateOrAddRefOnChannel(
                        instance, 
                        ref _head.Handle,
                        resourceType); 
                } 
                else
                { 
                    if (_tail == null)
                    {
                        //
                        // We're adding the second proxy. 
                        //
                        // Before:        [head] 
                        // After resize:  [head] [ empty] [empty] 
                        // After insert:  [head] [tail 0] [empty]
                        //                       ---------------- 

                        Debug.Assert(count == 1);

                        _tail = new Proxy[2]; 
                    }
                    else if (count > _tail.Length) 
                    { 
                        //
                        // Increase the tail size by 2. 
                        //
                        // Before:        [head] [tail 0] ... [tail c-2]
                        // After resize:  [head] [tail 0] ... [tail c-2] [   empty] [empty]
                        // After insert:  [head] [tail 0] ... [tail c-3] [tail c-2] [empty] 
                        //                       ------------------------------------------
                        // 
 
                        ResizeTail(2);
                    } 

                    //
                    // Now that we have a tail, fill in the first free element.
                    // 

                    Proxy proxy; 
 
                    proxy.Channel = channel;
                    proxy.Flags = VisualProxyFlags.None; 
                    proxy.Handle = DUCE.ResourceHandle.Null;

                    channel.CreateOrAddRefOnChannel(
                        instance, 
                        ref proxy.Handle,
                        resourceType); 
 
                    _tail[count - 1] = proxy;
                } 

                return /* created */ true;
            }
            else if (index == PROXY_STORED_INLINE) 
            {
                // 
                // We simply need to increase the reference count on head... 
                //
 
                channel.CreateOrAddRefOnChannel(
                    instance,
                    ref _head.Handle,
                    resourceType); 
            }
            else 
            { 
                //
                // Increase the reference count on one of the tail proxies... 
                //

                channel.CreateOrAddRefOnChannel(
                    instance, 
                    ref _tail[index].Handle,
                    resourceType); 
            } 

            return /* not created */ false; 
        }


        ///  
        /// If visual is on channel, its reference count is increased.
        /// Otherwise, a new resource is created on that channel. 
        ///  
        internal bool ReleaseOnChannel(DUCE.Channel channel)
        { 
            int index = Find(channel);
            bool proxyRemoved = false;
            int count = Count;
 
            if (index == PROXY_STORED_INLINE)
            { 
                if (channel.ReleaseOnChannel(_head.Handle)) 
                {
                    // 
                    // Need to move the last of the non-empty tail to head
                    // or clear the head. Erase the head if that was the last
                    // proxy.
                    // 

                    if (count == 1) 
                    { 
                        _head = new Proxy();
                    } 
                    else
                    {
                        _head = _tail[count - 2];
                    } 

                    proxyRemoved = true; 
                } 
            }
            else if (index >= 0) 
            {
                if (channel.ReleaseOnChannel(_tail[index].Handle))
                {
                    // 
                    // Need to move the last of the non-empty tail to the
                    // removed index. Avoid in-place copying. 
                    // 

                    if (index != count - 2) 
                    {
                        _tail[index] = _tail[count - 2];
                    }
 
                    proxyRemoved = true;
                } 
            } 
            else
            { 
                Debug.Assert(index != PROXY_NOT_FOUND);
                return false;
            }
 
            if (proxyRemoved)
            { 
                if (_tail != null) 
                {
                    // 
                    // Keep the tail short. We allow for one extra free element
                    // in tail to avoid constant allocations / reallocations.
                    //
 
                    if (count == 2)
                    { 
                        //                        ------------------ 
                        // Before removal: [head] [tail c-1] [empty]
                        // Here and now:   [head] [ deleted] [empty] 
                        // After removal:  [head]
                        //

                        _tail = null; 
                    }
                    else if (count == _tail.Length) 
                    { 
                        //                        ---------------------------------------------------
                        // Before removal: [head] [tail 0] [tail 1] ... [tail c-3] [tail c-2] [empty] 
                        // Here and now:   [head] [tail 0] [tail 1] ... [tail c-3] [ deleted] [empty]
                        // After removal:  [head] [tail 0] [tail 1] ... [tail c-3]
                        //
 
                        ResizeTail(-2);
                    } 
                    else 
                    {
                        //                        ------------------------------------------------------ 
                        // Before removal: [head] [tail 0] [tail 1] ... [tail c-4] [tail c-3] [tail c-2]
                        // Here and now:   [head] [tail 0] [tail 1] ... [tail c-4] [tail c-3] [ deleted]
                        // After removal:  [head] [tail 0] [tail 1] ... [tail c-4] [tail c-3] [   empty]
                        // 

                        _tail[count - 2] = new Proxy(); 
                    } 
                }
            } 

            return proxyRemoved;
        }
 

        ///  
        /// Returns the channel that the n-th proxy connects to. 
        /// 
        internal DUCE.Channel GetChannel(int index) 
        {
            Debug.Assert(index >= 0 && index < Count);

            if (index < Count) 
            {
                if (index == 0) 
                { 
                    return _head.Channel;
                } 
                else if (index > 0)
                {
                    return _tail[index - 1].Channel;
                } 
            }
 
            return null; 
        }
 
        #endregion Internal Methods


 
        // ---------------------------------------------------------------
        // 
        //   Internal Methods: resource handle getters 
        //
        // --------------------------------------------------------------- 

        #region Internal Methods: resource handle getters

        ///  
        /// Returns the handle the visual has on a specific channel.
        ///  
        internal DUCE.ResourceHandle GetHandle(DUCE.Channel channel) 
        {
            return GetHandle(Find(channel) + 1); // Find's results are -1 based, adjust by one. 
        }


        ///  
        /// Returns the handle the visual has on the n-th channel.
        ///  
        internal DUCE.ResourceHandle GetHandle(int index) 
        {
            Debug.Assert(index >= 0 && index < Count); 

            if (index < Count)
            {
                if (index == 0) 
                {
                    return _head.Handle; 
                } 
                else if (index > 0)
                { 
                    return _tail[index - 1].Handle;
                }
            }
 
            return DUCE.ResourceHandle.Null;
        } 
 
        #endregion Internal Methods: resource handle getters
 


        // ---------------------------------------------------------------
        // 
        //   Internal Methods: visual proxy flags
        // 
        // ---------------------------------------------------------------- 

        #region Internal Methods: visual proxy flags 

        /// 
        /// Returns the flags the visual has on a specific channel.
        ///  
        internal VisualProxyFlags GetFlags(DUCE.Channel channel)
        { 
            return GetFlags(Find(channel) + 1); // Find's results are -1 based, adjust by one. 
        }
 

        /// 
        /// Returns the handle the visual has on n-th channel.
        ///  
        internal VisualProxyFlags GetFlags(int index)
        { 
            if (index < Count) 
            {
                if (index == 0) 
                {
                    return _head.Flags;
                }
                else if (index > 0) 
                {
                    return _tail[index - 1].Flags; 
                } 
            }
 
            return VisualProxyFlags.None;
        }

 
        /// 
        /// Sets the flags the visual has on a specific channel. 
        ///  
        internal void SetFlags(
            DUCE.Channel channel, 
            bool value,
            VisualProxyFlags flags)
        {
            SetFlags(Find(channel) + 1, value, flags); // Find's results are -1 based, adjust by one. 
        }
 
 
        /// 
        /// Sets the flags the visual has on the n-th channel. 
        /// 
        internal void SetFlags(
            int index,
            bool value, 
            VisualProxyFlags flags)
        { 
            Debug.Assert(index >= 0 && index < Count); 

            if (index < Count) 
            {
                if (index == 0)
                {
                    _head.Flags = 
                        value ? (_head.Flags | flags) : (_head.Flags & ~flags);
                } 
                else if (index > 0) 
                {
                    _tail[index - 1].Flags = 
                        value ? (_tail[index - 1].Flags | flags) : (_tail[index - 1].Flags & ~flags);
                }
            }
        } 

 
        ///  
        /// Sets the flags on all channels the visual is marshaled to.
        ///  
        internal void SetFlagsOnAllChannels(
            bool value,
            VisualProxyFlags flags)
        { 
            if (_head.Channel != null)
            { 
                _head.Flags = 
                    value ? (_head.Flags | flags) : (_head.Flags & ~flags);
 
                for (int i = 0, limit = Count - 1; i < limit; i++)
                {
                    _tail[i].Flags =
                        value ? (_tail[i].Flags | flags) : (_tail[i].Flags & ~flags); 
                }
            } 
        } 

        ///  
        /// Returns true if the given flags are set for every proxy or if
        /// the visual is not being marshaled.
        /// 
        internal bool CheckFlagsOnAllChannels( 
            VisualProxyFlags conjunctionFlags)
        { 
            if (_head.Channel != null) 
            {
                if ((_head.Flags & conjunctionFlags) != conjunctionFlags) 
                    return false;

                for (int i = 0, limit = Count - 1; i < limit; i++)
                { 
                    if ((_tail[i].Flags & conjunctionFlags) != conjunctionFlags)
                        return false; 
                } 
            }
 
            return true;
        }

        #endregion Internal Methods: visual proxy flags 

 
        // ------------------------------------------------------------------- 
        //
        //   Private Methods 
        //
        // --------------------------------------------------------------------

        #region Private Methods 

        ///  
        /// Looks for the given channel in the proxies list. 
        /// 
        private int Find(DUCE.Channel channel) 
        {
            if (_head.Channel == channel)
            {
                return PROXY_STORED_INLINE; 
            }
            else if (_tail != null) 
            { 
                for (int i = 0, limit = Count - 1; i < limit; i++)
                { 
                    if (_tail[i].Channel == channel)
                    {
                        return i;
                    } 
                }
            } 
 
            return PROXY_NOT_FOUND;
        } 

        /// 
        /// Grows or shrinks the tail by a given size.
        ///  
        private void ResizeTail(int delta)
        { 
            int newLength = _tail.Length + delta; 

            Debug.Assert(delta % 2 == 0 && newLength >= 2); 

            Proxy[] reallocatedTail = new Proxy[newLength];

            Array.Copy(_tail, reallocatedTail, Math.Min(_tail.Length, newLength)); 

            _tail = reallocatedTail; 
        } 

        #endregion Private Methods 



        // -------------------------------------------------------------------- 
        //
        //   Private Fields 
        // 
        // -------------------------------------------------------------------
 
        #region Private Fields

        /// 
        /// Returned by the Find method to denote that a proxy for the given 
        /// channel has not been found.
        ///  
        private const int PROXY_NOT_FOUND = -2; 

        ///  
        /// Returned by the Find method to denote that a proxy for the given
        /// channel has been found in the inline storage.
        /// 
        private const int PROXY_STORED_INLINE = -1; 

        ///  
        /// This data structure is optimized for single entry. _head is 
        /// the one entry that we inline into the struct for that purpose.
        ///  
        private Proxy _head;

        /// 
        /// All the other entries end up in this array. 
        /// 
        private Proxy[] _tail; 
 
        #endregion Private Fields
    } 
}



// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK