Skip to content

Commit 4e32099

Browse files
committed
LockType and RLock builtins are in
- using a Semaphore for regular locks and ReentrantLock for RLocks - threading module can be imported
1 parent 25764b9 commit 4e32099

File tree

10 files changed

+459
-33
lines changed

10 files changed

+459
-33
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@
137137
import com.oracle.graal.python.builtins.objects.str.StringBuiltins;
138138
import com.oracle.graal.python.builtins.objects.superobject.SuperBuiltins;
139139
import com.oracle.graal.python.builtins.objects.thread.LockBuiltins;
140+
import com.oracle.graal.python.builtins.objects.thread.RLockBuiltins;
140141
import com.oracle.graal.python.builtins.objects.thread.ThreadBuiltins;
141142
import com.oracle.graal.python.builtins.objects.traceback.TracebackBuiltins;
142143
import com.oracle.graal.python.builtins.objects.tuple.TupleBuiltins;
@@ -291,6 +292,7 @@ private static final PythonBuiltins[] initializeBuiltins() {
291292
new ThreadModuleBuiltins(),
292293
new ThreadBuiltins(),
293294
new LockBuiltins(),
295+
new RLockBuiltins(),
294296
new SuperBuiltins(),
295297
new BinasciiModuleBuiltins(),
296298
new PosixSubprocessModuleBuiltins(),

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ public enum PythonBuiltinClassType implements LazyPythonClass {
8888
PBuffer("buffer", "builtins"),
8989
PThread("thread", "_thread"),
9090
PLock("lock", "_thread"),
91+
PRLock("rlock", "_thread"),
9192
PSocket("socket", "_socket"),
9293

9394
// Errors and exceptions:

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ThreadModuleBuiltins.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import com.oracle.graal.python.builtins.PythonBuiltins;
5151
import com.oracle.graal.python.builtins.objects.PNone;
5252
import com.oracle.graal.python.builtins.objects.thread.PLock;
53+
import com.oracle.graal.python.builtins.objects.thread.PRLock;
5354
import com.oracle.graal.python.builtins.objects.thread.PThread;
5455
import com.oracle.graal.python.builtins.objects.type.PythonClass;
5556
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
@@ -71,15 +72,24 @@ protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFa
7172
return ThreadModuleBuiltinsFactory.getFactories();
7273
}
7374

74-
@Builtin(name = "allocate_lock", fixedNumOfPositionalArgs = 1, constructsClass = PythonBuiltinClassType.PLock)
75+
@Builtin(name = "LockType", fixedNumOfPositionalArgs = 1, constructsClass = PythonBuiltinClassType.PLock)
7576
@GenerateNodeFactory
76-
abstract static class AllocateLockNode extends PythonUnaryBuiltinNode {
77+
abstract static class ConstructLockNode extends PythonUnaryBuiltinNode {
7778
@Specialization
78-
PLock allocate(PythonClass cls) {
79+
PLock construct(PythonClass cls) {
7980
return factory().createLock(cls);
8081
}
8182
}
8283

84+
@Builtin(name = "RLock", fixedNumOfPositionalArgs = 1, constructsClass = PythonBuiltinClassType.PRLock)
85+
@GenerateNodeFactory
86+
abstract static class ConstructRLockNode extends PythonUnaryBuiltinNode {
87+
@Specialization
88+
PRLock construct(PythonClass cls) {
89+
return factory().createRLock(cls);
90+
}
91+
}
92+
8393
@Builtin(name = "get_ident", fixedNumOfPositionalArgs = 0)
8494
@GenerateNodeFactory
8595
abstract static class GetCurrentThreadIdNode extends PythonBuiltinNode {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.graal.python.builtins.objects.thread;
42+
43+
import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject;
44+
import com.oracle.graal.python.builtins.objects.type.PythonClass;
45+
46+
public abstract class AbstractPythonLock extends PythonBuiltinObject {
47+
48+
AbstractPythonLock(PythonClass cls) {
49+
super(cls);
50+
}
51+
52+
private long getTimeoutInMillis(double timeout) {
53+
// TODO: look at
54+
// https://github.com/python/cpython/blob/e42b705188271da108de42b55d9344642170aa2b/Python/pytime.c
55+
// _PyTime_AsMicroseconds
56+
long seconds = (long) timeout;
57+
long milli = (long) ((timeout - seconds) * 1000);
58+
return seconds * 1000 + milli;
59+
}
60+
61+
abstract boolean tryToAcquire();
62+
63+
abstract boolean blockUntilAcquire() throws InterruptedException;
64+
65+
abstract boolean acquireTimeout(long timeout) throws InterruptedException;
66+
67+
boolean acquire() {
68+
try {
69+
return blockUntilAcquire();
70+
} catch (InterruptedException e) {
71+
return false;
72+
}
73+
}
74+
75+
boolean acquire(int waitFlag, double timeout) {
76+
if (waitFlag == 0) {
77+
return tryToAcquire();
78+
} else {
79+
try {
80+
if (timeout < 0) {
81+
return blockUntilAcquire();
82+
} else {
83+
return acquireTimeout(getTimeoutInMillis(timeout));
84+
}
85+
} catch (InterruptedException e) {
86+
return false;
87+
}
88+
}
89+
}
90+
91+
public abstract void release();
92+
93+
public abstract boolean locked();
94+
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/thread/LockBuiltins.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242

4343
import static com.oracle.graal.python.nodes.SpecialMethodNames.__ENTER__;
4444
import static com.oracle.graal.python.nodes.SpecialMethodNames.__EXIT__;
45+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__REPR__;
4546

4647
import java.util.List;
4748

@@ -150,4 +151,17 @@ boolean isLocked(PLock self) {
150151
return self.locked();
151152
}
152153
}
154+
155+
@Builtin(name = __REPR__, fixedNumOfPositionalArgs = 1)
156+
@GenerateNodeFactory
157+
abstract static class ReprLockNode extends PythonUnaryBuiltinNode {
158+
@Specialization
159+
@TruffleBoundary
160+
String repr(PLock self) {
161+
return String.format("<%s %s object at %s>",
162+
(self.locked()) ? "locked" : "unlocked",
163+
self.getPythonClass(),
164+
self.hashCode());
165+
}
166+
}
153167
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/thread/PLock.java

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -40,47 +40,42 @@
4040
*/
4141
package com.oracle.graal.python.builtins.objects.thread;
4242

43+
import java.util.concurrent.Semaphore;
4344
import java.util.concurrent.TimeUnit;
44-
import java.util.concurrent.locks.ReentrantLock;
4545

46-
import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject;
4746
import com.oracle.graal.python.builtins.objects.type.PythonClass;
4847

49-
public class PLock extends PythonBuiltinObject {
50-
private final ReentrantLock lock;
48+
public class PLock extends AbstractPythonLock {
49+
private final Semaphore semaphore;
5150

5251
public PLock(PythonClass cls) {
5352
super(cls);
54-
lock = new ReentrantLock();
53+
semaphore = new Semaphore(1);
5554
}
5655

57-
public boolean acquire(int waitFlag, double timeout) {
58-
if (waitFlag == 0) {
59-
return lock.tryLock();
60-
} else {
61-
if (timeout < 0) {
62-
lock.lock();
63-
return true;
64-
} else {
65-
// TODO: look at
66-
// https://github.com/python/cpython/blob/e42b705188271da108de42b55d9344642170aa2b/Python/pytime.c
67-
// _PyTime_AsMicroseconds
68-
long seconds = (long) timeout;
69-
long milli = (long) ((timeout - seconds) * 1000);
70-
try {
71-
return lock.tryLock(seconds * 1000 + milli, TimeUnit.MILLISECONDS);
72-
} catch (InterruptedException e) {
73-
return false;
74-
}
75-
}
76-
}
56+
@Override
57+
boolean tryToAcquire() {
58+
return semaphore.tryAcquire();
7759
}
7860

61+
@Override
62+
boolean blockUntilAcquire() throws InterruptedException {
63+
semaphore.acquire();
64+
return true;
65+
}
66+
67+
@Override
68+
boolean acquireTimeout(long timeout) throws InterruptedException {
69+
return semaphore.tryAcquire(timeout, TimeUnit.MILLISECONDS);
70+
}
71+
72+
@Override
7973
public void release() {
80-
lock.unlock();
74+
semaphore.release();
8175
}
8276

77+
@Override
8378
public boolean locked() {
84-
return lock.isLocked();
79+
return semaphore.availablePermits() == 0;
8580
}
8681
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.graal.python.builtins.objects.thread;
42+
43+
import java.util.concurrent.TimeUnit;
44+
import java.util.concurrent.locks.ReentrantLock;
45+
46+
import com.oracle.graal.python.builtins.objects.type.PythonClass;
47+
48+
public class PRLock extends AbstractPythonLock {
49+
private class InternalReentrantLock extends ReentrantLock {
50+
private static final long serialVersionUID = 2531000884985514112L;
51+
52+
long getOwnerId() {
53+
Thread owner = getOwner();
54+
if (owner != null) {
55+
return owner.getId();
56+
}
57+
return 0;
58+
}
59+
}
60+
61+
private final InternalReentrantLock lock;
62+
63+
public PRLock(PythonClass cls) {
64+
super(cls);
65+
this.lock = new InternalReentrantLock();
66+
}
67+
68+
public boolean isOwned() {
69+
return lock.isHeldByCurrentThread();
70+
}
71+
72+
public int getCount() {
73+
return lock.getHoldCount();
74+
}
75+
76+
public long getOwnerId() {
77+
return lock.getOwnerId();
78+
}
79+
80+
public void releaseAll() {
81+
while (lock.getHoldCount() > 0) {
82+
lock.unlock();
83+
}
84+
}
85+
86+
@Override
87+
boolean tryToAcquire() {
88+
return lock.tryLock();
89+
}
90+
91+
@Override
92+
boolean blockUntilAcquire() throws InterruptedException {
93+
lock.lock();
94+
return true;
95+
}
96+
97+
@Override
98+
boolean acquireTimeout(long timeout) throws InterruptedException {
99+
return lock.tryLock(timeout, TimeUnit.MILLISECONDS);
100+
}
101+
102+
@Override
103+
public void release() {
104+
lock.unlock();
105+
}
106+
107+
@Override
108+
public boolean locked() {
109+
return lock.isLocked();
110+
}
111+
}

0 commit comments

Comments
 (0)