Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions Include/internal/pycore_cown.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#ifndef Py_INTERNAL_COWN_H
#define Py_INTERNAL_COWN_H
#ifdef __cplusplus
extern "C" {
#endif

#ifndef Py_BUILD_CORE
# error "Py_BUILD_CORE must be defined to include this header"
#endif

#include "object.h"
#include "exports.h"

typedef struct _PyCownObject _PyCownObject;
#define _PyCownObject_CAST(op) _Py_CAST(_PyCownObject*, op)

PyAPI_DATA(PyTypeObject) _PyCown_Type;

typedef uint64_t _PyCown_ipid_t;
typedef uint64_t _PyCown_thread_id_t;

PyAPI_FUNC(_PyCown_ipid_t) _PyCown_ThisInterpreterId(void);
PyAPI_FUNC(_PyCown_thread_id_t) _PyCown_ThisThreadId(void);


#ifdef __cplusplus
}
#endif
#endif /* !Py_INTERNAL_COWN_H */
4 changes: 4 additions & 0 deletions Include/internal/pycore_immutability.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ extern "C" {
# error "Py_BUILD_CORE must be defined to include this header"
#endif

PyAPI_DATA(PyTypeObject) _PyTracingRegion_Type;
PyAPI_FUNC(int) _PyTracingRegion_Close(PyObject* region);
PyAPI_FUNC(int) _PyTracingRegion_Open(PyObject* region);

struct _Py_immutability_state {
int late_init_done;
struct _Py_hashtable_t *shallow_immutable_types;
Expand Down
2 changes: 2 additions & 0 deletions Lib/immutable.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
FREEZABLE_PROXY = _c.FREEZABLE_PROXY
InterpreterLocal = _c.InterpreterLocal
SharedField = _c.SharedField
TracingRegion = _c.TracingRegion
Cown = _c.Cown

# FIXME(immutable): For the longest time we used the name `isfrozen`
# without the underscore. This keeps the function name for now, but
Expand Down
76 changes: 76 additions & 0 deletions Lib/test/test_freeze/test_tracing_region.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import sys
import unittest
from immutable import freeze, is_frozen, freezable
from immutable import TracingRegion as Region

class TestTraceRefs(unittest.TestCase):
def test_trace(self):
@freezable
class A:
pass

r = Region()
r.a = A()
r.b = A()
r.c = A()

_, base_refs = r.trace()

a = r.a
_, ref_count = r.trace()
self.assertEqual(ref_count, base_refs + 1)

b = r.b
c = r.c
_, ref_count = r.trace()
self.assertEqual(ref_count, base_refs + 3)

class TestImplicitFreeze(unittest.TestCase):
def test_implicit_freeze_func(self):
@freezable
def some_func():
pass
r = Region()

r.obj = some_func
self.assertFalse(is_frozen(r.obj))
r.trace()
self.assertTrue(is_frozen(r.obj))

def test_implicit_freeze_type(self):
@freezable
class A:
pass
r = Region()

r.obj = A
self.assertFalse(is_frozen(r.obj))
r.trace()
self.assertTrue(is_frozen(r.obj))

def test_implicit_freeze_module(self):
import random;
r = Region()

r.obj = random
self.assertFalse(is_frozen(r.obj))
r.trace()
self.assertTrue(is_frozen(r.obj))

# Unimport module
sys.modules.pop("random", None)
sys.mut_modules.pop("random", None)

def test_implicit_freeze_str(self):
r = Region()

r.obj = "Ducks are cool"
r.trace()
self.assertTrue(is_frozen(r.obj))

def test_implicit_freeze_int(self):
r = Region()

r.obj = 17
r.trace()
self.assertTrue(is_frozen(r.obj))
2 changes: 2 additions & 0 deletions Makefile.pre.in
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,7 @@ OBJECT_OBJS= \
Objects/classobject.o \
Objects/codeobject.o \
Objects/complexobject.o \
Objects/cownobject.o \
Objects/descrobject.o \
Objects/enumobject.o \
Objects/exceptions.o \
Expand Down Expand Up @@ -555,6 +556,7 @@ OBJECT_OBJS= \
Objects/sliceobject.o \
Objects/structseq.o \
Objects/templateobject.o \
Objects/tracingregionobject.o \
Objects/tupleobject.o \
Objects/typeobject.o \
Objects/typevarobject.o \
Expand Down
16 changes: 16 additions & 0 deletions Modules/_immutablemodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "Python.h"
#include <stdbool.h>
#include "pycore_cown.h"
#include "pycore_object.h"
#include "pycore_immutability.h"
#include "pycore_critical_section.h"
Expand Down Expand Up @@ -650,6 +651,21 @@ immutable_exec(PyObject *module) {
return -1;
}

if (PyModule_AddType(module, &_PyTracingRegion_Type) != 0) {
return -1;
}
if (_PyImmutability_SetFreezable(
(PyObject*)&_PyTracingRegion_Type, _Py_FREEZABLE_YES) < 0) {
return -1;
}

if (PyModule_AddType(module, &_PyCown_Type) != 0) {
return -1;
}
if (_PyImmutability_SetFreezable((PyObject*)&_PyCown_Type, _Py_FREEZABLE_YES) < 0) {
return -1;
}

if (PyModule_AddIntConstant(module, "FREEZABLE_YES",
_Py_FREEZABLE_YES) != 0) {
return -1;
Expand Down
Loading
Loading