Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
72a0d218
Kaydet (Commit)
72a0d218
authored
Ock 29, 2018
tarafından
Pablo Galindo
Kaydeden (comit)
Raymond Hettinger
Ock 29, 2018
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
bpo-31356: Add context manager to temporarily disable GC (GH-4224)
üst
0cd6bca6
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
208 additions
and
1 deletion
+208
-1
gc.rst
Doc/library/gc.rst
+28
-0
mem.h
Include/internal/mem.h
+1
-0
test_gc.py
Lib/test/test_gc.py
+70
-1
2017-11-02-00-34-42.bpo-31356.54Lb8U.rst
...ore and Builtins/2017-11-02-00-34-42.bpo-31356.54Lb8U.rst
+3
-0
gcmodule.c
Modules/gcmodule.c
+106
-0
No files found.
Doc/library/gc.rst
Dosyayı görüntüle @
72a0d218
...
...
@@ -33,6 +33,34 @@ The :mod:`gc` module provides the following functions:
Disable automatic garbage collection.
.. class:: ensure_disabled()
Return a context manager object that disables the garbage collector and reenables the previous
state upon completion of the block. This is basically equivalent to::
from gc import enable, disable, isenabled
@contextmanager
def ensure_disabled():
was_enabled_previously = isenabled()
gc.disable()
yield
if was_enabled_previously:
gc.enable()
And lets you write code like this::
with ensure_disabled():
run_some_timing()
with ensure_disabled():
# do_something_that_has_real_time_guarantees
# such as a pair trade, robotic braking, etc
without needing to explicitly enable and disable the garbage collector yourself.
This context manager is implemented in C to assure atomicity, thread safety and speed.
.. function:: isenabled()
Returns true if automatic collection is enabled.
...
...
Include/internal/mem.h
Dosyayı görüntüle @
72a0d218
...
...
@@ -116,6 +116,7 @@ struct _gc_runtime_state {
int
enabled
;
int
debug
;
long
disabled_threads
;
/* linked lists of container objects */
struct
gc_generation
generations
[
NUM_GENERATIONS
];
PyGC_Head
*
generation0
;
...
...
Lib/test/test_gc.py
Dosyayı görüntüle @
72a0d218
import
unittest
from
test.support
import
(
verbose
,
refcount_test
,
run_unittest
,
strip_python_stderr
,
cpython_only
,
start_threads
,
temp_dir
,
requires_type_collecting
)
temp_dir
,
requires_type_collecting
,
reap_threads
)
from
test.support.script_helper
import
assert_python_ok
,
make_script
import
sys
...
...
@@ -9,6 +9,8 @@ import time
import
gc
import
weakref
import
threading
import
warnings
try
:
from
_testcapi
import
with_tp_del
...
...
@@ -1007,6 +1009,73 @@ class GCTogglingTests(unittest.TestCase):
# empty __dict__.
self
.
assertEqual
(
x
,
None
)
def
test_ensure_disabled
(
self
):
original_status
=
gc
.
isenabled
()
with
gc
.
ensure_disabled
():
inside_status
=
gc
.
isenabled
()
after_status
=
gc
.
isenabled
()
self
.
assertEqual
(
original_status
,
True
)
self
.
assertEqual
(
inside_status
,
False
)
self
.
assertEqual
(
after_status
,
True
)
def
test_ensure_disabled_with_gc_disabled
(
self
):
gc
.
disable
()
original_status
=
gc
.
isenabled
()
with
gc
.
ensure_disabled
():
inside_status
=
gc
.
isenabled
()
after_status
=
gc
.
isenabled
()
self
.
assertEqual
(
original_status
,
False
)
self
.
assertEqual
(
inside_status
,
False
)
self
.
assertEqual
(
after_status
,
False
)
@reap_threads
def
test_ensure_disabled_thread
(
self
):
thread_original_status
=
None
thread_inside_status
=
None
thread_after_status
=
None
def
disabling_thread
():
nonlocal
thread_original_status
nonlocal
thread_inside_status
nonlocal
thread_after_status
thread_original_status
=
gc
.
isenabled
()
with
gc
.
ensure_disabled
():
time
.
sleep
(
0.01
)
thread_inside_status
=
gc
.
isenabled
()
thread_after_status
=
gc
.
isenabled
()
original_status
=
gc
.
isenabled
()
with
warnings
.
catch_warnings
(
record
=
True
)
as
w
,
gc
.
ensure_disabled
():
inside_status_before_thread
=
gc
.
isenabled
()
thread
=
threading
.
Thread
(
target
=
disabling_thread
)
thread
.
start
()
inside_status_after_thread
=
gc
.
isenabled
()
after_status
=
gc
.
isenabled
()
thread
.
join
()
self
.
assertEqual
(
len
(
w
),
1
)
self
.
assertTrue
(
issubclass
(
w
[
-
1
]
.
category
,
RuntimeWarning
))
self
.
assertEqual
(
"Garbage collector enabled while another thread is "
"inside gc.ensure_enabled"
,
str
(
w
[
-
1
]
.
message
))
self
.
assertEqual
(
original_status
,
True
)
self
.
assertEqual
(
inside_status_before_thread
,
False
)
self
.
assertEqual
(
thread_original_status
,
False
)
self
.
assertEqual
(
thread_inside_status
,
True
)
self
.
assertEqual
(
thread_after_status
,
False
)
self
.
assertEqual
(
inside_status_after_thread
,
False
)
self
.
assertEqual
(
after_status
,
True
)
def
test_main
():
enabled
=
gc
.
isenabled
()
gc
.
disable
()
...
...
Misc/NEWS.d/next/Core and Builtins/2017-11-02-00-34-42.bpo-31356.54Lb8U.rst
0 → 100644
Dosyayı görüntüle @
72a0d218
Add a new contextmanager to the gc module that temporarily disables the GC
and restores the previous state. The implementation is done in C to assure
atomicity and speed.
Modules/gcmodule.c
Dosyayı görüntüle @
72a0d218
...
...
@@ -1067,6 +1067,10 @@ static PyObject *
gc_enable_impl
(
PyObject
*
module
)
/*[clinic end generated code: output=45a427e9dce9155c input=81ac4940ca579707]*/
{
if
(
_PyRuntime
.
gc
.
disabled_threads
){
PyErr_WarnEx
(
PyExc_RuntimeWarning
,
"Garbage collector enabled while another "
"thread is inside gc.ensure_enabled"
,
1
);
}
_PyRuntime
.
gc
.
enabled
=
1
;
Py_RETURN_NONE
;
}
...
...
@@ -1508,6 +1512,102 @@ static PyMethodDef GcMethods[] = {
{
NULL
,
NULL
}
/* Sentinel */
};
typedef
struct
{
PyObject_HEAD
int
previous_gc_state
;
}
ensure_disabled_object
;
static
void
ensure_disabled_object_dealloc
(
ensure_disabled_object
*
m_obj
)
{
Py_TYPE
(
m_obj
)
->
tp_free
((
PyObject
*
)
m_obj
);
}
static
PyObject
*
ensure_disabled__enter__method
(
ensure_disabled_object
*
self
,
PyObject
*
args
)
{
PyGILState_STATE
gstate
=
PyGILState_Ensure
();
++
_PyRuntime
.
gc
.
disabled_threads
;
self
->
previous_gc_state
=
_PyRuntime
.
gc
.
enabled
;
gc_disable_impl
(
NULL
);
PyGILState_Release
(
gstate
);
Py_RETURN_NONE
;
}
static
PyObject
*
ensure_disabled__exit__method
(
ensure_disabled_object
*
self
,
PyObject
*
args
)
{
PyGILState_STATE
gstate
=
PyGILState_Ensure
();
--
_PyRuntime
.
gc
.
disabled_threads
;
if
(
self
->
previous_gc_state
){
gc_enable_impl
(
NULL
);
}
else
{
gc_disable_impl
(
NULL
);
}
PyGILState_Release
(
gstate
);
Py_RETURN_NONE
;
}
static
struct
PyMethodDef
ensure_disabled_object_methods
[]
=
{
{
"__enter__"
,
(
PyCFunction
)
ensure_disabled__enter__method
,
METH_NOARGS
},
{
"__exit__"
,
(
PyCFunction
)
ensure_disabled__exit__method
,
METH_VARARGS
},
{
NULL
,
NULL
}
/* sentinel */
};
static
PyObject
*
new_disabled_obj
(
PyTypeObject
*
type
,
PyObject
*
args
,
PyObject
*
kwdict
){
ensure_disabled_object
*
self
;
self
=
(
ensure_disabled_object
*
)
type
->
tp_alloc
(
type
,
0
);
return
(
PyObject
*
)
self
;
};
static
PyTypeObject
gc_ensure_disabled_type
=
{
PyVarObject_HEAD_INIT
(
NULL
,
0
)
"gc.ensure_disabled"
,
/* tp_name */
sizeof
(
ensure_disabled_object
),
/* tp_size */
0
,
/* tp_itemsize */
/* methods */
(
destructor
)
ensure_disabled_object_dealloc
,
/* tp_dealloc */
0
,
/* tp_print */
0
,
/* tp_getattr */
0
,
/* tp_setattr */
0
,
/* tp_reserved */
0
,
/* tp_repr */
0
,
/* tp_as_number */
0
,
/*tp_as_sequence*/
0
,
/*tp_as_mapping*/
0
,
/*tp_hash*/
0
,
/*tp_call*/
0
,
/*tp_str*/
PyObject_GenericGetAttr
,
/*tp_getattro*/
0
,
/*tp_setattro*/
0
,
/*tp_as_buffer*/
Py_TPFLAGS_DEFAULT
|
Py_TPFLAGS_BASETYPE
,
/*tp_flags*/
0
,
/*tp_doc*/
0
,
/* tp_traverse */
0
,
/* tp_clear */
0
,
/* tp_richcompare */
0
,
/* tp_weaklistoffset */
0
,
/* tp_iter */
0
,
/* tp_iternext */
ensure_disabled_object_methods
,
/* tp_methods */
0
,
/* tp_members */
0
,
/* tp_getset */
0
,
/* tp_base */
0
,
/* tp_dict */
0
,
/* tp_descr_get */
0
,
/* tp_descr_set */
0
,
/* tp_dictoffset */
0
,
/* tp_init */
PyType_GenericAlloc
,
/* tp_alloc */
new_disabled_obj
,
/* tp_new */
PyObject_Del
,
/* tp_free */
};
static
struct
PyModuleDef
gcmodule
=
{
PyModuleDef_HEAD_INIT
,
"gc"
,
/* m_name */
...
...
@@ -1548,6 +1648,12 @@ PyInit_gc(void)
if
(
PyModule_AddObject
(
m
,
"callbacks"
,
_PyRuntime
.
gc
.
callbacks
)
<
0
)
return
NULL
;
if
(
PyType_Ready
(
&
gc_ensure_disabled_type
)
<
0
)
return
NULL
;
if
(
PyModule_AddObject
(
m
,
"ensure_disabled"
,
(
PyObject
*
)
&
gc_ensure_disabled_type
)
<
0
)
return
NULL
;
#define ADD_INT(NAME) if (PyModule_AddIntConstant(m, #NAME, NAME) < 0) return NULL
ADD_INT
(
DEBUG_STATS
);
ADD_INT
(
DEBUG_COLLECTABLE
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment