Skip to content

Commit 8a9918a

Browse files
committed
add _thread.lock builtin (all locks are internally reentrant locks)
1 parent 57f4429 commit 8a9918a

File tree

5 files changed

+227
-0
lines changed

5 files changed

+227
-0
lines changed

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
@@ -87,6 +87,7 @@ public enum PythonBuiltinClassType implements LazyPythonClass {
8787
PZip("zip", "builtins"),
8888
PBuffer("buffer", "builtins"),
8989
PThread("thread", "_thread"),
90+
PLock("lock", "_thread"),
9091
PSocket("socket", "_socket"),
9192

9293
// Errors and exceptions:

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,30 @@
4343
import java.util.ArrayList;
4444
import java.util.List;
4545

46+
import com.oracle.graal.python.builtins.Builtin;
4647
import com.oracle.graal.python.builtins.CoreFunctions;
4748
import com.oracle.graal.python.builtins.PythonBuiltins;
49+
import com.oracle.graal.python.builtins.objects.thread.PLock;
50+
import com.oracle.graal.python.builtins.objects.type.PythonClass;
4851
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
52+
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
53+
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
4954
import com.oracle.truffle.api.dsl.NodeFactory;
55+
import com.oracle.truffle.api.dsl.Specialization;
5056

5157
@CoreFunctions(defineModule = "_thread")
5258
public class ThreadModuleBuiltins extends PythonBuiltins {
5359
@Override
5460
protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFactories() {
5561
return new ArrayList<>();
5662
}
63+
64+
@Builtin(name = "allocate_lock", fixedNumOfPositionalArgs = 1)
65+
@GenerateNodeFactory
66+
abstract static class AllocateLockNode extends PythonUnaryBuiltinNode {
67+
@Specialization
68+
PLock allocate(PythonClass cls) {
69+
return factory().createLock(cls);
70+
}
71+
}
5772
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
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.List;
44+
45+
import com.oracle.graal.python.builtins.Builtin;
46+
import com.oracle.graal.python.builtins.CoreFunctions;
47+
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
48+
import com.oracle.graal.python.builtins.PythonBuiltins;
49+
import com.oracle.graal.python.builtins.objects.PNone;
50+
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
51+
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
52+
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
53+
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
54+
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
55+
import com.oracle.truffle.api.dsl.NodeFactory;
56+
import com.oracle.truffle.api.dsl.Specialization;
57+
58+
@CoreFunctions(extendClasses = PythonBuiltinClassType.PLock)
59+
public class LockBuiltins extends PythonBuiltins {
60+
@Override
61+
protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFactories() {
62+
return LockBuiltinsFactory.getFactories();
63+
}
64+
65+
@Builtin(name = "acquire", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 3, keywordArguments = {"waitflag", "timeout"})
66+
@GenerateNodeFactory
67+
abstract static class AcquireLockNode extends PythonTernaryBuiltinNode {
68+
@Specialization
69+
@TruffleBoundary
70+
boolean doAcquire(PLock self, int waitFlag, double timeout) {
71+
return self.acquire(waitFlag, timeout);
72+
}
73+
74+
@Specialization
75+
@TruffleBoundary
76+
boolean doAcquire(PLock self, @SuppressWarnings("unused") PNone waitFlag, double timeout) {
77+
return self.acquire(1, timeout);
78+
}
79+
80+
@Specialization
81+
@TruffleBoundary
82+
boolean doAcquire(PLock self, int waitFlag, @SuppressWarnings("unused") PNone timeout) {
83+
return self.acquire(waitFlag, -1.0);
84+
}
85+
86+
@Specialization
87+
@TruffleBoundary
88+
boolean doAcquire(PLock self, @SuppressWarnings("unused") PNone waitFlag, @SuppressWarnings("unused") PNone timeout) {
89+
return self.acquire(1, -1.0);
90+
}
91+
}
92+
93+
@Builtin(name = "release", fixedNumOfPositionalArgs = 1)
94+
@GenerateNodeFactory
95+
abstract static class ReleaseLockNode extends PythonUnaryBuiltinNode {
96+
@Specialization
97+
@TruffleBoundary
98+
Object doRelease(PLock self) {
99+
self.release();
100+
return PNone.NONE;
101+
}
102+
}
103+
104+
@Builtin(name = "locked", fixedNumOfPositionalArgs = 1)
105+
@GenerateNodeFactory
106+
abstract static class IsLockedLockNode extends PythonUnaryBuiltinNode {
107+
@Specialization
108+
boolean isLocked(PLock self) {
109+
return self.locked();
110+
}
111+
}
112+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
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.object.PythonBuiltinObject;
47+
import com.oracle.graal.python.builtins.objects.type.PythonClass;
48+
49+
public class PLock extends PythonBuiltinObject {
50+
private final ReentrantLock lock;
51+
52+
public PLock(PythonClass cls) {
53+
super(cls);
54+
lock = new ReentrantLock();
55+
}
56+
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+
}
77+
}
78+
79+
public void release() {
80+
lock.unlock();
81+
}
82+
83+
public boolean locked() {
84+
return lock.isLocked();
85+
}
86+
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@
9797
import com.oracle.graal.python.builtins.objects.socket.PSocket;
9898
import com.oracle.graal.python.builtins.objects.str.PString;
9999
import com.oracle.graal.python.builtins.objects.superobject.SuperObject;
100+
import com.oracle.graal.python.builtins.objects.thread.PLock;
100101
import com.oracle.graal.python.builtins.objects.traceback.PTraceback;
101102
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
102103
import com.oracle.graal.python.builtins.objects.type.LazyPythonClass;
@@ -744,4 +745,16 @@ public PSocket createSocket(int family, int type, int proto) {
744745
public PSocket createSocket(PythonClass cls, int family, int type, int proto) {
745746
return trace(new PSocket(cls, family, type, proto));
746747
}
748+
749+
/*
750+
* Threading
751+
*/
752+
753+
public PLock createLock() {
754+
return createLock(PythonBuiltinClassType.PLock);
755+
}
756+
757+
public PLock createLock(PythonClass cls) {
758+
return trace(new PLock(cls));
759+
}
747760
}

0 commit comments

Comments
 (0)