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]

Reply via email to