Skip to content
This repository was archived by the owner on Oct 18, 2024. It is now read-only.

Commit 11858d7

Browse files
committed
fix: make ApiVersionsRegistry thread-safe
1 parent 52a6117 commit 11858d7

File tree

2 files changed

+45
-45
lines changed

2 files changed

+45
-45
lines changed

xml/utils/src/main/java/com/itsaky/androidide/xml/internal/versions/DefaultApiVersions.kt

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,15 @@ package com.itsaky.androidide.xml.internal.versions
1919

2020
import com.itsaky.androidide.xml.versions.ApiVersion
2121
import com.itsaky.androidide.xml.versions.ApiVersions
22-
import org.eclipse.jdt.core.Signature
23-
import java.util.concurrent.ConcurrentHashMap
2422

25-
/** @author Akash Yadav */
23+
/**
24+
* This implementation is not thread safe. Do not modify concurrently.
25+
*
26+
* @author Akash Yadav
27+
*/
2628
internal class DefaultApiVersions : ApiVersions {
2729

28-
val classes =
29-
ConcurrentHashMap<String, Pair<ApiVersion?, ConcurrentHashMap<String, ApiVersion>>>()
30+
val classes = HashMap<String, Pair<ApiVersion?, HashMap<String, ApiVersion>>>()
3031

3132
private fun String.flatten() = replace('.', '/')
3233

@@ -57,9 +58,9 @@ internal class DefaultApiVersions : ApiVersions {
5758
private fun computeClass(
5859
name: String,
5960
version: ApiVersion? = null
60-
): Pair<ApiVersion?, ConcurrentHashMap<String, ApiVersion>> {
61+
): Pair<ApiVersion?, HashMap<String, ApiVersion>> {
6162
return classes.computeIfAbsent(name.flatten()) {
62-
version to ConcurrentHashMap()
63+
version to hashMapOf()
6364
}
6465
}
6566
}

xml/utils/src/main/java/com/itsaky/androidide/xml/internal/versions/DefaultApiVersionsRegistry.kt

Lines changed: 37 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import java.util.concurrent.ConcurrentHashMap
3333
*/
3434
@AutoService(ApiVersionsRegistry::class)
3535
@VisibleForTesting
36-
class DefaultApiVersionsRegistry : ApiVersionsParser(), ApiVersionsRegistry {
36+
class DefaultApiVersionsRegistry : ApiVersionsRegistry {
3737

3838
private val versions = ConcurrentHashMap<String, ApiVersions>()
3939

@@ -43,10 +43,6 @@ class DefaultApiVersionsRegistry : ApiVersionsParser(), ApiVersionsRegistry {
4343

4444
override var isLoggingEnabled: Boolean = true
4545

46-
private var _currentApiVersions: DefaultApiVersions? = null
47-
private val currentApiVersions: DefaultApiVersions
48-
get() = checkNotNull(_currentApiVersions)
49-
5046
override fun forPlatformDir(platform: File): ApiVersions? {
5147
var version = versions[platform.path]
5248
if (version != null) {
@@ -69,50 +65,53 @@ class DefaultApiVersionsRegistry : ApiVersionsParser(), ApiVersionsRegistry {
6965
}
7066

7167
return versionsFile.inputStream().buffered().use { inputStream ->
72-
check(_currentApiVersions == null)
73-
_currentApiVersions = DefaultApiVersions()
74-
parse(inputStream)
75-
currentApiVersions.also {
76-
_currentApiVersions = null
77-
}
68+
// we do not implement the parsing logic in the registry itself for thread safety
69+
val versions = DefaultApiVersions()
70+
val parser = ApiVersionsParserInternal(versions)
71+
parser.parse(inputStream)
72+
versions
7873
}
7974
}
8075

81-
override fun isDuplicateClass(name: String): Boolean {
82-
return currentApiVersions.containsClass(name)
83-
}
84-
85-
override fun isDuplicateMember(className: String, memberName: String): Boolean {
86-
return currentApiVersions.containsClassMember(className, memberName)
76+
override fun clear() {
77+
versions.clear()
8778
}
8879

89-
override fun consumeClassVersionInfo(name: String, apiVersion: ApiVersion) {
90-
if (apiVersion.isSinceInception()) {
91-
return
80+
private class ApiVersionsParserInternal(
81+
private val currentApiVersions: DefaultApiVersions
82+
) : ApiVersionsParser() {
83+
override fun isDuplicateClass(name: String): Boolean {
84+
return currentApiVersions.containsClass(name)
9285
}
93-
currentApiVersions.putClass(name, apiVersion)
94-
}
9586

96-
override fun consumeMemberVersionInfo(
97-
className: String,
98-
member: String,
99-
memberType: String,
100-
apiVersion: ApiVersion
101-
) {
102-
if (apiVersion.isSinceInception()) {
103-
return
87+
override fun isDuplicateMember(className: String, memberName: String): Boolean {
88+
return currentApiVersions.containsClassMember(className, memberName)
10489
}
10590

106-
var identifier = member
107-
if (memberType == TAG_METHOD) {
108-
// strip return type to save some memory
109-
identifier = member.substring(0, member.lastIndexOf(')') + 1)
91+
override fun consumeClassVersionInfo(name: String, apiVersion: ApiVersion) {
92+
if (apiVersion.isSinceInception()) {
93+
return
94+
}
95+
currentApiVersions.putClass(name, apiVersion)
11096
}
11197

112-
currentApiVersions.putMember(className, identifier, apiVersion)
113-
}
98+
override fun consumeMemberVersionInfo(
99+
className: String,
100+
member: String,
101+
memberType: String,
102+
apiVersion: ApiVersion
103+
) {
104+
if (apiVersion.isSinceInception()) {
105+
return
106+
}
114107

115-
override fun clear() {
116-
versions.clear()
108+
var identifier = member
109+
if (memberType == TAG_METHOD) {
110+
// strip return type to save some memory
111+
identifier = member.substring(0, member.lastIndexOf(')') + 1)
112+
}
113+
114+
currentApiVersions.putMember(className, identifier, apiVersion)
115+
}
117116
}
118117
}

0 commit comments

Comments
 (0)