Skip to content

Commit 883ce7b

Browse files
authored
Merge pull request jruby#9300 from headius/replace_wait_timeout
Replace now-deprecated wait_timeout
2 parents 9a90bf7 + 24f8918 commit 883ce7b

1 file changed

Lines changed: 94 additions & 15 deletions

File tree

core/src/main/java/org/jruby/RubyThread.java

Lines changed: 94 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ public class RubyThread extends RubyObject implements ExecutionContext {
187187
/** Thread-local tuple used for sleeping (semaphore, millis, nanos) */
188188
private final SleepTask2 sleepTask = new SleepTask2();
189189

190+
/** Thread-local tuple used for waiting (object, millis, nanos) */
191+
private final WaitTask waitTask = new WaitTask();
192+
190193
/** Whether this is an "adopted" thread not created by Ruby code */
191194
private final boolean adopted;
192195

@@ -1674,6 +1677,67 @@ public boolean sleep(long milliseconds, long nanoseconds) throws InterruptedExce
16741677
}
16751678
}
16761679

1680+
/**
1681+
* Wait for the object's monitor the specified number of seconds, or forever if seconds is zero.
1682+
*
1683+
* @param o the object to wait for
1684+
* @param seconds the number of seconds to wait, as a double
1685+
* @return whether the wait took at least the specified amount of time, or true if the time specified was zero
1686+
* @throws InterruptedException
1687+
*/
1688+
public boolean waitForObject(Object o, double seconds) throws InterruptedException {
1689+
if (seconds > 0.0) {
1690+
long delay_ns = (long)(seconds * 1000000000.0);
1691+
int delay_ns_remainder = (int)( delay_ns % 1000000 );
1692+
long delay_ms = delay_ns / 1000000;
1693+
return waitForObject(o, delay_ms, delay_ns_remainder);
1694+
} else {
1695+
waitForObject(o);
1696+
return true;
1697+
}
1698+
}
1699+
1700+
/**
1701+
* Wait for the object's monitor until woken up or notified.
1702+
*
1703+
* Equivalent to calling {@link RubyThread#waitForObject(Object, long, int)} with 0 for millis and nanos.
1704+
*
1705+
* @param o the object to wait for
1706+
* @throws InterruptedException
1707+
*/
1708+
public void waitForObject(Object o) throws InterruptedException {
1709+
waitTask.millis = 0;
1710+
waitTask.nanos = 0;
1711+
executeTaskBlocking(getContext(), o, waitTask);
1712+
}
1713+
1714+
/**
1715+
* Wait for the object's monitor the specified number of milliseconds and nanoseconds, or forever if they are zero.
1716+
*
1717+
* @param o the object to wait for
1718+
* @param millis the number of milliseconds to wait
1719+
* @param nanos the number of nanoseconds to wait
1720+
* @return whether the wait took at least the specified amount of time, or true if the time specified was zero
1721+
* @throws InterruptedException
1722+
*/
1723+
public boolean waitForObject(Object o, long millis, int nanos) throws InterruptedException {
1724+
long totalNanos = millis * 1000000 + nanos;
1725+
if (totalNanos == 0) {
1726+
waitForObject(o);
1727+
return true;
1728+
}
1729+
1730+
long start_ns = System.nanoTime();
1731+
if (totalNanos > 0) {
1732+
waitTask.millis = millis;
1733+
waitTask.nanos = nanos;
1734+
executeTaskBlocking(getContext(), o, waitTask);
1735+
}
1736+
long end_ns = System.nanoTime();
1737+
1738+
return (end_ns - start_ns) <= totalNanos;
1739+
}
1740+
16771741
public IRubyObject status() { // not used
16781742
return status(getRuntime().getCurrentContext());
16791743
}
@@ -1801,6 +1865,32 @@ public void wakeup(RubyThread thread, Object data) {
18011865
}
18021866
}
18031867

1868+
/**
1869+
* A Task for waiting on an object's monitor.
1870+
*/
1871+
private static class WaitTask implements Task<Object, Long> {
1872+
long millis;
1873+
int nanos;
1874+
1875+
@Override
1876+
public Long run(ThreadContext context, Object data) throws InterruptedException {
1877+
long start = System.nanoTime();
1878+
1879+
synchronized (data) {
1880+
data.wait(millis, nanos);
1881+
}
1882+
1883+
return System.nanoTime() - start;
1884+
}
1885+
1886+
@Override
1887+
public void wakeup(RubyThread thread, Object data) {
1888+
synchronized (data) {
1889+
data.notify();
1890+
}
1891+
}
1892+
}
1893+
18041894
@Deprecated(since = "9.0.0.0")
18051895
public void executeBlockingTask(BlockingTask task) throws InterruptedException {
18061896
try {
@@ -2459,23 +2549,12 @@ public void afterBlockingCall() {
24592549
pollThreadEvents();
24602550
}
24612551

2462-
// Deprecated but still used by concurrent_ruby
2552+
/**
2553+
* @deprecated use {@link RubyThread#waitForObject(Object, double)} and siblings
2554+
*/
24632555
@Deprecated(since = "10.1.0.0")
24642556
public boolean wait_timeout(IRubyObject o, Double timeout) throws InterruptedException {
2465-
if ( timeout != null ) {
2466-
long delay_ns = (long)(timeout.doubleValue() * 1000000000.0);
2467-
long start_ns = System.nanoTime();
2468-
if (delay_ns > 0) {
2469-
long delay_ms = delay_ns / 1000000;
2470-
int delay_ns_remainder = (int)( delay_ns % 1000000 );
2471-
executeBlockingTask(new SleepTask(o, delay_ms, delay_ns_remainder));
2472-
}
2473-
long end_ns = System.nanoTime();
2474-
return ( end_ns - start_ns ) <= delay_ns;
2475-
} else {
2476-
executeBlockingTask(new SleepTask(o, 0, 0));
2477-
return true;
2478-
}
2557+
return waitForObject(o, timeout == null ? 0 : timeout.doubleValue());
24792558
}
24802559

24812560
public RubyThreadGroup getThreadGroup() {

0 commit comments

Comments
 (0)