Skip to content

Commit 8dff082

Browse files
committed
Made lazy instantiation of Client safer. shannah#25
1 parent 0130306 commit 8dff082

File tree

1 file changed

+42
-17
lines changed

1 file changed

+42
-17
lines changed

src/main/java/ca/weblite/objc/Client.java

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,26 +35,42 @@ public class Client {
3535
* Reference to the default client instance with type coercion enabled
3636
* for both inputs and outputs.
3737
*/
38-
private static Client instance;
38+
private static volatile Client instance;
39+
40+
private Client(boolean coerceInputs, boolean coerceOutputs) {
41+
this.coerceInputs = coerceInputs;
42+
this.coerceOutputs = coerceOutputs;
43+
}
44+
45+
private Client() {
46+
this(true, true);
47+
}
3948

4049
/**
4150
* Retrieves the global reference to a client that has both input coercion
4251
* and output coercion enabled.
4352
*
4453
* @return Singleton instance.
4554
*/
46-
public static Client getInstance(){
47-
if ( instance == null ){
48-
instance = new Client();
55+
public static Client getInstance() {
56+
Client localInstance = instance;
57+
if (localInstance == null) {
58+
// Could also use dedicated lock for `instance` and `rawClient`, but likely not worth it
59+
synchronized (Client.class) {
60+
localInstance = instance;
61+
if (localInstance == null) {
62+
instance = localInstance = new Client();
63+
}
64+
}
4965
}
50-
return instance;
66+
return localInstance;
5167
}
5268

5369
/**
5470
* Reference to a simple client that has type coercion disabled for both
5571
* inputs and outputs.
5672
*/
57-
private static Client rawClient;
73+
private static volatile Client rawClient;
5874

5975
/**
6076
* Retrieves singleton instance to a simple client that has type coercion
@@ -63,12 +79,19 @@ public static Client getInstance(){
6379
* @return a {@link ca.weblite.objc.Client} object.
6480
*/
6581
public static Client getRawClient(){
66-
if ( rawClient == null ){
67-
rawClient = new Client();
68-
rawClient.coerceInputs = false;
69-
rawClient.coerceOutputs = false;
82+
Client localInstance = rawClient;
83+
84+
if (localInstance == null ){
85+
synchronized(Client.class) {
86+
localInstance = rawClient;
87+
if (localInstance == null) {
88+
localInstance = new Client(false, false);
89+
rawClient = localInstance;
90+
}
91+
}
92+
7093
}
71-
return rawClient;
94+
return localInstance;
7295
}
7396

7497
/**
@@ -78,30 +101,32 @@ public static Client getRawClient(){
78101
* TypeMapping subclasses.
79102
*
80103
*/
81-
boolean coerceInputs=true;
104+
final boolean coerceInputs;
82105

83106
/**
84107
* Flag to indicate whether the output of messages should be coerced. If
85108
* this flag is true, then any C outputs from messages will be converted
86109
* to their corresponding Java types using the TypeMapper class.
87110
*/
88-
boolean coerceOutputs=true;
111+
final boolean coerceOutputs;
89112

90113

91114

92115
/**
93116
* Set the coerceInputs flag. Setting this to true will cause all subsequent
94117
* requests to coerce the input (i.e. convert Java parameters to corresponding
95118
* C-types).
119+
*
96120
*
97121
* @param coerceInputs Whether to coerce inputs to messages.
98122
* @return Self for chaining.
99123
* @see TypeMapper
100124
* @see TypeMapping
125+
* @Deprecated Use {@link #getRawClient() } to get a client with coercion off. Use {@link #getInstance() } to get a client with coercion on.
101126
*/
102127
public Client setCoerceInputs(boolean coerceInputs){
103-
this.coerceInputs = coerceInputs;
104-
return this;
128+
throw new UnsupportedOperationException("Cannot modify coerce inputs setting on shared global instance of Objective-C client");
129+
105130
}
106131

107132
/**
@@ -113,10 +138,10 @@ public Client setCoerceInputs(boolean coerceInputs){
113138
* @return Self for chaining.
114139
* @see TypeMapper
115140
* @see TypeMapping
141+
* @Deprecated Use {@link #getRawClient() } to get a client with coercion off. Use {@link #getInstance() } to get a client with coercion on.
116142
*/
117143
public Client setCoerceOutputs(boolean coerceOutputs){
118-
this.coerceOutputs = coerceOutputs;
119-
return this;
144+
throw new UnsupportedOperationException("Cannot modify coerce inputs setting on shared global instance of Objective-C client");
120145
}
121146

122147

0 commit comments

Comments
 (0)