VisualProxy.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Core / System / Windows / Media / VisualProxy.cs / 1 / 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;
            } 
        }
 
        ///  
        /// This function duplicates a handle from the out-of-band channel
        /// to a normal a-sync channel. The resource has to have been already 
        /// created on out-of-band channel.
        /// It then stores the Channel and the handle of the non out-of-band
        /// channel since it is this cahnnel that is used later on in other
        /// functions. 
        /// 
        internal DUCE.ResourceHandle DuplicateHandle( 
            DUCE.Channel sourceChannel,     // outOfBandChannel 
            DUCE.ResourceHandle resourceHandle,
            DUCE.Channel targetChannel) 
        {
            int index = Find(sourceChannel);
            int count = Count;
 
            // The out-of-band channel should never be stored in the proxy.
            Debug.Assert(index == PROXY_NOT_FOUND); 
 
            // The resource should only be duplicated once on the target channel.
            Debug.Assert(count == 0); 
            Debug.Assert(_head.Channel == null);

            _head.Channel = targetChannel;
            _head.Flags = VisualProxyFlags.None; 
            _head.Handle = sourceChannel.DuplicateHandle(resourceHandle, targetChannel);
 
            return _head.Handle; 
        }
 
        /// 
        /// If the visual is on channel, its reference count is increased.
        /// Otherwise, a new resource is created on that channel.
        ///  
        internal bool CreateOrAddRefOnChannel(
            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(
                        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( 
                        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(
                    ref _head.Handle,
                    resourceType);
            } 
            else
            { 
                // 
                // Increase the reference count on one of the tail proxies...
                // 

                channel.CreateOrAddRefOnChannel(
                    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