41
41
package com .oracle .graal .python .builtins .modules ;
42
42
43
43
import java .util .List ;
44
+ import java .util .concurrent .Semaphore ;
44
45
46
+ import com .oracle .graal .python .PythonLanguage ;
45
47
import com .oracle .graal .python .builtins .Builtin ;
46
48
import com .oracle .graal .python .builtins .CoreFunctions ;
47
49
import com .oracle .graal .python .builtins .PythonBuiltinClassType ;
48
50
import com .oracle .graal .python .builtins .PythonBuiltins ;
51
+ import com .oracle .graal .python .builtins .objects .PNone ;
49
52
import com .oracle .graal .python .builtins .objects .thread .PSemLock ;
50
53
import com .oracle .graal .python .builtins .objects .type .LazyPythonClass ;
51
54
import com .oracle .graal .python .nodes .function .PythonBuiltinBaseNode ;
52
55
import com .oracle .graal .python .nodes .function .PythonBuiltinNode ;
56
+ import com .oracle .graal .python .nodes .function .builtins .PythonUnaryBuiltinNode ;
53
57
import com .oracle .graal .python .nodes .util .CastToJavaIntNode ;
58
+ import com .oracle .graal .python .nodes .util .CastToJavaStringNode ;
54
59
import com .oracle .graal .python .runtime .PythonCore ;
60
+ import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
55
61
import com .oracle .truffle .api .dsl .Cached ;
62
+ import com .oracle .truffle .api .dsl .CachedLanguage ;
56
63
import com .oracle .truffle .api .dsl .GenerateNodeFactory ;
57
64
import com .oracle .truffle .api .dsl .NodeFactory ;
58
65
import com .oracle .truffle .api .dsl .Specialization ;
@@ -76,21 +83,68 @@ public void initialize(PythonCore core) {
76
83
abstract static class ConstructSemLockNode extends PythonBuiltinNode {
77
84
@ Specialization
78
85
PSemLock construct (LazyPythonClass cls , Object kindObj , Object valueObj , Object maxvalueObj , Object nameObj , Object unlinkObj ,
86
+ @ Cached CastToJavaStringNode castNameNode ,
79
87
@ Cached CastToJavaIntNode castKindToIntNode ,
80
88
@ Cached CastToJavaIntNode castValueToIntNode ,
81
89
@ Cached CastToJavaIntNode castMaxvalueToIntNode ,
82
- @ Cached CastToJavaIntNode castUnlinkToIntNode ) {
90
+ @ Cached CastToJavaIntNode castUnlinkToIntNode ,
91
+ @ CachedLanguage PythonLanguage lang ) {
83
92
int kind = castKindToIntNode .execute (kindObj );
84
93
if (kind != PSemLock .RECURSIVE_MUTEX && kind != PSemLock .SEMAPHORE ) {
85
94
throw raise (PythonBuiltinClassType .ValueError , "unrecognized kind" );
86
95
}
87
96
int value = castValueToIntNode .execute (valueObj );
88
- int maxvalue = castMaxvalueToIntNode .execute (maxvalueObj );
97
+ castMaxvalueToIntNode .execute (maxvalueObj ); // executed for the side-effect, but ignored on posix
98
+ Semaphore semaphore = newSemaphore (value );
89
99
int unlink = castUnlinkToIntNode .execute (unlinkObj );
90
- if (unlink != 0 ) {
91
- throw raise (PythonBuiltinClassType .SystemError , "semaphore unlinking is not yet implemented" );
100
+ String name = castNameNode .execute (nameObj );
101
+ if (unlink == 0 ) {
102
+ // CPython creates a named semaphore, and if unlink != 0 unlinks
103
+ // it directly so it cannot be access by other processes. We
104
+ // have to explicitly link it, so we do that here if we
105
+ // must. CPython always uses O_CREAT | O_EXCL for creating named
106
+ // semaphores, so a conflict raises.
107
+ if (semaphoreExists (lang , name )) {
108
+ throw raise (PythonBuiltinClassType .FileExistsError , "Semaphore name taken: '%s'" , name );
109
+ } else {
110
+ semaphorePut (lang , semaphore , name );
111
+ }
92
112
}
93
- return factory ().createSemLock (cls , kind , value , maxvalue , nameObj );
113
+ return factory ().createSemLock (cls , kind , semaphore );
114
+ }
115
+
116
+ @ TruffleBoundary
117
+ private static Object semaphorePut (PythonLanguage lang , Semaphore semaphore , String name ) {
118
+ return lang .namedSemaphores .put (name , semaphore );
119
+ }
120
+
121
+ @ TruffleBoundary
122
+ private static boolean semaphoreExists (PythonLanguage lang , String name ) {
123
+ return lang .namedSemaphores .containsKey (name );
124
+ }
125
+
126
+ @ TruffleBoundary
127
+ private static Semaphore newSemaphore (int value ) {
128
+ return new Semaphore (value );
129
+ }
130
+ }
131
+
132
+ @ GenerateNodeFactory
133
+ @ Builtin (name = "sem_unlink" , parameterNames = {"name" })
134
+ abstract static class SemUnlink extends PythonUnaryBuiltinNode {
135
+ @ Specialization
136
+ PNone doit (String name ,
137
+ @ CachedLanguage PythonLanguage lang ) {
138
+ Semaphore prev = semaphoreRemove (name , lang );
139
+ if (prev == null ) {
140
+ throw raise (PythonBuiltinClassType .FileNotFoundError , "No such file or directory: 'semaphores:/%s'" , name );
141
+ }
142
+ return PNone .NONE ;
143
+ }
144
+
145
+ @ TruffleBoundary
146
+ private static Semaphore semaphoreRemove (String name , PythonLanguage lang ) {
147
+ return lang .namedSemaphores .remove (name );
94
148
}
95
149
}
96
150
}
0 commit comments