Example #1
0
            /// <summary>
            /// Find the data block for stream position 'position'.  If it is already been fetched great!
            /// If not return a block that can be filled in (but has NOT been).  You can tell because
            /// block.m_filled == false in that case.  It is also possible that the block is being filled
            /// so you have to wait on it (outside the StreamCache lock), before returning it.
            /// </summary>
            private DataBlock FindBlockForPosition(long position)
            {
                // We assume the StreamCache lock is held!
                DataBlock block     = m_blocks;
                DataBlock freeBlock = null;

                for (; ;)
                {
                    if (block.m_position <= position && position < block.m_position + block.m_len)
                    {
                        return(block);
                    }

                    if (freeBlock == null && block.m_refCount == 0 && !block.m_beingFilled)
                    {
                        freeBlock = block;
                    }

                    if (block == m_blocks)
                    {
                        // TODO, if we have not hit our concurrency limit, and it looks like we are streaming,
                        // add more workers, as the workers can't seem to keep up.
                        if (freeBlock == null)
                        {
                            freeBlock = m_blocks.m_next = new DataBlock(m_blocks.m_data.Length, this, m_blocks.m_next);
                        }

                        Debug.Assert(!block.m_beingFilled && block.m_refCount == 0);
                        block = freeBlock;
                        block.Clear(position);
                        break;
                    }
                }
                return(block);
            }
Example #2
0
            /// <summary>
            /// This routine returns a block that we have determined is useful to prefetch.   If we can't
            /// find a good block to prefetch, we return null.
            /// </summary>
            private DataBlock GetDataBlockToFetch()
            {
                // We assume the StreamCache lock is held!

                // Our heuristic is simple:  Just read ahead from the block at m_block
                DataBlock block = m_blocks.m_next;
                long      positionToPrefetch = m_blocks.m_position + m_blocks.m_len;
                long      length             = Length;

                for (; ;)
                {
                    // If we have not already done the readahead
                    if (block.m_position != positionToPrefetch)
                    {
                        if (positionToPrefetch >= length)       // past end of stream
                        {
                            return(null);
                        }

                        // It is not in use one way or the other
                        if (block.m_refCount == 0 && !block.m_beingFilled)
                        {
                            // Then go ahead and use it to prefetch.
                            block.Clear(positionToPrefetch);
                            return(block);
                        }
                    }
                    else
                    {
                        positionToPrefetch = block.m_position + block.m_len;
                    }

                    if (block == m_blocks)
                    {
                        return(null);
                    }
                }
            }