Hello Andrey,

  thanks! I wanted to do it earlier but had no idea how to sole the problem.
I actually right from the beginning wanted to do all three in there. Anyway
you might also want to see t he last slides of my last presentation (the one
from OSCON) which you can find here: http://talks.somabo.de/

best regards
marcus

Thursday, August 11, 2005, 12:04:37 AM, you wrote:

>    Wonderful idea Helly!

> Andrey

> Marcus Boerger wrote:
>> helly         Wed Aug 10 17:56:02 2005 EDT
>> 
>>   Added files:                 
>>     /php-src/ext/spl/internal splobjectstorage.inc 
>>     /php-src/ext/spl/tests    observer_002.phpt 
>> 
>>   Modified files:              
>>     /php-src/ext/spl  spl_observer.c 
>>   Log:
>>   - Implement SplObjectStorage as announced during OSCON
>>   # This class starts naming of new classes in Spl by prefix Spl as dicussed.
>>   # The class reduces object storage complexity from O(n) to O(1) which is
>>   # not possible in user space.
>>   
>>   
>> 
>> 
>> ------------------------------------------------------------------------
>> 
>> http://cvs.php.net/diff.php/php-src/ext/spl/spl_observer.c?r1=1.2&r2=1.3&ty=u
>> Index: php-src/ext/spl/spl_observer.c
>> diff -u php-src/ext/spl/spl_observer.c:1.2 php-src/ext/spl/spl_observer.c:1.3
>> --- php-src/ext/spl/spl_observer.c:1.2        Wed Aug  3 10:07:53 2005
>> +++ php-src/ext/spl/spl_observer.c    Wed Aug 10 17:56:00 2005
>> @@ -16,7 +16,7 @@
>>    
>> +----------------------------------------------------------------------+
>>   */
>>  
>> -/* $Id: spl_observer.c,v 1.2 2005/08/03 14:07:53 sniper Exp $ */
>> +/* $Id: spl_observer.c,v 1.3 2005/08/10 21:56:00 helly Exp $ */
>>  
>>  #ifdef HAVE_CONFIG_H
>>  # include "config.h"
>> @@ -32,6 +32,8 @@
>>  #include "spl_functions.h"
>>  #include "spl_engine.h"
>>  #include "spl_observer.h"
>> +#include "spl_iterators.h"
>> +#include "spl_array.h"
>>  
>>  SPL_METHOD(Observer, update);
>>  SPL_METHOD(Subject, attach);
>> @@ -65,14 +67,197 @@
>>       {NULL, NULL, NULL}
>>  };
>>  
>> -PHPAPI zend_class_entry  *spl_ce_Observer;
>> -PHPAPI zend_class_entry  *spl_ce_Subject;
>> +PHPAPI zend_class_entry     *spl_ce_Observer;
>> +PHPAPI zend_class_entry     *spl_ce_Subject;
>> +PHPAPI zend_class_entry     *spl_ce_SplObjectStorage;
>> +PHPAPI zend_object_handlers spl_handler_SplObjectStorage;
>> +
>> +typedef struct _spl_SplObjectStorage {
>> +     zend_object       std;
>> +     HashTable         storage;
>> +     long              index;
>> +     HashPosition      pos;
>> +} spl_SplObjectStorage;
>> +
>> +/* storage is an assoc aray of [zend_object_value]=>[zval*] */
>> +
>> +void spl_SplOjectStorage_free_storage(void *object TSRMLS_DC) /* {{{ */
>> +{
>> +     spl_SplObjectStorage *intern = (spl_SplObjectStorage *)object;
>> +
>> +     zend_hash_destroy(intern->std.properties);
>> +     FREE_HASHTABLE(intern->std.properties);
>> +
>> +     zend_hash_destroy(&intern->storage);
>> +
>> +     efree(object);
>> +} /* }}} */
>> +
>> +static zend_object_value spl_object_storage_new_ex(zend_class_entry
>> *class_type, spl_SplObjectStorage **obj, zval *orig TSRMLS_DC) /* {{{ */
>> +{
>> +     zend_object_value retval;
>> +     spl_SplObjectStorage *intern;
>> +     zval *tmp;
>> +
>> +     intern = emalloc(sizeof(spl_SplObjectStorage));
>> +     memset(intern, 0, sizeof(spl_SplObjectStorage));
>> +     intern->std.ce = class_type;
>> +     *obj = intern;
>> +
>> +     ALLOC_HASHTABLE(intern->std.properties);
>> +     zend_hash_init(intern->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
>> +     zend_hash_copy(intern->std.properties,
>> &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void
>> *) &tmp, sizeof(zval *));
>> +
>> +     zend_hash_init(&intern->storage, 0, NULL, ZVAL_PTR_DTOR, 0);
>> +
>> +     retval.handle = zend_objects_store_put(intern, NULL,
>> (zend_objects_free_object_storage_t) spl_SplOjectStorage_free_storage,
>> NULL TSRMLS_CC);
>> +     retval.handlers = &spl_handler_SplObjectStorage;
>> +     return retval;
>> +}
>> +/* }}} */
>> +
>> +/* {{{ spl_array_object_new */
>> +static zend_object_value spl_SplObjectStorage_new(zend_class_entry 
>> *class_type TSRMLS_DC)
>> +{
>> +     spl_SplObjectStorage *tmp;
>> +     return spl_object_storage_new_ex(class_type, &tmp, NULL TSRMLS_CC);
>> +}
>> +/* }}} */
>> +
>> +/* {{{ proto void SplObjectStorage::attach($obj)
>> + Attaches an object to the storage if not yet contained */
>> +SPL_METHOD(SplObjectStorage, attach)
>> +{
>> +     zval *obj;
>> +     spl_SplObjectStorage *intern =
>> (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
>> +
>> +     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == 
>> FAILURE) {
>> +             return;
>> +     }
>> +     
>> +     zend_hash_update(&intern->storage, (char*)&obj->value.obj,
>> sizeof(obj->value.obj), &obj, sizeof(zval**), NULL);
>> +     obj->refcount++;
>> +} /* }}} */
>> +
>> +/* {{{ proto void SplObjectStorage::detach($obj)
>> + Detaches an object from the storage */
>> +SPL_METHOD(SplObjectStorage, detach)
>> +{
>> +     zval *obj;
>> +     spl_SplObjectStorage *intern =
>> (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
>> +
>> +     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == 
>> FAILURE) {
>> +             return;
>> +     }
>> +     
>> +     zend_hash_del(&intern->storage, (char*)&obj->value.obj, 
>> sizeof(obj->value.obj));
>> +     zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
>> +     intern->index = 0;
>> +} /* }}} */
>> +
>> +/* {{{ proto bool SplObjectStorage::contains($obj)
>> + Determine whethe an object is contained in the storage */
>> +SPL_METHOD(SplObjectStorage, contains)
>> +{
>> +     zval *obj;
>> +     spl_SplObjectStorage *intern =
>> (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
>> +
>> +     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == 
>> FAILURE) {
>> +             return;
>> +     }
>> +     
>> +     RETURN_BOOL(zend_hash_exists(&intern->storage,
>> (char*)&obj->value.obj, sizeof(obj->value.obj)));
>> +} /* }}} */
>> +
>> +/* {{{ proto int SplObjectStorage::count()
>> + Determine number of objects in storage */
>> +SPL_METHOD(SplObjectStorage, count)
>> +{
>> +     spl_SplObjectStorage *intern =
>> (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
>> +     
>> +     RETURN_LONG(zend_hash_num_elements(&intern->storage));
>> +} /* }}} */
>> +
>> +/* {{{ proto void SplObjectStorage::rewind()
>> + */
>> +SPL_METHOD(SplObjectStorage, rewind)
>> +{
>> +     spl_SplObjectStorage *intern =
>> (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
>> +     
>> +     zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
>> +     intern->index = 0;
>> +} /* }}} */
>> +
>> +/* {{{ proto bool SplObjectStorage::valid()
>> + */
>> +SPL_METHOD(SplObjectStorage, valid)
>> +{
>> +     spl_SplObjectStorage *intern =
>> (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
>> +     
>> +     RETURN_BOOL(zend_hash_has_more_elements_ex(&intern->storage, 
>> &intern->pos) == SUCCESS);
>> +} /* }}} */
>> +
>> +/* {{{ proto mixed SplObjectStorage::key()
>> + */
>> +SPL_METHOD(SplObjectStorage, key)
>> +{
>> +     spl_SplObjectStorage *intern =
>> (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
>> +     
>> +     RETURN_LONG(intern->index);
>> +} /* }}} */
>> +
>> +/* {{{ proto mixed SplObjectStorage::current()
>> + */
>> +SPL_METHOD(SplObjectStorage, current)
>> +{
>> +     zval **entry;
>> +     spl_SplObjectStorage *intern =
>> (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
>> +     
>> +     if (zend_hash_get_current_data_ex(&intern->storage,
>> (void**)&entry, &intern->pos) == FAILURE) {
>> +             return;
>> +     }
>> +     RETVAL_ZVAL(*entry, 1, 0);
>> +} /* }}} */
>> +
>> +/* {{{ proto void SplObjectStorage::next()
>> + */
>> +SPL_METHOD(SplObjectStorage, next)
>> +{
>> +     spl_SplObjectStorage *intern =
>> (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
>> +     
>> +     zend_hash_move_forward_ex(&intern->storage, &intern->pos);
>> +     intern->index++;
>> +} /* }}} */
>> +
>> +static
>> +ZEND_BEGIN_ARG_INFO(arginfo_Object, 0)
>> +     ZEND_ARG_INFO(0, object 0)
>> +ZEND_END_ARG_INFO();
>> +
>> +static zend_function_entry spl_funcs_SplObjectStorage[] = {
>> +     SPL_ME(SplObjectStorage,  attach,      arginfo_Object,        0)
>> +     SPL_ME(SplObjectStorage,  detach,      arginfo_Object,        0)
>> +     SPL_ME(SplObjectStorage,  contains,    arginfo_Object,        0)
>> +     SPL_ME(SplObjectStorage,  count,       NULL,                  0)
>> +     SPL_ME(SplObjectStorage,  rewind,      NULL,                  0)
>> +     SPL_ME(SplObjectStorage,  valid,       NULL,                  0)
>> +     SPL_ME(SplObjectStorage,  key,         NULL,                  0)
>> +     SPL_ME(SplObjectStorage,  current,     NULL,                  0)
>> +     SPL_ME(SplObjectStorage,  next,        NULL,                  0)
>> +     {NULL, NULL, NULL}
>> +};
>>  
>>  /* {{{ PHP_MINIT_FUNCTION(spl_observer) */
>>  PHP_MINIT_FUNCTION(spl_observer)
>>  {
>>       REGISTER_SPL_INTERFACE(Observer);
>>       REGISTER_SPL_INTERFACE(Subject);
>> +
>> +     REGISTER_SPL_STD_CLASS_EX(SplObjectStorage,
>> spl_SplObjectStorage_new, spl_funcs_SplObjectStorage);
>> +     memcpy(&spl_handler_SplObjectStorage,
>> zend_get_std_object_handlers(), sizeof(zend_object_handlers));
>> +
>> +     REGISTER_SPL_IMPLEMENTS(SplObjectStorage, Countable);
>> +     REGISTER_SPL_IMPLEMENTS(SplObjectStorage, Iterator);
>>       
>>       return SUCCESS;
>>  }
>> 
>> http://cvs.php.net/co.php/php-src/ext/spl/internal/splobjectstorage.inc?r=1.1&p=1
>> Index: php-src/ext/spl/internal/splobjectstorage.inc
>> +++ php-src/ext/spl/internal/splobjectstorage.inc
>> <?php
>> 
>> /** @file splobjectstorage.inc
>>  * @ingroup SPL
>>  * @brief class SplObjectStorage
>>  * @author  Marcus Boerger
>>  * @date    2003 - 2005
>>  *
>>  * SPL - Standard PHP Library
>>  */
>> 
>> /**
>>  * @brief   Object storage
>>  * @author  Marcus Boerger
>>  * @version 1.0
>>  * @since PHP 6.0
>>  *
>>  * This container allows to store objects uniquly without the need to compare
>>  * them one by one. This is only possible internally. The code represenation
>>  * here therefore has a complexity of O(n) while the actual implementation 
>> has
>>  * complexity O(1).
>>  */
>> class SplObjectStorage implements Iterator, Countable
>> {
>>       private $storage = array();
>>       private $index = 0;
>> 
>>       /** Rewind to top iterator as set in constructor
>>        */
>>       function rewind()
>>       {
>>               rewind($this->storage);
>>       }
>>       
>>       /** @return whether iterator is valid
>>        */
>>       function valid()
>>       {
>>               return key($this->storage) !== false;
>>       }
>>       
>>       /** @return current key
>>        */
>>       function key()
>>       {
>>               return $this->index;
>>       }
>>       
>>       /** @return current object
>>        */
>>       function current()
>>       {
>>               return current($this->storage);
>>       }
>>       
>>       /** Forward to next element
>>        */
>>       function next()
>>       {
>>               next($this->storage);
>>               $this->index++;
>>       }
>> 
>>       /** @return number of objects in storage
>>        */
>>       function count()
>>       {
>>               return count($this->storage);
>>       }
>> 
>>       /** @obj object to look for
>>        * @return whether $obj is contained in storage
>>         */
>>       function contains($obj)
>>       {
>>               if (is_object($obj))
>>               {
>>                       foreach($this->storage as $object)
>>                       {
>>                               if ($object === $obj)
>>                               {
>>                                       return true;
>>                               }
>>                       }
>>               }
>>               return false;
>>       }
>> 
>>       /** @param $obj new object to attach to storage if not yet contained
>>        */
>>       function attach($obj)
>>       {
>>               if (is_object($obj) && !$this->contains($obj))
>>               {
>>                       $this->storage[] = $obj;
>>               }
>>       }
>> 
>>       /** @param $obj object to remove from storage
>>        */
>>       function detach($obj)
>>       {
>>               if (is_object($obj))
>>               {
>>                       foreach($this->storage as $idx => $object)
>>                       {
>>                               if ($object === $obj)
>>                               {
>>                                       unset($this->storage[$idx]);
>>                                       $this->rewind();
>>                                       return;
>>                               }
>>                       }
>>               }
>>       }
>> }
>> 
>> ?>
>> http://cvs.php.net/co.php/php-src/ext/spl/tests/observer_002.phpt?r=1.1&p=1
>> Index: php-src/ext/spl/tests/observer_002.phpt
>> +++ php-src/ext/spl/tests/observer_002.phpt
>> --TEST--
>> SPL: SplObjectStorage
>> --FILE--
>> <?php
>> 
>> class MyObjectStorage extends SplObjectStorage
>> {
>>       function rewind()
>>       {
>>               echo __METHOD__ . "()\n";
>>               parent::rewind();
>>       }
>> 
>>       function valid()
>>       {
>>               echo __METHOD__ . "(" . (parent::valid() ? 1 : 0) . ")\n";
>>               return parent::valid();
>>       }
>> 
>>       function key()
>>       {
>>               echo __METHOD__ . "(" . parent::key() . ")\n";
>>               return parent::key();
>>       }
>> 
>>       function current()
>>       {
>>               echo __METHOD__ . "(" . parent::current()->getName() . ")\n";
>>               return parent::current();
>>       }
>> 
>>       function next()
>>       {
>>               echo __METHOD__ . "()\n";
>>               parent::next();
>>       }
>> }
>> 
>> class ObserverImpl implements Observer
>> {
>>       protected $name = '';
>> 
>>       function __construct($name = 'obj')
>>       {
>>               $this->name = '$' . $name;
>>       }
>> 
>>       function update(Subject $subject)
>>       {
>>               echo $this->name . '->' . __METHOD__ . '(' . 
>> $subject->getName() . ");\n";
>>       }
>>       
>>       function getName()
>>       {
>>               return $this->name;
>>       }
>> }
>> 
>> class SubjectImpl implements Subject
>> {
>>       protected $name = '';
>>       protected $observers;
>> 
>>       function __construct($name = 'sub')
>>       {
>>               $this->observers = new MyObjectStorage;
>>               $this->name = '$' . $name;
>>       }
>> 
>>       function attach(Observer $observer)
>>       {
>>               echo $this->name . '->' . __METHOD__ . '(' . 
>> $observer->getName() . ");\n";
>>               $this->observers->attach($observer);
>>       }
>>       
>>       function detach(Observer $observer)
>>       {
>>               echo $this->name . '->' . __METHOD__ . '(' . 
>> $observer->getName() . ");\n";
>>               $this->observers->detach($observer);
>>       }
>>       
>>       function count()
>>       {
>>               return $this->observers->count();
>>       }
>>       
>>       function notify()
>>       {
>>               echo $this->name . '->' . __METHOD__ . "();\n";
>>               foreach($this->observers as $key => $observer)
>>               {
>>                       $observer->update($this);
>>               }
>>       }
>> 
>>       function getName()
>>       {
>>               return $this->name;
>>       }
>>       
>>       function contains($obj)
>>       {
>>               return $this->observers->contains($obj);
>>       }
>> }
>> 
>> $sub = new SubjectImpl;
>> 
>> $ob1 = new ObserverImpl("ob1");
>> $ob2 = new ObserverImpl("ob2");
>> $ob3 = new ObserverImpl("ob3");
>> 
>> var_dump($sub->contains($ob1));
>> $sub->attach($ob1);
>> var_dump($sub->contains($ob1));
>> $sub->attach($ob1);
>> $sub->attach($ob2);
>> $sub->attach($ob3);
>> var_dump($sub->count());
>> 
>> $sub->notify();
>> 
>> $sub->detach($ob3);
>> var_dump($sub->count());
>> 
>> $sub->notify();
>> 
>> $sub->detach($ob2);
>> $sub->detach($ob1);
>> var_dump($sub->count());
>> 
>> $sub->notify();
>> 
>> $sub->attach($ob3);
>> var_dump($sub->count());
>> 
>> $sub->notify();
>> 
>> ?>
>> ===DONE===
>> <?php exit(0); ?>
>> --EXPECT--
>> bool(false)
>> $sub->SubjectImpl::attach($ob1);
>> bool(true)
>> $sub->SubjectImpl::attach($ob1);
>> $sub->SubjectImpl::attach($ob2);
>> $sub->SubjectImpl::attach($ob3);
>> int(3)
>> $sub->SubjectImpl::notify();
>> MyObjectStorage::rewind()
>> MyObjectStorage::valid(1)
>> MyObjectStorage::current($ob1)
>> MyObjectStorage::key(0)
>> $ob1->ObserverImpl::update($sub);
>> MyObjectStorage::next()
>> MyObjectStorage::valid(1)
>> MyObjectStorage::current($ob2)
>> MyObjectStorage::key(1)
>> $ob2->ObserverImpl::update($sub);
>> MyObjectStorage::next()
>> MyObjectStorage::valid(1)
>> MyObjectStorage::current($ob3)
>> MyObjectStorage::key(2)
>> $ob3->ObserverImpl::update($sub);
>> MyObjectStorage::next()
>> MyObjectStorage::valid(0)
>> $sub->SubjectImpl::detach($ob3);
>> int(2)
>> $sub->SubjectImpl::notify();
>> MyObjectStorage::rewind()
>> MyObjectStorage::valid(1)
>> MyObjectStorage::current($ob1)
>> MyObjectStorage::key(0)
>> $ob1->ObserverImpl::update($sub);
>> MyObjectStorage::next()
>> MyObjectStorage::valid(1)
>> MyObjectStorage::current($ob2)
>> MyObjectStorage::key(1)
>> $ob2->ObserverImpl::update($sub);
>> MyObjectStorage::next()
>> MyObjectStorage::valid(0)
>> $sub->SubjectImpl::detach($ob2);
>> $sub->SubjectImpl::detach($ob1);
>> int(0)
>> $sub->SubjectImpl::notify();
>> MyObjectStorage::rewind()
>> MyObjectStorage::valid(0)
>> $sub->SubjectImpl::attach($ob3);
>> int(1)
>> $sub->SubjectImpl::notify();
>> MyObjectStorage::rewind()
>> MyObjectStorage::valid(1)
>> MyObjectStorage::current($ob3)
>> MyObjectStorage::key(0)
>> $ob3->ObserverImpl::update($sub);
>> MyObjectStorage::next()
>> MyObjectStorage::valid(0)
>> ===DONE===
>> 
>> 




Best regards,
 Marcus

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to