Skip to content

Commit b40c4cd

Browse files
committed
Adding support for native WeakReferences
PHP 7.4 adds native support for WeakReferences. There will be no need for the weakref extension (that was incompatible with PHP 7.3). This PR adds support for these new Weakrefences.
1 parent 9f9dac2 commit b40c4cd

File tree

3 files changed

+115
-3
lines changed

3 files changed

+115
-3
lines changed

src/NativeWeakrefObjectStorage.php

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
/*
5+
Copyright (C) 2006-2014 David Négrier - THE CODING MACHINE
6+
7+
This program is free software; you can redistribute it and/or modify
8+
it under the terms of the GNU General Public License as published by
9+
the Free Software Foundation; either version 2 of the License, or
10+
(at your option) any later version.
11+
12+
This program is distributed in the hope that it will be useful,
13+
but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
GNU General Public License for more details.
16+
17+
You should have received a copy of the GNU General Public License
18+
along with this program; if not, write to the Free Software
19+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20+
*/
21+
22+
namespace TheCodingMachine\TDBM;
23+
24+
use WeakReference;
25+
26+
/**
27+
* The NativeWeakrefObjectStorage class is used to reference all beans that have been fetched from the database.
28+
* If a bean is requested twice from TDBM, the NativeWeakrefObjectStorage is used to "cache" the bean.
29+
* Unlike the StandardObjectStorage, the NativeWeakrefObjectStorage manages memory in a clever way, using WeakReference.
30+
* WeakReference have been added in PHP 7.4.
31+
*
32+
* @author David Negrier
33+
*/
34+
class NativeWeakrefObjectStorage implements ObjectStorageInterface
35+
{
36+
/**
37+
* An array of fetched object, accessible via table name and primary key.
38+
* If the primary key is split on several columns, access is done by an array of columns, serialized.
39+
*
40+
* @var WeakReference[][]
41+
*/
42+
private $objects = array();
43+
44+
/**
45+
* Every 10000 set in the dataset, we perform a cleanup to ensure the WeakRef instances
46+
* are removed if they are no more valid.
47+
* This is to avoid having memory used by dangling WeakRef instances.
48+
*
49+
* @var int
50+
*/
51+
private $garbageCollectorCount = 0;
52+
53+
/**
54+
* Sets an object in the storage.
55+
*
56+
* @param string $tableName
57+
* @param string|int $id
58+
* @param DbRow $dbRow
59+
*/
60+
public function set(string $tableName, $id, DbRow $dbRow): void
61+
{
62+
$this->objects[$tableName][$id] = WeakReference::create($dbRow);
63+
++$this->garbageCollectorCount;
64+
if ($this->garbageCollectorCount === 10000) {
65+
$this->garbageCollectorCount = 0;
66+
$this->cleanupDanglingWeakRefs();
67+
}
68+
}
69+
70+
/**
71+
* Returns an object from the storage (or null if no object is set).
72+
*
73+
* @param string $tableName
74+
* @param string|int $id
75+
*
76+
* @return DbRow|null
77+
*/
78+
public function get(string $tableName, $id) : ?DbRow
79+
{
80+
if (isset($this->objects[$tableName][$id])) {
81+
return $this->objects[$tableName][$id]->get();
82+
}
83+
return null;
84+
}
85+
86+
/**
87+
* Removes an object from the storage.
88+
*
89+
* @param string $tableName
90+
* @param string|int $id
91+
*/
92+
public function remove(string $tableName, $id): void
93+
{
94+
unset($this->objects[$tableName][$id]);
95+
}
96+
97+
private function cleanupDanglingWeakRefs(): void
98+
{
99+
foreach ($this->objects as $tableName => $table) {
100+
foreach ($table as $id => $obj) {
101+
if ($obj->valid() === false) {
102+
unset($this->objects[$tableName][$id]);
103+
}
104+
}
105+
}
106+
}
107+
}

src/TDBMService.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
namespace TheCodingMachine\TDBM;
2323

24+
use function class_exists;
2425
use Doctrine\Common\Cache\Cache;
2526
use Doctrine\Common\Cache\ClearableCache;
2627
use Doctrine\Common\Cache\VoidCache;
@@ -46,7 +47,7 @@
4647
use Psr\Log\LoggerInterface;
4748
use Psr\Log\LogLevel;
4849
use Psr\Log\NullLogger;
49-
use function var_export;
50+
use WeakReference;
5051

5152
/**
5253
* The TDBMService class is the main TDBM class. It provides methods to retrieve TDBMObject instances
@@ -179,7 +180,9 @@ class TDBMService
179180
*/
180181
public function __construct(ConfigurationInterface $configuration)
181182
{
182-
if (extension_loaded('weakref')) {
183+
if (class_exists(WeakReference::class)) {
184+
$this->objectStorage = new NativeWeakrefObjectStorage();
185+
} elseif (extension_loaded('weakref')) {
183186
$this->objectStorage = new WeakrefObjectStorage();
184187
} else {
185188
$this->objectStorage = new StandardObjectStorage();

src/WeakrefObjectStorage.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626
* If a bean is requested twice from TDBM, the WeakrefObjectStorage is used to "cache" the bean.
2727
* Unlike the StandardObjectStorage, the WeakrefObjectStorage manages memory in a clever way, using the weakref
2828
* PHP extension. It is used if the "weakref" extension is available.
29-
* Otherwise, the StandardObjectStorage is used instead.
29+
* Otherwise, the StandardObjectStorage or NativeWeakrefObjectStorage (in PHP 7.4+) is used instead.
30+
*
31+
* Note: the weakref extension is available until PHP 7.2, but not available in PHP 7.3+
3032
*
3133
* @author David Negrier
3234
*/

0 commit comments

Comments
 (0)