@@ -726,11 +726,6 @@ lock_dealloc(PyObject *op)
726
726
Py_DECREF (tp );
727
727
}
728
728
729
- static inline PyLockStatus
730
- acquire_timed (PyThread_type_lock lock , PyTime_t timeout )
731
- {
732
- return PyThread_acquire_lock_timed_with_retries (lock , timeout );
733
- }
734
729
735
730
static int
736
731
lock_acquire_parse_args (PyObject * args , PyObject * kwds ,
@@ -973,10 +968,7 @@ static PyType_Spec lock_type_spec = {
973
968
974
969
typedef struct {
975
970
PyObject_HEAD
976
- PyThread_type_lock rlock_lock ;
977
- PyThread_ident_t rlock_owner ;
978
- unsigned long rlock_count ;
979
- PyObject * in_weakreflist ;
971
+ _PyRecursiveMutex lock ;
980
972
} rlockobject ;
981
973
982
974
static int
@@ -992,59 +984,26 @@ rlock_dealloc(PyObject *op)
992
984
{
993
985
rlockobject * self = (rlockobject * )op ;
994
986
PyObject_GC_UnTrack (self );
995
- if (self -> in_weakreflist != NULL )
996
- PyObject_ClearWeakRefs ((PyObject * ) self );
997
- /* self->rlock_lock can be NULL if PyThread_allocate_lock() failed
998
- in rlock_new() */
999
- if (self -> rlock_lock != NULL ) {
1000
- /* Unlock the lock so it's safe to free it */
1001
- if (self -> rlock_count > 0 )
1002
- PyThread_release_lock (self -> rlock_lock );
1003
-
1004
- PyThread_free_lock (self -> rlock_lock );
1005
- }
987
+ PyObject_ClearWeakRefs ((PyObject * ) self );
1006
988
PyTypeObject * tp = Py_TYPE (self );
1007
989
tp -> tp_free (self );
1008
990
Py_DECREF (tp );
1009
991
}
1010
992
1011
- static bool
1012
- rlock_is_owned_by (rlockobject * self , PyThread_ident_t tid )
1013
- {
1014
- PyThread_ident_t owner_tid =
1015
- _Py_atomic_load_ullong_relaxed (& self -> rlock_owner );
1016
- return owner_tid == tid && self -> rlock_count > 0 ;
1017
- }
1018
993
1019
994
static PyObject *
1020
995
rlock_acquire (PyObject * op , PyObject * args , PyObject * kwds )
1021
996
{
1022
997
rlockobject * self = (rlockobject * )op ;
1023
998
PyTime_t timeout ;
1024
- PyThread_ident_t tid ;
1025
- PyLockStatus r = PY_LOCK_ACQUIRED ;
1026
999
1027
- if (lock_acquire_parse_args (args , kwds , & timeout ) < 0 )
1000
+ if (lock_acquire_parse_args (args , kwds , & timeout ) < 0 ) {
1028
1001
return NULL ;
1029
-
1030
- tid = PyThread_get_thread_ident_ex ();
1031
- if (rlock_is_owned_by (self , tid )) {
1032
- unsigned long count = self -> rlock_count + 1 ;
1033
- if (count <= self -> rlock_count ) {
1034
- PyErr_SetString (PyExc_OverflowError ,
1035
- "Internal lock count overflowed" );
1036
- return NULL ;
1037
- }
1038
- self -> rlock_count = count ;
1039
- Py_RETURN_TRUE ;
1040
- }
1041
- r = acquire_timed (self -> rlock_lock , timeout );
1042
- if (r == PY_LOCK_ACQUIRED ) {
1043
- assert (self -> rlock_count == 0 );
1044
- _Py_atomic_store_ullong_relaxed (& self -> rlock_owner , tid );
1045
- self -> rlock_count = 1 ;
1046
1002
}
1047
- else if (r == PY_LOCK_INTR ) {
1003
+
1004
+ PyLockStatus r = _PyRecursiveMutex_LockTimed (& self -> lock , timeout ,
1005
+ _PY_LOCK_HANDLE_SIGNALS | _PY_LOCK_DETACH );
1006
+ if (r == PY_LOCK_INTR ) {
1048
1007
return NULL ;
1049
1008
}
1050
1009
@@ -1078,17 +1037,12 @@ static PyObject *
1078
1037
rlock_release (PyObject * op , PyObject * Py_UNUSED (ignored ))
1079
1038
{
1080
1039
rlockobject * self = (rlockobject * )op ;
1081
- PyThread_ident_t tid = PyThread_get_thread_ident_ex ();
1082
1040
1083
- if (! rlock_is_owned_by ( self , tid ) ) {
1041
+ if (_PyRecursiveMutex_TryUnlock ( & self -> lock ) < 0 ) {
1084
1042
PyErr_SetString (PyExc_RuntimeError ,
1085
1043
"cannot release un-acquired lock" );
1086
1044
return NULL ;
1087
1045
}
1088
- if (-- self -> rlock_count == 0 ) {
1089
- _Py_atomic_store_ullong_relaxed (& self -> rlock_owner , 0 );
1090
- PyThread_release_lock (self -> rlock_lock );
1091
- }
1092
1046
Py_RETURN_NONE ;
1093
1047
}
1094
1048
@@ -1116,25 +1070,15 @@ rlock_acquire_restore(PyObject *op, PyObject *args)
1116
1070
{
1117
1071
rlockobject * self = (rlockobject * )op ;
1118
1072
PyThread_ident_t owner ;
1119
- unsigned long count ;
1120
- int r = 1 ;
1073
+ Py_ssize_t count ;
1121
1074
1122
- if (!PyArg_ParseTuple (args , "(k " Py_PARSE_THREAD_IDENT_T "):_acquire_restore" ,
1075
+ if (!PyArg_ParseTuple (args , "(n " Py_PARSE_THREAD_IDENT_T "):_acquire_restore" ,
1123
1076
& count , & owner ))
1124
1077
return NULL ;
1125
1078
1126
- if (!PyThread_acquire_lock (self -> rlock_lock , 0 )) {
1127
- Py_BEGIN_ALLOW_THREADS
1128
- r = PyThread_acquire_lock (self -> rlock_lock , 1 );
1129
- Py_END_ALLOW_THREADS
1130
- }
1131
- if (!r ) {
1132
- PyErr_SetString (ThreadError , "couldn't acquire lock" );
1133
- return NULL ;
1134
- }
1135
- assert (self -> rlock_count == 0 );
1136
- _Py_atomic_store_ullong_relaxed (& self -> rlock_owner , owner );
1137
- self -> rlock_count = count ;
1079
+ _PyRecursiveMutex_Lock (& self -> lock );
1080
+ _Py_atomic_store_ullong_relaxed (& self -> lock .thread , owner );
1081
+ self -> lock .level = (size_t )count - 1 ;
1138
1082
Py_RETURN_NONE ;
1139
1083
}
1140
1084
@@ -1148,21 +1092,18 @@ static PyObject *
1148
1092
rlock_release_save (PyObject * op , PyObject * Py_UNUSED (ignored ))
1149
1093
{
1150
1094
rlockobject * self = (rlockobject * )op ;
1151
- PyThread_ident_t owner ;
1152
- unsigned long count ;
1153
1095
1154
- if (self -> rlock_count == 0 ) {
1096
+ if (! _PyRecursiveMutex_IsLockedByCurrentThread ( & self -> lock ) ) {
1155
1097
PyErr_SetString (PyExc_RuntimeError ,
1156
1098
"cannot release un-acquired lock" );
1157
1099
return NULL ;
1158
1100
}
1159
1101
1160
- owner = self -> rlock_owner ;
1161
- count = self -> rlock_count ;
1162
- self -> rlock_count = 0 ;
1163
- _Py_atomic_store_ullong_relaxed (& self -> rlock_owner , 0 );
1164
- PyThread_release_lock (self -> rlock_lock );
1165
- return Py_BuildValue ("k" Py_PARSE_THREAD_IDENT_T , count , owner );
1102
+ PyThread_ident_t owner = self -> lock .thread ;
1103
+ Py_ssize_t count = self -> lock .level + 1 ;
1104
+ self -> lock .level = 0 ; // ensure the unlock releases the lock
1105
+ _PyRecursiveMutex_Unlock (& self -> lock );
1106
+ return Py_BuildValue ("n" Py_PARSE_THREAD_IDENT_T , count , owner );
1166
1107
}
1167
1108
1168
1109
PyDoc_STRVAR (rlock_release_save_doc ,
@@ -1175,10 +1116,10 @@ static PyObject *
1175
1116
rlock_recursion_count (PyObject * op , PyObject * Py_UNUSED (ignored ))
1176
1117
{
1177
1118
rlockobject * self = (rlockobject * )op ;
1178
- PyThread_ident_t tid = PyThread_get_thread_ident_ex ();
1179
- PyThread_ident_t owner =
1180
- _Py_atomic_load_ullong_relaxed ( & self -> rlock_owner );
1181
- return PyLong_FromUnsignedLong ( owner == tid ? self -> rlock_count : 0UL );
1119
+ if ( _PyRecursiveMutex_IsLockedByCurrentThread ( & self -> lock )) {
1120
+ return PyLong_FromSize_t ( self -> lock . level + 1 );
1121
+ }
1122
+ return PyLong_FromLong ( 0 );
1182
1123
}
1183
1124
1184
1125
PyDoc_STRVAR (rlock_recursion_count_doc ,
@@ -1191,12 +1132,8 @@ static PyObject *
1191
1132
rlock_is_owned (PyObject * op , PyObject * Py_UNUSED (ignored ))
1192
1133
{
1193
1134
rlockobject * self = (rlockobject * )op ;
1194
- PyThread_ident_t tid = PyThread_get_thread_ident_ex ();
1195
-
1196
- if (rlock_is_owned_by (self , tid )) {
1197
- Py_RETURN_TRUE ;
1198
- }
1199
- Py_RETURN_FALSE ;
1135
+ long owned = _PyRecursiveMutex_IsLockedByCurrentThread (& self -> lock );
1136
+ return PyBool_FromLong (owned );
1200
1137
}
1201
1138
1202
1139
PyDoc_STRVAR (rlock_is_owned_doc ,
@@ -1212,45 +1149,29 @@ rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1212
1149
if (self == NULL ) {
1213
1150
return NULL ;
1214
1151
}
1215
- self -> in_weakreflist = NULL ;
1216
- self -> rlock_owner = 0 ;
1217
- self -> rlock_count = 0 ;
1218
-
1219
- self -> rlock_lock = PyThread_allocate_lock ();
1220
- if (self -> rlock_lock == NULL ) {
1221
- Py_DECREF (self );
1222
- PyErr_SetString (ThreadError , "can't allocate lock" );
1223
- return NULL ;
1224
- }
1152
+ self -> lock = (_PyRecursiveMutex ){0 };
1225
1153
return (PyObject * ) self ;
1226
1154
}
1227
1155
1228
1156
static PyObject *
1229
1157
rlock_repr (PyObject * op )
1230
1158
{
1231
1159
rlockobject * self = (rlockobject * )op ;
1232
- PyThread_ident_t owner =
1233
- _Py_atomic_load_ullong_relaxed ( & self -> rlock_owner ) ;
1160
+ PyThread_ident_t owner = self -> lock . thread ;
1161
+ size_t count = self -> lock . level + 1 ;
1234
1162
return PyUnicode_FromFormat (
1235
- "<%s %s object owner=%" PY_FORMAT_THREAD_IDENT_T " count=%lu at %p>" ,
1236
- self -> rlock_count ? "locked" : "unlocked" ,
1163
+ "<%s %s object owner=%" PY_FORMAT_THREAD_IDENT_T " count=%zu at %p>" ,
1164
+ owner ? "locked" : "unlocked" ,
1237
1165
Py_TYPE (self )-> tp_name , owner ,
1238
- self -> rlock_count , self );
1166
+ count , self );
1239
1167
}
1240
1168
1241
1169
1242
1170
#ifdef HAVE_FORK
1243
1171
static PyObject *
1244
1172
rlock__at_fork_reinit (rlockobject * self , PyObject * Py_UNUSED (args ))
1245
1173
{
1246
- if (_PyThread_at_fork_reinit (& self -> rlock_lock ) < 0 ) {
1247
- PyErr_SetString (ThreadError , "failed to reinitialize lock at fork" );
1248
- return NULL ;
1249
- }
1250
-
1251
- self -> rlock_owner = 0 ;
1252
- self -> rlock_count = 0 ;
1253
-
1174
+ self -> lock = (_PyRecursiveMutex ){0 };
1254
1175
Py_RETURN_NONE ;
1255
1176
}
1256
1177
#endif /* HAVE_FORK */
@@ -1281,18 +1202,12 @@ static PyMethodDef rlock_methods[] = {
1281
1202
};
1282
1203
1283
1204
1284
- static PyMemberDef rlock_type_members [] = {
1285
- {"__weaklistoffset__" , Py_T_PYSSIZET , offsetof(rlockobject , in_weakreflist ), Py_READONLY },
1286
- {NULL },
1287
- };
1288
-
1289
1205
static PyType_Slot rlock_type_slots [] = {
1290
1206
{Py_tp_dealloc , rlock_dealloc },
1291
1207
{Py_tp_repr , rlock_repr },
1292
1208
{Py_tp_methods , rlock_methods },
1293
1209
{Py_tp_alloc , PyType_GenericAlloc },
1294
1210
{Py_tp_new , rlock_new },
1295
- {Py_tp_members , rlock_type_members },
1296
1211
{Py_tp_traverse , rlock_traverse },
1297
1212
{0 , 0 },
1298
1213
};
@@ -1301,7 +1216,7 @@ static PyType_Spec rlock_type_spec = {
1301
1216
.name = "_thread.RLock" ,
1302
1217
.basicsize = sizeof (rlockobject ),
1303
1218
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
1304
- Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE ),
1219
+ Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_MANAGED_WEAKREF ),
1305
1220
.slots = rlock_type_slots ,
1306
1221
};
1307
1222
0 commit comments