Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace synchronized blocks in retrofit2 with ReentrantLock(Improve) #5911

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

ChangguHan
Copy link
Contributor

Motivation:

Modifications:

  • remove synchronized in ArmeriaCallFactory's createRequest() by using CAS
  • Add comments related to buffer's synchronized blocks.

Result:

  • Remove synchronized block in retrofit2, but still have one issue with PipeBuffer(needed okhttp4)
}

// Run atomically
if (executionStateUpdater.compareAndSet(this, ExecutionState.IDLE, ExecutionState.RUNNING)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to make the use of CAS instead of using Reentrant Lock.
So, when the compare failed, enqueue returns with failure callback.

@@ -36,6 +36,11 @@ void write(byte[] source, int offset, int byteCount) {
if (byteCount == 0) {
return;
}
/*
* Once use okhttp4, the synchronized block could be replaced by Reentrant and Condition for Virtual Thread support.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any plan to use okhttp4?
If that is not too far in the future, I hope to work in this PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's probably best to follow the okhttp version upstream is using which seems to be okhttp3 unless there is a significant benefit.
https://github.com/square/retrofit/blob/trunk/gradle/libs.versions.toml#L17

On a side note, does the okio side PR contain changes for APIs which Armeria is using? I'm asking because okhttp itself is an http engine and usage within Armeria is minimal.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The okio side replace synchronized with using lock, condition, timeout.awaitSignal, condition.signalAll() at here.

Especially, the way to notify to monitor(here) is replaced with
timeout.awaitSignal.
But we cannot use timeout.awaitSignal unless we upgrade the version of okio.

Copy link
Contributor

@jrhee17 jrhee17 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a small nit but looks good 👍

if (executionStateUpdater.compareAndSet(this, ExecutionState.IDLE, ExecutionState.RUNNING)) {
httpResponse = doCall(callFactory, request);
} else {
callback.onFailure(this, new IOException("Call state is not IDLE"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since entering this block is semantically equivalent to L190

Suggested change
callback.onFailure(this, new IOException("Call state is not IDLE"));
throw new IllegalStateException("executed already");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jrhee17
This block is for when httpResponse is null and executionState is not ExecutionState.IDLE.
When the call is cancelled, the state is ExecutionState.CANCELED

@@ -36,6 +36,11 @@ void write(byte[] source, int offset, int byteCount) {
if (byteCount == 0) {
return;
}
/*
* Once use okhttp4, the synchronized block could be replaced by Reentrant and Condition for Virtual Thread support.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's probably best to follow the okhttp version upstream is using which seems to be okhttp3 unless there is a significant benefit.
https://github.com/square/retrofit/blob/trunk/gradle/libs.versions.toml#L17

On a side note, does the okio side PR contain changes for APIs which Armeria is using? I'm asking because okhttp itself is an http engine and usage within Armeria is minimal.

@github-actions github-actions bot added the Stale label Nov 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2 participants