@@ -2098,6 +2098,16 @@ struct channel_info {
2098
2098
struct {
2099
2099
// 1: closed; -1: closing
2100
2100
int closed ;
2101
+ struct {
2102
+ Py_ssize_t nsend_only ; // not released
2103
+ Py_ssize_t nsend_only_released ;
2104
+ Py_ssize_t nrecv_only ; // not released
2105
+ Py_ssize_t nrecv_only_released ;
2106
+ Py_ssize_t nboth ; // not released
2107
+ Py_ssize_t nboth_released ;
2108
+ Py_ssize_t nboth_send_released ;
2109
+ Py_ssize_t nboth_recv_released ;
2110
+ } all ;
2101
2111
struct {
2102
2112
// 1: associated; -1: released
2103
2113
int send ;
@@ -2152,20 +2162,68 @@ _channel_get_info(_channels *channels, int64_t cid, struct channel_info *info)
2152
2162
// Get the number of queued objects.
2153
2163
info -> count = chan -> queue -> count ;
2154
2164
2155
- // Get the current ends status.
2156
- _channelend * send = _channelend_find (chan -> ends -> send , interpid , NULL );
2157
- if (send == NULL ) {
2158
- info -> status .cur .send = 0 ;
2159
- }
2160
- else {
2161
- info -> status .cur .send = send -> open ? 1 : -1 ;
2162
- }
2163
- _channelend * recv = _channelend_find (chan -> ends -> recv , interpid , NULL );
2164
- if (recv == NULL ) {
2165
- info -> status .cur .recv = 0 ;
2165
+ // Get the ends statuses.
2166
+ assert (info -> status .cur .send == 0 );
2167
+ assert (info -> status .cur .recv == 0 );
2168
+ _channelend * send = chan -> ends -> send ;
2169
+ while (send != NULL ) {
2170
+ if (send -> interpid == interpid ) {
2171
+ info -> status .cur .send = send -> open ? 1 : -1 ;
2172
+ }
2173
+
2174
+ if (send -> open ) {
2175
+ info -> status .all .nsend_only += 1 ;
2176
+ }
2177
+ else {
2178
+ info -> status .all .nsend_only_released += 1 ;
2179
+ }
2180
+ send = send -> next ;
2166
2181
}
2167
- else {
2168
- info -> status .cur .recv = recv -> open ? 1 : -1 ;
2182
+ _channelend * recv = chan -> ends -> recv ;
2183
+ while (recv != NULL ) {
2184
+ if (recv -> interpid == interpid ) {
2185
+ info -> status .cur .recv = recv -> open ? 1 : -1 ;
2186
+ }
2187
+
2188
+ // XXX This is O(n*n). Why do we have 2 linked lists?
2189
+ _channelend * send = chan -> ends -> send ;
2190
+ while (send != NULL ) {
2191
+ if (send -> interpid == recv -> interpid ) {
2192
+ break ;
2193
+ }
2194
+ send = send -> next ;
2195
+ }
2196
+ if (send == NULL ) {
2197
+ if (recv -> open ) {
2198
+ info -> status .all .nrecv_only += 1 ;
2199
+ }
2200
+ else {
2201
+ info -> status .all .nrecv_only_released += 1 ;
2202
+ }
2203
+ }
2204
+ else {
2205
+ if (recv -> open ) {
2206
+ if (send -> open ) {
2207
+ info -> status .all .nboth += 1 ;
2208
+ info -> status .all .nsend_only -= 1 ;
2209
+ }
2210
+ else {
2211
+ info -> status .all .nboth_recv_released += 1 ;
2212
+ info -> status .all .nsend_only_released -= 1 ;
2213
+ }
2214
+ }
2215
+ else {
2216
+ if (send -> open ) {
2217
+ info -> status .all .nboth_send_released += 1 ;
2218
+ info -> status .all .nsend_only -= 1 ;
2219
+ }
2220
+ else {
2221
+ info -> status .all .nboth_released += 1 ;
2222
+ info -> status .all .nsend_only_released -= 1 ;
2223
+ }
2224
+ }
2225
+ }
2226
+ recv = recv -> next ;
2169
2227
}
2170
2228
2171
2229
finally :
@@ -2183,6 +2241,23 @@ static PyStructSequence_Field channel_info_fields[] = {
2183
2241
{"closing" , "send is closed, recv is non-empty" },
2184
2242
{"closed" , "both ends are closed" },
2185
2243
{"count" , "queued objects" },
2244
+
2245
+ {"num_interp_send" , "interpreters bound to the send end" },
2246
+ {"num_interp_send_released" ,
2247
+ "interpreters bound to the send end and released" },
2248
+
2249
+ {"num_interp_recv" , "interpreters bound to the send end" },
2250
+ {"num_interp_recv_released" ,
2251
+ "interpreters bound to the send end and released" },
2252
+
2253
+ {"num_interp_both" , "interpreters bound to both ends" },
2254
+ {"num_interp_both_released" ,
2255
+ "interpreters bound to both ends and released_from_both" },
2256
+ {"num_interp_both_send_released" ,
2257
+ "interpreters bound to both ends and released_from_the send end" },
2258
+ {"num_interp_both_recv_released" ,
2259
+ "interpreters bound to both ends and released_from_the recv end" },
2260
+
2186
2261
{"send_associated" , "current interpreter is bound to the send end" },
2187
2262
{"send_released" , "current interpreter *was* bound to the send end" },
2188
2263
{"recv_associated" , "current interpreter is bound to the recv end" },
@@ -2228,6 +2303,14 @@ new_channel_info(PyObject *mod, struct channel_info *info)
2228
2303
SET_BOOL (info -> status .closed == -1 );
2229
2304
SET_BOOL (info -> status .closed == 1 );
2230
2305
SET_COUNT (info -> count );
2306
+ SET_COUNT (info -> status .all .nsend_only );
2307
+ SET_COUNT (info -> status .all .nsend_only_released );
2308
+ SET_COUNT (info -> status .all .nrecv_only );
2309
+ SET_COUNT (info -> status .all .nrecv_only_released );
2310
+ SET_COUNT (info -> status .all .nboth );
2311
+ SET_COUNT (info -> status .all .nboth_released );
2312
+ SET_COUNT (info -> status .all .nboth_send_released );
2313
+ SET_COUNT (info -> status .all .nboth_recv_released );
2231
2314
SET_BOOL (info -> status .cur .send == 1 );
2232
2315
SET_BOOL (info -> status .cur .send == -1 );
2233
2316
SET_BOOL (info -> status .cur .recv == 1 );
0 commit comments