Skip to content

Commit

Permalink
Fixing lazy sync problem
Browse files Browse the repository at this point in the history
Using properly Double-checked locking pattern for Lazy and
SerializableLazy classes. Additionally, adding more test to
cover the introduced code.
  • Loading branch information
cardil committed Dec 3, 2018
1 parent 67c1ca6 commit e5c8aa9
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 20 deletions.
19 changes: 8 additions & 11 deletions src/main/java/pl/wavesoftware/eid/impl/Lazy.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
* @since 2.0.0
*/
class Lazy<T> implements Supplier<T> {
private Supplier<T> supplier;
private volatile Supplier<T> supplier;
private T value;

Lazy(Supplier<T> supplier) {
Expand All @@ -50,16 +50,13 @@ static <R> Lazy<R> of(R value) {
@Override
public T get() {
if (supplier != null) {
value = doGet();
}
return value;
}

private synchronized T doGet() {
if (supplier != null) {
T calculated = supplier.get();
supplier = null;
return calculated;
synchronized (this) {
if (supplier != null) {
T calculated = supplier.get();
supplier = null;
value = calculated;
}
}
}
return value;
}
Expand Down
15 changes: 6 additions & 9 deletions src/main/java/pl/wavesoftware/eid/impl/SerializableLazy.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ final class SerializableLazy<T extends Serializable>
implements SerializableSupplier<T> {

private static final long serialVersionUID = 20181124011908L;
private T serializable;
private volatile T serializable;

private SerializableLazy(Supplier<T> supplier) {
super(supplier);
Expand All @@ -42,14 +42,11 @@ static <R extends Serializable> SerializableLazy<R> serializableOf(Supplier<R> s
@Override
public T get() {
if (serializable == null) {
serializable = doGetFromParent();
}
return serializable;
}

private synchronized T doGetFromParent() {
if (serializable == null) {
return super.get();
synchronized (this) {
if (serializable == null) {
serializable = super.get();
}
}
}
return serializable;
}
Expand Down
87 changes: 87 additions & 0 deletions src/test/java/pl/wavesoftware/eid/impl/DefaultFormatterTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright (c) 2018 Wave Software
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package pl.wavesoftware.eid.impl;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import pl.wavesoftware.eid.Eid;
import pl.wavesoftware.eid.configuration.Configuration;
import pl.wavesoftware.eid.configuration.ConfigurationBuilder;
import pl.wavesoftware.eid.configuration.Configurator;
import pl.wavesoftware.eid.configuration.Formatter;
import pl.wavesoftware.eid.configuration.UniqueIdGenerator;

import static org.assertj.core.api.Assertions.assertThat;

/**
* @author <a href="mailto:krzysztof.suszynski@wavesoftware.pl">Krzysztof Suszynski</a>
* @since 2018-12-03
*/
public class DefaultFormatterTest {

private Configurator restore;

@Before
public void before() {
restore = Eid.getBinding().getConfigurationSystem().configure(new Configurator() {
@Override
public void configure(ConfigurationBuilder configuration) {
configuration.uniqueIdGenerator(new UniqueIdGenerator() {
@Override
public String generateUniqId() {
return "deadcafe";
}
});
}
});
}

@After
public void after() {
Eid.getBinding().getConfigurationSystem().configure(restore);
}

@Test
public void format() {
// given
Configuration configuration = new ConfigurationImpl();
Formatter formatter = new DefaultFormatter(configuration);

// when
String formatted = formatter.format(new Eid("20181203:224055"));

// then
assertThat(formatted).isEqualTo("[20181203:224055]<deadcafe>");
}

@Test
public void formatWithMessage() {
// given
Configuration configuration = new ConfigurationImpl();
Formatter formatter = new DefaultFormatter(configuration);

// when
String formatted = formatter.format(
new Eid("20181203:224137"),
"a message"
);

// then
assertThat(formatted).isEqualTo("[20181203:224137]<deadcafe> => a message");
}
}
47 changes: 47 additions & 0 deletions src/test/java/pl/wavesoftware/eid/impl/InternalChecksTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2018 Wave Software
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package pl.wavesoftware.eid.impl;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import static org.assertj.core.api.Assertions.*;

/**
* @author <a href="mailto:krzysztof.suszynski@wavesoftware.pl">Krzysztof Suszynski</a>
* @since 2018-12-03
*/
public class InternalChecksTest {

@Rule
public ExpectedException expectedException = ExpectedException.none();

@Test
public void testCheckNotNull() {
// given
String eid = "20181203:223812";
String val = System.getProperty("non-existing-key-in-system");

// then
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage(eid);

// when
InternalChecks.checkNotNull(val, eid);
}
}
44 changes: 44 additions & 0 deletions src/test/java/pl/wavesoftware/eid/impl/MessageSupplierTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2018 Wave Software
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package pl.wavesoftware.eid.impl;

import org.junit.Test;
import pl.wavesoftware.eid.configuration.Configuration;

import static org.assertj.core.api.Assertions.assertThat;

/**
* @author <a href="mailto:krzysztof.suszynski@wavesoftware.pl">Krzysztof Suszynski</a>
* @since 2018-12-03
*/
public class MessageSupplierTest {

@Test
public void testGet() {
// given
Configuration configuration = new ConfigurationImpl();
MessageSupplier supplier = new MessageSupplier(
configuration, "{0} -> 11", new Object[] { ".5" }
);

// when
String message = supplier.get();

// then
assertThat(message).isEqualTo(".5 -> 11");
}
}

0 comments on commit e5c8aa9

Please sign in to comment.