⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 restack.h

📁 代理服务器原代码
💻 H
📖 第 1 页 / 共 2 页
字号:
            m_end     = m_current_node->m_head.m_end;
        }

        return pb;
    }

    void * _unwind( size_t size ) // throw()
    {
        return _unwind( m_current - size );
    }

    struct real_unwinder;
    friend struct real_unwinder;
    struct real_unwinder
    {
        stack_type * pstack_;
        size_t       size_;
        bool         dismissed_;
        real_unwinder( stack_type * pstack, size_t size ) // throw()
            : pstack_(pstack), size_(size), dismissed_(false) {}
        ~real_unwinder() // throw()
        {
            if( ! dismissed_ )
                pstack_->_unwind( size_ );
        }
        void dismiss() // throw()
        {
            dismissed_ = true;
        }
    };

    struct dummy_unwinder
    {
        dummy_unwinder( stack_type *, size_t ) {} // throw()
        void dismiss() {} // throw()
    };

    // Disallow these for now. Might implement them later.
    hetero_stack( hetero_stack const & );
    hetero_stack & operator=( hetero_stack const & );

public:

    class type_error : public std::logic_error
    {
        std::type_info const * prequested_type_;
        std::type_info const * pactual_type_;
    public:
        type_error( 
            std::type_info const & requested_type,
            std::type_info const & actual_type,
            std::string const & s = "type error in hetero_stack" ) // throw()
          : std::logic_error( s + " (requested type: " + requested_type.name()
                + ", actual type: " + actual_type.name() + ")" ),
            prequested_type_( &requested_type ),
            pactual_type_( &actual_type )
        {
        }
        std::type_info const & requested_type() const // throw()
        {
            return *prequested_type_;
        }
        std::type_info const & actual_type() const // throw()
        {
            return *pactual_type_;
        }
    };

    hetero_stack() // throw()
      : m_current_node( &m_first_node.m_node )
    {
        _check_align();
        m_first_node.m_node.m_head.m_back    = & m_first_node.m_node;
        m_first_node.m_node.m_head.m_next    = NULL;
        m_begin = m_current = m_first_node.m_node.m_head.m_current = m_first_node.m_node.m_mem;
        m_end = m_first_node.m_node.m_head.m_end = m_first_node.m_buf + sizeof( m_first_node );
    }

    ~hetero_stack() // throw()
    {
        m_current_node = m_first_node.m_node.m_head.m_next;
        for( stack_node * next_node; m_current_node; m_current_node = next_node )
        {
            next_node = m_current_node->m_head.m_next;
            ::operator delete( static_cast<void*>( m_current_node ) );
        }
    }

    template< typename T >
    inline void push( T const & t ) // throw(std::bad_alloc,...)
    {
        // Make sure that the alignment for type T is not worse
        // than our declared alignment.
        detail::static_assert<( Alignment >= detail::alignof<T>::value )> const align_test;
        ( void ) align_test;

        // If T won't throw in copy c'tor, and if RuntimeTypeCheck is false,
        // then we don't need to use an unwinder object.
        typedef typename ::regex::detail::select< AssumePOD, // || detail::has_trivial_copy<T>::value,
            dummy_unwinder, real_unwinder >::type unwinder;

        // If this throws, it doesn't change state,
        // so there is nothing to roll back.
        void * pv = _alloc( size_of<T>::with_rtti );

        // Rolls back the _alloc if later steps throw
        // BUGBUG we can do the alloc, but not update m_current until after
        // the copy c'tor to avoid the need for an unwinder object
        unwinder guard1( this, size_of<T>::with_rtti );

        new ( pv ) T( t ); // Could throw if ! has_trivial_copy<T>::value

        // If we are debugging the stack, then push a pointer to the type_info
        // for this type T. It will be checked in pop().
        if( RuntimeTypeCheck )
        {
            new ( static_cast<byte*>( pv ) + size_of<T>::aligned ) 
                ( std::type_info const*const* )( & detail::unique_type_info<T>::value );
        }

        // ok, everything succeeded -- dismiss the guard
        guard1.dismiss();
    }

    template< typename T >
    inline void pop( T & t ) // throw(...)
    {
        detail::static_assert<( Alignment >= detail::alignof<T>::value )> const align_test;
        ( void ) align_test;

        // If we are debugging the stack, then in push() we pushed a pointer
        // to the type_info struct for this type T.  Check it now.
        if( RuntimeTypeCheck )
        {
            void * pti = m_current - size_of<std::type_info const*const*>::aligned;
            if( ! detail::unique_type_info<T>::equals( *static_cast<std::type_info const*const**>( pti ) ) )
                throw type_error( typeid( T ), ***static_cast<std::type_info const*const**>( pti ) );
        }

        // Don't change state yet because assignment op could throw!
        void * pT = m_current - size_of<T>::with_rtti;
        t = *static_cast<T const*>( pT ); // could throw
        static_cast<T const*>( pT )->~T();
        _unwind( static_cast<byte*>( pT ) );
    }

    // Call this version of pop when you don't need the popped value
    template< typename T >
    inline void pop() // throw(type_error,...)
    {
        detail::static_assert<( Alignment >= detail::alignof<T>::value )> const align_test;
        ( void ) align_test;

        // If we are debugging the stack, then in push() we pushed a pointer

        // to the type_info struct for this type T.  Check it now.
        if( RuntimeTypeCheck )
        {
            void * pti = m_current - size_of<std::type_info const*const*>::aligned;
            if( ! detail::unique_type_info<T>::equals( *static_cast<std::type_info const*const**>( pti ) ) )
                throw type_error( typeid( T ), ***static_cast<std::type_info const*const**>( pti ) );
        }

        T const * pT = static_cast<T const *>( _unwind( size_of<T>::with_rtti ) );
        pT->~T();
    }

    // Call this version of pop when you don't need the popped value and
    // throwing an exception isn't an option
    template< typename T >
    inline bool pop( std::nothrow_t const & ) // throw()
    {
        detail::static_assert<( Alignment >= detail::alignof<T>::value )> const align_test;
        ( void ) align_test;

        // If we are debugging the stack, then in push() we pushed a pointer
        // to the type_info struct for this type T.  Check it now.
        if( RuntimeTypeCheck )
        {
            void * pti = m_current - size_of<std::type_info const*const*>::aligned;
            if( ! detail::unique_type_info<T>::equals( *static_cast<std::type_info const*const**>( pti ) ) )
                return false; // type error, can't throw so bail.
        }

        T const * pT = static_cast<T const *>( _unwind( size_of<T>::with_rtti ) );
        pT->~T();
        return true;
    }

    template< typename T >
    inline T & top( T ) const // throw(type_error,...)
    {
        detail::static_assert<( Alignment >= detail::alignof<T>::value )> const align_test;
        ( void ) align_test;

        if( RuntimeTypeCheck )
        {
            // If we are debugging the stack, then the top of the stack is a
            // pointer to a type_info struct. Assert that we have the correct type.
            void * pti = m_current - size_of<std::type_info const*const*>::aligned;
            if( ! detail::unique_type_info<T>::equals( *static_cast<std::type_info const*const**>( pti ) ) )
                throw type_error( typeid( T ), ***static_cast<std::type_info const*const**>( pti ) );
        }

        void * pT = m_current - size_of<T>::with_rtti;
        return *static_cast<T*>( pT );
    }

    // Fetch the type_info for the element at the top of the stack
    std::type_info const & top_type() const // throw()
    {
        detail::static_assert< RuntimeTypeCheck > const type_check; ( void ) type_check;
        void * pti = m_current - size_of<std::type_info const*const*>::aligned;
        return ***static_cast<std::type_info const*const**>( pti );
    }

    // Get a pointer to the top of the stack
    void * set_jump() const // throw()
    {
        return m_current;
    }

    // Quick and dirty stack unwind. Does not call destructors.
    void long_jump( void * jump_ptr ) // throw()
    {
        for( ;; )
        {
            if( std::less<void*>()( jump_ptr, m_current_node->m_mem ) ||
                std::less<void*>()( m_current_node->m_head.m_end, jump_ptr ) )
            {
                m_current_node->m_head.m_current = m_current_node->m_mem;
                m_current_node = m_current_node->m_head.m_back;
            }
            else
            {
                m_begin   = m_current_node->m_mem;
                m_current = m_current_node->m_head.m_current = static_cast<byte*>( jump_ptr );
                m_end     = m_current_node->m_head.m_end;
                return;
            }
        }
    }

    bool empty() const // throw()
    {
        return m_current == m_first_node.m_node.m_mem;
    }

    // Use scoped_push for automatically pushing/popping
    // things to and from the stack. This is especially useful
    // if you want to push a bunch of things "atomically".  For
    // instance:
    //
    // typedef hetero_stack<>::scoped_pop scoped_pop;
    // scoped_pop p1 = stack.scoped_push( int(1) ); // could throw
    // scoped_pop p2 = stack.scoped_push( std::string("foo") ); // could throw
    // stack.push( float(3.14159) ); // could throw
    // p2.dismiss(); // ok, nothing threw, so ...
    // p1.dismiss(); //  ... dismiss the scoped_pops
    //
    // If p2 and p1 are not dismissed, as in the case when an
    // exception gets thrown, then they automatically pop their
    // arguments from the stack.

    class scoped_pop_base
    {
    protected:
        stack_type * pstack_;
        bool mutable owns_;
        scoped_pop_base & operator=( scoped_pop_base const & ); // disallow assignment
    public:
        scoped_pop_base( stack_type * pstack ) // throw(std::bad_alloc,...)
          : pstack_( pstack )
          , owns_( true )
        {
        }
        scoped_pop_base( scoped_pop_base const & that ) // throw() // destructive copy
          : pstack_( that.pstack_ )
          , owns_( that.owns_ )
        {
            // This popper takes ownership, that popper gives it up.
            that.owns_ = false;
        }
        void dismiss() const // throw()
        {
            owns_ = false;
        }
    };

    template< typename T >
    struct scoped_pop_t : public scoped_pop_base
    {
        scoped_pop_t( stack_type * pstack, T const & t ) // throw(std::bad_alloc,...)
          : scoped_pop_base( pstack )
        {
            // Note that if this throws an exception the destructor
            // will not get called, which is what we want.
            pstack_->push( t );
        }
        ~scoped_pop_t() // throw()
        {
            // If we own this stack space, pop it.
            if( owns_ )
                pstack_->template pop<T>( std::nothrow );
        }
    };

    template< typename T >
    scoped_pop_t<T> scoped_push( T const & t ) // throw(...)
    {
        return scoped_pop_t<T>( this, t );
    }

    typedef scoped_pop_base const & scoped_pop;
};

// BUGBUG push and pop *must* be balanced since d'tors need to be called.
// Iterative execution of regex matching makes this difficult considering
// the fact that push() could cause an exception to be thrown.  The entire
// stack of sub_expr* must be backtracked completely and correctly.

// Alternate solution: push nothing that needs to be destroyed.

#ifdef _MSC_VER
#pragma warning( pop )
#endif

} // namespace regex

#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -