codeconsole opened a new pull request, #3195:
URL: https://github.com/apache/groovy/pull/3195
`Closure` is `Serializable`, and a `memoize()` closure whose wrapped closure
has no non-serializable owner serializes. The other memoize variants never did:
```groovy
def base = { x -> x * 2 }.dehydrate()
roundTrip(base.memoize()) // works
roundTrip(base.memoizeAtMost(2)) // NotSerializableException: LRUCache
roundTrip(base.memoizeAtLeast(0)) // NotSerializableException:
NullProtectionStorage
roundTrip(base.memoizeAtLeast(2)) // NotSerializableException:
ReferenceQueue (SoftReference once called)
```
Seen in 4.0.33, 5.0.8 and 6.0.0 too.
`LRUCache` is now `Serializable`. Its `ConcurrentLinkedHashMap` already
serializes its capacity and entries, so `memoizeAtMost` keeps its cached values
and maximum size, like `memoize()` does.
The soft reference variants keep their protected cache size and rebuild the
protection storage and reference queue, now transient, when deserialized. Their
cached values are soft references, which cannot be serialized and may be
cleared by the garbage collector at any time; they now serialize as cleared
references, which the deserialized closure removes with
`cleanUpNullReferences`. So `memoizeAtLeast` and `memoizeBetween` are
deserialized with an empty cache with the same limits. This works for any
serializable `MemoizeCache` passed to
`Memoize.buildSoftReferenceMemoizeFunction`. No public signature changes.
Merging with #3190 (GROOVY-12669): `Closure.java` (Javadoc),
`AbstractMemoizeTestCase` (appended tests) and
`Memoize.SoftReferenceMemoizeFunction` conflict textually. Keep #3190's
constructors and `cacheFactory`, make `lruProtectionStorage` and `queue`
transient and non-final as here, have #3190's public constructor initialise
them through `initTransientFields()`, and keep this change's `readObject` and
reference classes. With both in, a memoized closure that is dehydrated
afterwards also serializes.
## Tests
`testSerializedCopyStillMemoizes` and
`testSerializedCopyOfDehydratedClosure` in `AbstractMemoizeTestCase` (all four
variants),
`MemoizeAtMostTest.testSerializedCopyKeepsCachedValuesAndMaxCacheSize`,
`MemoizeAtLeastTest.testSerializedCopyDropsCachedValues` and
`testSerializedCopyKeepsProtectedCacheSize`,
`MemoizeBetweenTest.testSerializedCopyDropsCachedValuesAndKeepsLimits`, and
`ClosureSerializationCycleTest.testLegitimateSoftReferenceMemoizedClosureRoundTrips`
fail without the change.
`ClosureSerializationCycleTest.serializeCyclicSoftMemoized` no longer has to
clear the unserializable fields to build its gadget stream. The
`org.codehaus.groovy.runtime.memoize`, `groovy.*Closure*` and
`groovy.*Memoize*` tests 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]