Сделайте большие ассигнования, которые будут автоматически совершены при первом прикосновении - PullRequest
3 голосов
/ 04 января 2011

Как я могу выделить память в Windows, но не зафиксировать ее до первого прикосновения?

Я вижу, что VirtualAlloc позволяет мне зарезервировать диапазон памяти, но затем мне нужно вручную зафиксировать разделы этой памяти перед использованием. Я хотел бы, чтобы принятие было автоматическим, когда я впервые ссылаюсь на него.

Также, если возможно, я не хочу обнулять память перед фиксацией.

(Кроме того, в Linux это можно сделать, настроив частное отображение памяти для фрагмента / dev / zero)

Ответы [ 2 ]

1 голос
/ 04 января 2011

Предположительно, отсроченное выделение поддержки для адресов является целью, а не обязательной фиксацией при первом использовании?Если это так, похоже, что Windows сделает это за вас автоматически!

http://msdn.microsoft.com/en-us/library/aa366803(v=vs.85).aspx

Соответствующая цитата:

Как альтернатива динамическому распределениюпроцесс может просто зафиксировать весь регион, а не только резервировать его.Оба метода приводят к одному и тому же использованию физической памяти, поскольку зафиксированные страницы не потребляют физической памяти до тех пор, пока к ним не будет получен первый доступ.

Что касается сброса новых страниц на ноль, я считаю, что это функция безопасности инельзя избежать(В системе есть специальный поток, который обнуляет страницы, когда есть какое-то мертвое время, поэтому, если повезет, всегда будет нулевая страница, сразу готовая к использованию при необходимости.)

1 голос
/ 04 января 2011

Вы можете использовать умный указатель вашего собственного дизайна, который фиксирует его при первом разыменовании (конечно, перегружая операторы разыменования и косвенного обращения).

Это пример умного указателя, который создает экземпляр данного объекта при первом разыменовании (отложенная реализация). Та же идея, в основном:

template <typename T>
struct default_constructor_factory
{
    T * operator ()() { return new T; }
};

template <typename T, typename F = default_constructor_factory<T> >
class lazy_ptr : boost::noncopyable
{
public:
    typedef T element_type;
    typedef T value_type;
    typedef F factory_type;
    typedef lazy_ptr<T,F> this_type;

    lazy_ptr() : m_ptr(), m_factory() { }
    lazy_ptr(F factory) : m_ptr(), m_factory(factory) { }
    ~lazy_ptr() { if (m_ptr != NULL) delete m_ptr; }

    T & operator* () const
    {
        return *get();
    }

    T * operator-> () const
    {
        return get();
    }

    T * get() const
    {
        if (m_ptr == NULL)
            m_ptr = m_factory();
        return m_ptr;
    }

    void reset(T * p)
    {
        if (p != m_ptr)
        {
            if (m_ptr != NULL)
                delete m_ptr;
            m_ptr = p;
        }
    }

    T * release()
    {
        T * p = m_ptr;
        m_ptr = NULL;
        return p;
    }

    // non-dereferencing accessors

    T * peek() const
    {
        // may return NULL
        return m_ptr;
    }

    bool dereferenced() const
    {
        return peek() != NULL;
    }

//  operator bool() const { return dereferenced(); }

    // handle intrinsic conversion to testable bool using unspecified_bool technique
    typedef T * this_type::*unspecified_bool_type;
    operator unspecified_bool_type() const // never throws
    {
        return dereferenced() ? &this_type::m_ptr : NULL;
    }

private:
    // we must remain it's only owner!
    mutable T * m_ptr;

    // our factory generates the needed element on-demand
    mutable factory_type m_factory;
};

// shared_lazy_ptr
//
// we act as a copyable lazy pointer
// essentially, we add reference counting to a single shared lazy pointer
//
template <typename T, typename F = default_constructor_factory<T> >
class shared_lazy_ptr
{
public:
    typedef T element_type;
    typedef T value_type;
    typedef F factory_type;
    typedef lazy_ptr<T,F> ptr_type;
    typedef shared_lazy_ptr<T,F> this_type;

    shared_lazy_ptr() : m_ptr(new ptr_type) { }
    shared_lazy_ptr(F factory) : m_ptr(new ptr_type(factory)) { }

    // copy ctor
    shared_lazy_ptr(const this_type & rhs) : m_ptr(rhs.m_ptr), m_references(rhs.m_references) { }

    // assignment
    this_type & operator = (const this_type & rhs)
    {
        if (m_references.Reattach(rhs.m_references))
            delete m_ptr;
        m_ptr = rhs.m_ptr;
        return *this;
    }

    ~shared_lazy_ptr() 
    {
        if (m_references.IsOnly())
            delete m_ptr;
    }

    T & operator* () const
    {
        return *get();
    }

    T * operator-> () const
    {
        return get();
    }

    T * get() const
    {
        return m_ptr->get();
    }

    void reset(T * p)
    {
        if (p != get())
        {
            if (m_ptr != NULL)
                delete m_ptr;
            m_ptr = p;
        }
    }

    // non-dereferencing accessors

    T * peek() const
    {
        // may return NULL
        return get()->peek();
    }

    bool dereferenced() const
    {
        return peek() != NULL;
    }

//  operator bool() const { return dereferenced(); }

    // handle intrinsic conversion to testable bool using unspecified_bool technique
    typedef T * this_type::*unspecified_bool_type;
    operator unspecified_bool_type() const // never throws
    {
        return dereferenced() ? &this_type::m_ptr : NULL;
    }

private:
    lazy_ptr<T, F> * m_ptr;         // shared *lazy* pointer to the actual object
    ReferenceCount m_references;    // shared reference count to our lazy pointer
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...