codeconsole opened a new pull request, #3190:
URL: https://github.com/apache/groovy/pull/3190
A memoized closure forwards calls to the closure it wraps, which is held in
its `closure` field. `rehydrate` and `dehydrate` were inherited from `Closure`,
so they replaced only the wrapper's own owner, delegate and this object. The
wrapped closure kept the original ones:
```groovy
class O { def foo() { 'o' } }
class P { def foo() { 'p' } }
def c = new O().with { o -> { x -> foo() + x } }
c.rehydrate(null, new P(), new P()).memoize()(1) // 'p1'
c.memoize().rehydrate(null, new P(), new P())(1) // 'o1'
```
The same happens for `memoizeAtMost`, `memoizeAtLeast` and `memoizeBetween`,
in 4.0.33, 5.0.8 and 6.0.0 too. A dehydrated `memoize()` closure could not be
serialized, because the wrapped closure still referenced the owner.
`MemoizeFunction` now overrides `dehydrate` and `rehydrate`. They dehydrate
or rehydrate the wrapped closure and memoize the copy again. The copy gets an
empty cache, since the cached values were computed against the old owner. To
build that cache the same way, the memoized closure keeps the factory its cache
came from: `Closure.memoize*` pass a serializable factory to new
`Memoize.buildMemoizeFunction(Supplier, Closure)` and
`Memoize.buildSoftReferenceMemoizeFunction(int, Supplier, Closure)` overloads.
No existing signature changes. The soft-reference variant also keeps its
protected cache size and gives the copy fresh protection storage and a fresh
reference queue. The existing overloads that take a cache instance cannot build
another one, so their copy shares the supplied cache; their Javadoc says so.
This is the memoize counterpart of #3186 (GROOVY-12665), which does the same
for curried, writable, composed and trampolined closures.
## Tests
These fail without the change:
- in `AbstractMemoizeTestCase`, for all four variants:
`testRehydrateCallsTheRehydratedClosure`, `testRehydrateUsesTheNewDelegate` and
`testDehydrateClearsTheMemoizedClosure`
- in `MemoizeTest`: `testRehydratedCopyKeepsAnUnlimitedCache`,
`testDehydratedCopySerializesAndRehydrates` and
`testCopyOfClosureMemoizedWithSuppliedCacheSharesTheCache`
- `MemoizeAtMostTest.testRehydratedCopyKeepsTheMaximumCacheSize`
- `MemoizeBetweenTest.testRehydratedCopyKeepsTheCacheSizes`
- `MemoizeAtLeastTest.testRehydratedCopyKeepsTheProtectedCacheSize` and
`testCopyOfClosureMemoizedWithSuppliedCacheSharesTheCache`
`org.codehaus.groovy.runtime.memoize.*`, `groovy.lang.*Closure*`,
`groovy.*Closure*`, `groovy.*Memoize*` and `MemoizedASTTransformationTest`
pass. The Checkstyle and CodeNarc gates pass.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]