One point - the Javadoc for the method on ZoneRulesProvider

@return a modifiable copy of the set of zone IDs, not null

needs to change to

@return the unmodifiable set of zone IDs, not null

I'd welcome a second review on the volatile / thread-safety aspects,
although I think it is pretty simple and safe.

Stephen


On 9 May 2016 at 11:58, Bhanu Gopularam
<bhanu.prakash.gopula...@oracle.com> wrote:
> Hi all,
>
> Here is the updated webrev:
>
> http://cr.openjdk.java.net/~bgopularam/bhanu/JDK-8066291/webrev.02/
>
> I have included newly suggested changes. On test side, I had to cleanup test 
> java/time/zone/TCKZoneRulesProvider.java (test_getAvailableGroupIds) as 
> ZoneRulesProvider.getAvailableZoneIds() returns a non-modifiable list, the 
> tests for ZoneId.getAvailableZoneIds() is present in 
> java/time/tck/java/time/TCKZoneId.java ().
>
> Thanks,
> Bhanu
>
> -----Original Message-----
> From: Stephen Colebourne [mailto:scolebou...@joda.org]
> Sent: Friday, May 06, 2016 3:54 PM
> To: core-libs-dev
> Subject: Re: RFR 8066291: ZoneIdPrinterParser can be optimized
>
> The set of zones can only increase, it cannot decrease as there is no removal 
> mechanism. As such, the size of the set is a proxy for the number you 
> describe.
>
> One other point. The method that most users will call to get the set of 
> ZoneIds is ZoneId.getAvailableZoneIds(). That method delegates to the one on 
> ZoneRulesProvider. As such, we can change the method on ZoneRulesProvider to 
> return an immutable set while still keeping the method commonly used by users 
> returning a mutable set. The incompatibility impact caused by this would be 
> vanishingly small. To me, this is by far the best way to address this 
> problem, as it avoids a new method.
>
> Thus, I propose:
>
> 1) Add a new field private static volatile Set<String> ZONE_IDS;
>
> 2) Synchronize/lock registerProvider0() to ensure only one thread is in there 
> at a time.
>
> 3) At the end of registerProvider0() add all of the existing and new IDs to a 
> new HashSet wrapped in
> Collections.unmodifiableSet(combinedSet) and change ZONE_IDS to point at the 
> new set.
>
> 4) Change ZoneRulesProvider.getAvailableZoneIds() to return ZONE_IDS.
> Change the spec to indicate the result is unmodifiable.
>
> 5) Change ZoneId.getAvailableZoneIds() to return new
> HashSet(ZoneRulesProvider.getAvailableZoneIds())
>
> Code changes:
>
> ZoneId:
>
> public static Set<String> getAvailableZoneIds() {
>   return new HashSet(ZoneRulesProvider.getAvailableZoneIds());
> }
>
>
> ZoneRulesProvider:
>
> private static volatile Set<String> ZONE_IDS;
>
> @return the unmodifiable set of zone IDs, not null public static Set<String> 
> getAvailableZoneIds() {
>   return ZONE_IDS;
> }
>
> private static synchronized void registerProvider0(ZoneRulesProvider 
> provider) {
>   for (String zoneId : provider.provideZoneIds()) {
>     Objects.requireNonNull(zoneId, "zoneId");
>     ZoneRulesProvider old = ZONES.putIfAbsent(zoneId, provider);
>     if (old != null) {
>       throw new ZoneRulesException(
>         "Unable to register zone as one already registered with that
> ID: " + zoneId +
>         ", currently loading from provider: " + provider);
>     }
>   }
>   Set<String> combinedSet = new HashSet(ZONES.keySet());
>   ZONE_IDS = Collections.unmodifiableSet(combinedSet);
> }
>
> Stephen
>
>
> On 5 May 2016 at 19:48, Roger Riggs <roger.ri...@oracle.com> wrote:
>> Hi,
>>
>> Using the current number of ZoneIDs to avoid the recompilation of the
>> cache is a bit weak anyway, though it seems unlikely that a ZoneID
>> would be added and one deleted without being noticed.
>>
>> An alternative would be a API that returned a number that would change
>> every time the set of ZoneIds changed.
>> That would be more suitable both as a new API and as something to
>> trigger updates to the cache.
>>
>> I'd rather see a localized implementation with a simple model.
>>
>> Roger
>>
>>
>> On 5/5/2016 1:43 PM, Stephen Colebourne wrote:
>>>
>>> On reflection, both your and my solution have a race.
>>>
>>> the size method, is a clear check-then-act
>>>
>>> the read-only method uses Collections.unmodifiableSet() which only
>>> decorates the underlying set, thus is still check-thern-act
>>>
>>> (the current implementation does not have a race condition, as the
>>> data is copied, thus the size will match the data)
>>>
>>> There is no pleasant way to solve this that I can see. This is my
>>> best
>>> attempt:
>>>
>>> 1) Add a new field
>>>
>>> private static final CopyOnWriteArrayList<String> ZONE_IDS;
>>>
>>> 2) At the end of registerProvider0() add all of the new IDs to the
>>> list (must be outside the loop as otherwise CopyOnWriteArrayList will
>>> be slow)
>>>
>>> 3) Add a new method getAvailableZoneIdList() that returns the list
>>> wrapped in Collections.unmodifiableList()
>>>
>>> 4) In the calling code, query the size, and then use subList(0, size)
>>> to lock the size from race conditions.
>>>
>>>
>>> A variation would be
>>>
>>> 1) Add a new field
>>>
>>> private static volatile Set<String> ZONE_IDS;
>>>
>>> 2) Synchronize/lock registerProvider0() to ensure only one thread is
>>> in there at a time.
>>>
>>> 3) At the end of registerProvider0() add all of the new IDs to the
>>> set, storing Collections.unmodifiableSet(combinedSet)
>>>
>>> 4) Add a new method getAvailableZoneIdSet() that returns the
>>> unmodifiable set
>>>
>>> 5) Change the calling code to use the new method, but no other
>>> changes
>>>
>>>
>>> Stephen
>>>
>>>
>>> On 5 May 2016 at 16:53, Roger Riggs <roger.ri...@oracle.com> wrote:
>>>>
>>>> Hi Stephen,
>>>>
>>>> The aspect of the current implementation that is problematic is the
>>>> copying of the set, its not just single object creation but an entry
>>>> for every ZoneID.
>>>>
>>>> Adding a size method exposing some internal state increases the
>>>> possibility that when it is used independently it will be out of
>>>> sync.  Not a big issue, but one to avoid when designing an API.
>>>>
>>>> Exposing a mutable Hashset was probably a mistake but one that
>>>> cannot be corrected now.  The optics aren't concerning to me.
>>>>
>>>> SharedSecrets are much messier and not appropriate.
>>>>
>>>> Adding a method to provide what was originally needed is a cleaner
>>>> solution.
>>>>
>>>> Roger
>>>>
>>>>
>>>>
>>>>
>>>> On 5/5/2016 11:27 AM, Stephen Colebourne wrote:
>>>>>
>>>>> I fail to see why adding a new read-only method alongside the
>>>>> existing method adds any more value to the API than adding a new size 
>>>>> method.
>>>>> At least with the size method the API is still sensible - a mutable
>>>>> and immutable method alongside each other shouts out that a mistake
>>>>> was made. A size method is more subtle about the mistake (plenty of
>>>>> APIs have a size method alongside a collection method).
>>>>>
>>>>> Finally, a read-only method involves object creation, thus has
>>>>> worse performance than adding a size method.
>>>>>
>>>>> The only other alternative is perhaps to use SharedSecrets? I don't
>>>>> know what possibilities there are there. If not SharedSecrets, then
>>>>> no matter what, we are adding "a trivial method to the public API
>>>>> used only for an optimization".
>>>>>
>>>>> Stephen
>>>>>
>>>>>
>>>>> On 5 May 2016 at 15:23, Roger Riggs <roger.ri...@oracle.com> wrote:
>>>>>>
>>>>>> Hi Bhanu,
>>>>>>
>>>>>> Adding a trivial method to the public API used only for an
>>>>>> optimization is not a good fix for this issue.
>>>>>>
>>>>>> A better fix was suggested to add a non-copying read-only version
>>>>>> of
>>>>>>
>>>>>> ZoneRulesProvider.getAvailableZoneIds()
>>>>>>
>>>>>> Please revise the fix to instead implement and use:
>>>>>>
>>>>>>     /**
>>>>>>        * Gets a readonly set of available zone IDs.
>>>>>>        * <p>
>>>>>>        * These IDs are the string form of a {@link ZoneId}.
>>>>>>        *
>>>>>>        * @return a unmodifiable copy of the set of zone IDs, not null
>>>>>>        */
>>>>>>       public static Set<String> getReadOnlyAvailableZoneIds() {
>>>>>>           return Collections.unmodifiableSet(ZONES.keySet());
>>>>>>       }
>>>>>>
>>>>>> Roger
>>>>>>
>>>>>>
>>>>>>
>>>>>> On 5/5/2016 5:10 AM, Bhanu Gopularam wrote:
>>>>>>
>>>>>> Hi all,
>>>>>>
>>>>>>
>>>>>>
>>>>>> Please review fix following issue
>>>>>>
>>>>>>
>>>>>>
>>>>>> Bug Id : https://bugs.openjdk.java.net/browse/JDK-8066291
>>>>>>
>>>>>>
>>>>>>
>>>>>> Solution: provided new method to get size of available zone ids
>>>>>>
>>>>>>
>>>>>>
>>>>>> webrev :
>>>>>> http://cr.openjdk.java.net/~bgopularam/bhanu/JDK-8066291/webrev.00
>>>>>>
>>>>>>
>>>>>>
>>>>>> Thanks,
>>>>>>
>>>>>> Bhanu
>>>>>>
>>>>>>
>>

Reply via email to