From 540bb60c282e4447a90f4696c2c6ed83dcce20ed Mon Sep 17 00:00:00 2001 From: Heeseon Cheon Date: Sun, 30 Jun 2024 03:33:01 +0900 Subject: [PATCH] =?UTF-8?q?[=EC=A0=84=ED=9D=AC=EC=84=A0]=2011=EC=A3=BC?= =?UTF-8?q?=EC=B0=A8=20=EB=AF=B8=EC=85=98=20=EC=A0=9C=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../11\354\243\274\354\260\250.md" | 141 ++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 "8th_members/\354\240\204\355\235\254\354\204\240/11\354\243\274\354\260\250.md" diff --git "a/8th_members/\354\240\204\355\235\254\354\204\240/11\354\243\274\354\260\250.md" "b/8th_members/\354\240\204\355\235\254\354\204\240/11\354\243\274\354\260\250.md" new file mode 100644 index 0000000..2c5066a --- /dev/null +++ "b/8th_members/\354\240\204\355\235\254\354\204\240/11\354\243\274\354\260\250.md" @@ -0,0 +1,141 @@ +### set 구조체 분석 +```c++ +// Include/setobject.h +PyAPI_DATA(PyTypeObject) PySet_Type; +``` +```c++ +// Objects/setobject.c +PyTypeObject PySet_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "set", /* tp_name */ + sizeof(PySetObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)set_dealloc, /* tp_dealloc */ + 0, /* tp_vectorcall_offset */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_as_async */ + (reprfunc)set_repr, /* tp_repr */ + &set_as_number, /* tp_as_number */ + &set_as_sequence, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + PyObject_HashNotImplemented, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_BASETYPE, /* tp_flags */ + set_doc, /* tp_doc */ + (traverseproc)set_traverse, /* tp_traverse */ + (inquiry)set_clear_internal, /* tp_clear */ + (richcmpfunc)set_richcompare, /* tp_richcompare */ + offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */ + (getiterfunc)set_iter, /* tp_iter */ + 0, /* tp_iternext */ + set_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 */ + (initproc)set_init, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + set_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ + .tp_vectorcall = set_vectorcall, +}; +``` +#### set_new +```c++ +// Objects/setobject.c +static PyObject * +set_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + return make_new_set(type, NULL); +} +``` +```c++ +static PyObject * +make_new_set(PyTypeObject *type, PyObject *iterable) +{ + assert(PyType_Check(type)); + PySetObject *so; + + so = (PySetObject *)type->tp_alloc(type, 0); // 메모리 할당 + if (so == NULL) + return NULL; + + so->fill = 0; // 해시 테이블에서 사용중인 slot 수 (삭제된 항목 포함) + so->used = 0; // 실제 사용중인 항목 수 + so->mask = PySet_MINSIZE - 1; // 비트 마스크: 해시 테이블 크기 - 1 + so->table = so->smalltable; // 내장 작은 테이블 사용 + so->hash = -1; // 해시값 (-1: 아직 계산되지 않음을 나타냄) + so->finger = 0; // 순회 시 사용하는 인덱스 + so->weakreflist = NULL; // 약한 참조 리스트 + + // iterable 제공된 경우 set에 추가 + if (iterable != NULL) { + if (set_update_internal(so, iterable)) { + Py_DECREF(so); + return NULL; + } + } + + return (PyObject *)so; +} +``` +```c++ +static int +set_update_internal(PySetObject *so, PyObject *other) +{ + PyObject *key, *it; + + if (PyAnySet_Check(other)) + return set_merge(so, other); + + if (PyDict_CheckExact(other)) { + PyObject *value; + Py_ssize_t pos = 0; + Py_hash_t hash; + Py_ssize_t dictsize = PyDict_GET_SIZE(other); + + /* Do one big resize at the start, rather than + * incrementally resizing as we insert new keys. Expect + * that there will be no (or few) overlapping keys. + */ + if (dictsize < 0) + return -1; + if ((so->fill + dictsize)*5 >= so->mask*3) { + if (set_table_resize(so, (so->used + dictsize)*2) != 0) + return -1; + } + while (_PyDict_Next(other, &pos, &key, &value, &hash)) { + if (set_add_entry(so, key, hash)) + return -1; + } + return 0; + } + + it = PyObject_GetIter(other); + if (it == NULL) + return -1; + + while ((key = PyIter_Next(it)) != NULL) { + if (set_add_key(so, key)) { + Py_DECREF(it); + Py_DECREF(key); + return -1; + } + Py_DECREF(key); + } + Py_DECREF(it); + if (PyErr_Occurred()) + return -1; + return 0; +} +```