<?xml version="1.0" encoding="UTF-8"?>
<!-- Reviewed: no -->
<sect1 id="zend.memory.memory-objects">
    <title>Memory Objects</title>

    <sect2 id="zend.memory.memory-objects.movable">
        <title>Movable</title>

        <para>
            Create movable memory objects using the <methodname>create([$data])</methodname>
            method of the memory manager:
        </para>

        <programlisting language="php"><![CDATA[
$memObject = $memoryManager->create($data);
]]></programlisting>

        <para>
            "Movable" means that such objects may be swapped and unloaded from
            memory and then loaded when application code accesses the object.
        </para>
    </sect2>

    <sect2 id="zend.memory.memory-objects.locked">
        <title>Locked</title>

        <para>
            Create locked memory objects using the <methodname>createLocked([$data])</methodname>
            method of the memory manager:
        </para>

        <programlisting language="php"><![CDATA[
$memObject = $memoryManager->createLocked($data);
]]></programlisting>

        <para>
            "Locked" means that such objects are never swapped and unloaded
            from memory.
        </para>

        <para>
            Locked objects provides the same interface as movable objects
            (<classname>Zend_Memory_Container_Interface</classname>).
            So locked object can be used in any place instead of movable objects.
        </para>

        <para>
            It's useful if an application or developer can decide, that some
            objects should never be swapped, based on performance considerations.
        </para>

        <para>
            Access to locked objects is faster, because the memory manager doesn't
            need to track changes for these objects.
        </para>

        <para>
            The locked objects class (<classname>Zend_Memory_Container_Locked</classname>)
            guarantees virtually the same performance as working with a string
            variable. The overhead is a single dereference to get the class property.
        </para>
    </sect2>

    <sect2 id="zend.memory.memory-objects.value">
        <title>Memory container 'value' property</title>

        <para>
            Use the memory container (movable or locked) '<property>value</property>'
            property to operate with memory object data:
        </para>

        <programlisting language="php"><![CDATA[
$memObject = $memoryManager->create($data);

echo $memObject->value;

$memObject->value = $newValue;

$memObject->value[$index] = '_';

echo ord($memObject->value[$index1]);

$memObject->value = substr($memObject->value, $start, $length);
]]></programlisting>

        <para>
            An alternative way to access memory object data is to use the <link
                linkend="zend.memory.memory-objects.api.getRef"><methodname>getRef()</methodname></link>
            method. This method <emphasis>must</emphasis> be used for <acronym>PHP</acronym>
            versions before 5.2. It also may have to be used in some other
            cases for performance reasons.
        </para>
    </sect2>

    <sect2 id="zend.memory.memory-objects.api">
        <title>Memory container interface</title>

        <para>
            Memory container provides the following methods:
        </para>

        <sect3 id="zend.memory.memory-objects.api.getRef">
            <title>getRef() method</title>

            <programlisting language="php"><![CDATA[
public function &getRef();
]]></programlisting>

            <para>
                The <methodname>getRef()</methodname> method returns reference to the object value.
            </para>

            <para>
                Movable objects are loaded from the cache at this moment if the
                object is not already in memory. If the object is loaded from
                the cache, this might cause swapping of other objects if the
                memory limit would be exceeded by having all the managed
                objects in memory.
            </para>

            <para>
                The <methodname>getRef()</methodname> method <emphasis>must</emphasis> be
                used to access memory object data for <acronym>PHP</acronym> versions before 5.2.
            </para>

            <para>
                Tracking changes to data needs additional resources.
                The <methodname>getRef()</methodname> method returns reference to string,
                which is changed directly by user application.
                So, it's a good idea to use the <methodname>getRef()</methodname> method
                for value data processing:
            </para>

            <programlisting language="php"><![CDATA[
$memObject = $memoryManager->create($data);

$value = &$memObject->getRef();

for ($count = 0; $count < strlen($value); $count++) {
    $char = $value[$count];
    ...
}
]]></programlisting>
        </sect3>

        <sect3 id="zend.memory.memory-objects.api.touch">
            <title>touch() method</title>

            <programlisting language="php"><![CDATA[
public function touch();
]]></programlisting>

            <para>
                The <methodname>touch()</methodname> method should be used in common with
                <methodname>getRef()</methodname>. It signals that object value has been changed:
            </para>

            <programlisting language="php"><![CDATA[
$memObject = $memoryManager->create($data);
...

$value = &$memObject->getRef();

for ($count = 0; $count < strlen($value); $count++) {
    ...
    if ($condition) {
        $value[$count] = $char;
    }
    ...
}

$memObject->touch();
]]></programlisting>
        </sect3>

        <sect3 id="zend.memory.memory-objects.api.lock">
            <title>lock() method</title>

            <programlisting language="php"><![CDATA[
public function lock();
]]></programlisting>

            <para>
                The <methodname>lock()</methodname> methods locks object in memory.
                It should be used to prevent swapping of some objects you choose.
                Normally, this is not necessary, because the memory manager uses
                an intelligent algorithm to choose candidates for swapping.
                But if you exactly know, that at this part of code some
                objects should not be swapped, you may lock them.
            </para>

            <para>
                Locking objects in memory also guarantees that reference
                returned by the <methodname>getRef()</methodname> method is valid until you
                unlock the object:
            </para>

            <programlisting language="php"><![CDATA[
$memObject1 = $memoryManager->create($data1);
$memObject2 = $memoryManager->create($data2);
...

$memObject1->lock();
$memObject2->lock();

$value1 = &$memObject1->getRef();
$value2 = &$memObject2->getRef();

for ($count = 0; $count < strlen($value2); $count++) {
    $value1 .= $value2[$count];
}

$memObject1->touch();
$memObject1->unlock();
$memObject2->unlock();
]]></programlisting>
        </sect3>

        <sect3 id="zend.memory.memory-objects.api.unlock">
            <title>unlock() method</title>

            <programlisting language="php"><![CDATA[
public function unlock();
]]></programlisting>

            <para>
                <methodname>unlock()</methodname> method unlocks object when it's no longer
                necessary to be locked. See the example above.
            </para>
        </sect3>

        <sect3 id="zend.memory.memory-objects.api.isLocked">
            <title>isLocked() method</title>

            <programlisting language="php"><![CDATA[
public function isLocked();
]]></programlisting>

            <para>
                The <methodname>isLocked()</methodname> method can be used to check if
                object is locked. It returns <constant>TRUE</constant> if the object
                is locked, or <constant>FALSE</constant> if it is not locked.
                This is always <constant>TRUE</constant> for "locked" objects,
                and may be either <constant>TRUE</constant> or <constant>FALSE</constant>
                for "movable" objects.
            </para>
        </sect3>
    </sect2>
</sect1>
