@@ -41,6 +41,8 @@ void pmmpthread_store_init(pmmpthread_store_t* store) {
41
41
zend_hash_init (
42
42
& store -> hash , 8 , NULL ,
43
43
(dtor_func_t )pmmpthread_store_storage_dtor , 1 );
44
+ store -> first = HT_INVALID_IDX ;
45
+ store -> last = HT_INVALID_IDX ;
44
46
} /* }}} */
45
47
46
48
/* {{{ */
@@ -286,6 +288,10 @@ int pmmpthread_store_delete(zend_object *object, zval *key) {
286
288
if (result == SUCCESS && was_pmmpthread_object ) {
287
289
_pmmpthread_store_bump_modcount_nolock (threaded );
288
290
}
291
+ //TODO: it would be better if we can update this, if we deleted the first element
292
+ ts_obj -> props .first = HT_INVALID_IDX ;
293
+ ts_obj -> props .last = HT_INVALID_IDX ;
294
+
289
295
//TODO: sync local properties?
290
296
pmmpthread_monitor_unlock (& ts_obj -> monitor );
291
297
} else result = FAILURE ;
@@ -414,6 +420,8 @@ static inline zend_bool pmmpthread_store_update_shared_property(pmmpthread_objec
414
420
}
415
421
}
416
422
}
423
+ ts_obj -> props .first = HT_INVALID_IDX ;
424
+ ts_obj -> props .last = HT_INVALID_IDX ;
417
425
418
426
return result ;
419
427
}
@@ -538,6 +546,12 @@ int pmmpthread_store_write(zend_object *object, zval *key, zval *write, zend_boo
538
546
if (result == SUCCESS && was_pmmpthread_object ) {
539
547
_pmmpthread_store_bump_modcount_nolock (threaded );
540
548
}
549
+ if (key ) {
550
+ //only invalidate position if an arbitrary key was used
551
+ //if the item was appended, the first element was either unchanged or the position was invalid anyway
552
+ ts_obj -> props .first = HT_INVALID_IDX ;
553
+ ts_obj -> props .last = HT_INVALID_IDX ;
554
+ }
541
555
//this isn't necessary for any specific property write, but since we don't have any other way to clean up local
542
556
//cached ThreadSafe references that are dead, we have to take the opportunity
543
557
pmmpthread_store_sync_local_properties (object );
@@ -576,12 +590,20 @@ int pmmpthread_store_shift(zend_object *object, zval *member) {
576
590
577
591
if (pmmpthread_monitor_lock (& ts_obj -> monitor )) {
578
592
zval key ;
579
- HashPosition position ;
580
593
zval * zstorage ;
581
594
582
- zend_hash_internal_pointer_reset_ex (& ts_obj -> props .hash , & position );
583
- if ((zstorage = zend_hash_get_current_data_ex (& ts_obj -> props .hash , & position ))) {
584
- zend_hash_get_current_key_zval_ex (& ts_obj -> props .hash , & key , & position );
595
+ if (ts_obj -> props .first == HT_INVALID_IDX ) {
596
+ zend_hash_internal_pointer_reset_ex (& ts_obj -> props .hash , & ts_obj -> props .first );
597
+ }
598
+ if ((zstorage = zend_hash_get_current_data_ex (& ts_obj -> props .hash , & ts_obj -> props .first ))) {
599
+ zend_hash_get_current_key_zval_ex (& ts_obj -> props .hash , & key , & ts_obj -> props .first );
600
+
601
+ //the new first element will now be the next item, if there is one
602
+ if (zend_hash_move_forward_ex (& ts_obj -> props .hash , & ts_obj -> props .first ) == FAILURE ) {
603
+ ts_obj -> props .first = HT_INVALID_IDX ;
604
+ ts_obj -> props .last = HT_INVALID_IDX ;
605
+ }
606
+
585
607
zend_bool may_be_locally_cached ;
586
608
587
609
pmmpthread_store_restore_zval_ex (member , zstorage , & may_be_locally_cached );
@@ -617,17 +639,22 @@ int pmmpthread_store_chunk(zend_object *object, zend_long size, zend_bool preser
617
639
pmmpthread_object_t * ts_obj = threaded -> ts_obj ;
618
640
619
641
if (pmmpthread_monitor_lock (& ts_obj -> monitor )) {
620
- HashPosition position ;
621
642
zval * zstorage ;
622
643
623
644
array_init (chunk );
624
- zend_hash_internal_pointer_reset_ex (& ts_obj -> props .hash , & position );
645
+ if (ts_obj -> props .first == HT_INVALID_IDX ) {
646
+ zend_hash_internal_pointer_reset_ex (& ts_obj -> props .hash , & ts_obj -> props .first );
647
+ }
625
648
zend_bool stale_local_cache = 0 ;
626
649
while ((zend_hash_num_elements (Z_ARRVAL_P (chunk )) < size ) &&
627
- (zstorage = zend_hash_get_current_data_ex (& ts_obj -> props .hash , & position ))) {
650
+ (zstorage = zend_hash_get_current_data_ex (& ts_obj -> props .hash , & ts_obj -> props . first ))) {
628
651
zval key , zv ;
629
652
630
- zend_hash_get_current_key_zval_ex (& ts_obj -> props .hash , & key , & position );
653
+ zend_hash_get_current_key_zval_ex (& ts_obj -> props .hash , & key , & ts_obj -> props .first );
654
+ if (zend_hash_move_forward_ex (& ts_obj -> props .hash , & ts_obj -> props .first ) == FAILURE ) {
655
+ ts_obj -> props .first = HT_INVALID_IDX ;
656
+ ts_obj -> props .last = HT_INVALID_IDX ;
657
+ }
631
658
632
659
zend_bool may_be_locally_cached ;
633
660
pmmpthread_store_restore_zval_ex (& zv , zstorage , & may_be_locally_cached );
@@ -651,8 +678,6 @@ int pmmpthread_store_chunk(zend_object *object, zend_long size, zend_bool preser
651
678
}
652
679
zend_string_release (Z_STR (key ));
653
680
}
654
-
655
- zend_hash_internal_pointer_reset_ex (& ts_obj -> props .hash , & position );
656
681
}
657
682
if (stale_local_cache ) {
658
683
_pmmpthread_store_bump_modcount_nolock (threaded );
@@ -673,12 +698,18 @@ int pmmpthread_store_pop(zend_object *object, zval *member) {
673
698
674
699
if (pmmpthread_monitor_lock (& ts_obj -> monitor )) {
675
700
zval key ;
676
- HashPosition position ;
677
701
zval * zstorage ;
678
702
679
- zend_hash_internal_pointer_end_ex (& ts_obj -> props .hash , & position );
680
- if ((zstorage = zend_hash_get_current_data_ex (& ts_obj -> props .hash , & position ))) {
681
- zend_hash_get_current_key_zval_ex (& ts_obj -> props .hash , & key , & position );
703
+ if (ts_obj -> props .last == HT_INVALID_IDX ) {
704
+ zend_hash_internal_pointer_end_ex (& ts_obj -> props .hash , & ts_obj -> props .last );
705
+ }
706
+ if ((zstorage = zend_hash_get_current_data_ex (& ts_obj -> props .hash , & ts_obj -> props .last ))) {
707
+ zend_hash_get_current_key_zval_ex (& ts_obj -> props .hash , & key , & ts_obj -> props .last );
708
+
709
+ if (zend_hash_move_backwards_ex (& ts_obj -> props .hash , & ts_obj -> props .last ) == FAILURE ) {
710
+ ts_obj -> props .first = HT_INVALID_IDX ;
711
+ ts_obj -> props .last = HT_INVALID_IDX ;
712
+ }
682
713
683
714
zend_bool may_be_locally_cached ;
684
715
pmmpthread_store_restore_zval_ex (member , zstorage , & may_be_locally_cached );
@@ -1313,9 +1344,15 @@ void pmmpthread_store_reset(zend_object *object, HashPosition *position) {
1313
1344
pmmpthread_object_t * ts_obj = PMMPTHREAD_FETCH_TS_FROM (object );
1314
1345
1315
1346
if (pmmpthread_monitor_lock (& ts_obj -> monitor )) {
1316
- zend_hash_internal_pointer_reset_ex (& ts_obj -> props .hash , position );
1317
- if (zend_hash_has_more_elements_ex (& ts_obj -> props .hash , position ) == FAILURE ) { //empty
1318
- * position = HT_INVALID_IDX ;
1347
+ if (ts_obj -> props .first == HT_INVALID_IDX ) {
1348
+ zend_hash_internal_pointer_reset_ex (& ts_obj -> props .hash , position );
1349
+ if (zend_hash_has_more_elements_ex (& ts_obj -> props .hash , position ) == FAILURE ) { //empty
1350
+ * position = HT_INVALID_IDX ;
1351
+ } else {
1352
+ ts_obj -> props .first = * position ;
1353
+ }
1354
+ } else {
1355
+ * position = ts_obj -> props .first ;
1319
1356
}
1320
1357
pmmpthread_monitor_unlock (& ts_obj -> monitor );
1321
1358
}
0 commit comments