Skip to content

Commit 3f27537

Browse files
authored
Merge pull request #22 from openzim/fix_multi_thread
2 parents 4401c19 + e15448e commit 3f27537

File tree

3 files changed

+28
-27
lines changed

3 files changed

+28
-27
lines changed

libzim/lib.cxx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ ZimArticleWrapper::ZimArticleWrapper(PyObject *obj) : m_obj(obj)
2929

3030
ZimArticleWrapper::~ZimArticleWrapper()
3131
{
32+
PyGILState_STATE gstate;
33+
gstate = PyGILState_Ensure();
3234
Py_XDECREF(this->m_obj);
35+
PyGILState_Release(gstate);
3336
}
3437

3538
std::string ZimArticleWrapper::callCythonReturnString(std::string methodName) const

libzim/libzim.pxd

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ cdef extern from "lib.h":
3939

4040
cdef cppclass ZimCreatorWrapper:
4141
@staticmethod
42-
ZimCreatorWrapper *create(string fileName, string mainPage, string fullTextIndexLanguage, int minChunkSize) except +
43-
void addArticle(shared_ptr[ZimArticleWrapper] article) except +
44-
void finalize() except +
42+
ZimCreatorWrapper *create(string fileName, string mainPage, string fullTextIndexLanguage, int minChunkSize) nogil except +
43+
void addArticle(shared_ptr[ZimArticleWrapper] article) nogil except +
44+
void finalize() nogil except +
4545
Url getMainUrl() except +
4646
void setMainUrl(string) except +

libzim/libzim.pyx

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,14 @@ from collections import defaultdict
1717

1818
cdef class ZimBlob:
1919
cdef Blob* c_blob
20-
21-
def __init__(self, content):
20+
cdef bytes ref_content
2221

22+
def __cinit__(self, content):
2323
if isinstance(content, str):
24-
ref_content = content.encode('UTF-8')
24+
self.ref_content = content.encode('UTF-8')
2525
else:
26-
ref_content = content
27-
28-
self.c_blob = new Blob(<char *> ref_content, len(ref_content))
26+
self.ref_content = content
27+
self.c_blob = new Blob(<char *> self.ref_content, len(self.ref_content))
2928

3029
def __dealloc__(self):
3130
if self.c_blob != NULL:
@@ -37,12 +36,8 @@ cdef class ZimBlob:
3736
#########################
3837

3938
cdef class ZimArticle:
40-
cdef ZimArticleWrapper* c_article
4139
cdef ZimBlob blob
4240

43-
def __init__(self):
44-
self.c_article = new ZimArticleWrapper(<cpy_ref.PyObject*>self)
45-
4641
def get_url(self):
4742
raise NotImplementedError
4843

@@ -68,19 +63,17 @@ cdef class ZimArticle:
6863
raise NotImplementedError
6964

7065
def _get_data(self):
71-
self.blob = self.get_data()
66+
if self.blob is None:
67+
self.blob = self.get_data()
7268
return self.blob
7369

7470
def get_data(self):
7571
raise NotImplementedError
7672

77-
@property
78-
def mimetype(self):
79-
return self.c_article.getMimeType().decode('UTF-8')
8073

8174
#------ Helper for pure virtual methods --------
8275

83-
cdef get_article_method_from_object_ptr(void *ptr, string method, int *error):
76+
cdef get_article_method_from_object_ptr(void *ptr, string method, int *error) with gil:
8477
cdef ZimArticle art = <ZimArticle>(ptr)
8578
try:
8679
func = getattr(art, method.decode('UTF-8'))
@@ -94,26 +87,26 @@ cdef get_article_method_from_object_ptr(void *ptr, string method, int *error):
9487
#------- ZimArticle pure virtual methods --------
9588

9689
cdef public api:
97-
string string_cy_call_fct(void *ptr, string method, int *error):
90+
string string_cy_call_fct(void *ptr, string method, int *error) with gil:
9891
"""Lookup and execute a pure virtual method on ZimArticle returning a string"""
9992
func = get_article_method_from_object_ptr(ptr, method, error)
10093
ret_str = func()
10194
return ret_str.encode('UTF-8')
10295

103-
Blob blob_cy_call_fct(void *ptr, string method, int *error):
96+
Blob blob_cy_call_fct(void *ptr, string method, int *error) with gil:
10497
"""Lookup and execute a pure virtual method on ZimArticle returning a Blob"""
10598
cdef ZimBlob blob
10699

107100
func = get_article_method_from_object_ptr(ptr, method, error)
108101
blob = func()
109102
return dereference(blob.c_blob)
110103

111-
bool bool_cy_call_fct(void *ptr, string method, int *error):
104+
bool bool_cy_call_fct(void *ptr, string method, int *error) with gil:
112105
"""Lookup and execute a pure virtual method on ZimArticle returning a bool"""
113106
func = get_article_method_from_object_ptr(ptr, method, error)
114107
return func()
115108

116-
uint64_t int_cy_call_fct(void *ptr, string method, int *error):
109+
uint64_t int_cy_call_fct(void *ptr, string method, int *error) with gil:
117110
"""Lookup and execute a pure virtual method on ZimArticle returning an int"""
118111
func = get_article_method_from_object_ptr(ptr, method, error)
119112
return <uint64_t> func()
@@ -226,11 +219,13 @@ cdef class ZimCreator:
226219
self._main_page = self.c_creator.getMainUrl().getLongUrl().decode("UTF-8", "strict")
227220
self._index_language = index_language
228221
self._min_chunk_size = min_chunk_size
229-
self._metadata = {k:None for k in MANDATORY_METADATA_KEYS}
222+
self._metadata = {k:b"" for k in MANDATORY_METADATA_KEYS}
230223

231224
self._article_counter = defaultdict(int)
232225
self.update_metadata(date=datetime.date.today(), language= index_language)
233226

227+
def __dealloc__(self):
228+
del self.c_creator
234229

235230
@property
236231
def filename(self):
@@ -293,7 +288,7 @@ cdef class ZimCreator:
293288
# default dict update
294289
self._article_counter[article.get_mime_type().strip()] += 1
295290

296-
def add_article(self, ZimArticle article not None):
291+
def add_article(self, article not None):
297292
"""Add a ZimArticle to the Creator object.
298293
299294
Parameters
@@ -311,9 +306,11 @@ cdef class ZimCreator:
311306
raise RuntimeError("ZimCreator already finalized")
312307

313308
# Make a shared pointer to ZimArticleWrapper from the ZimArticle object (dereference internal c_article)
314-
cdef shared_ptr[ZimArticleWrapper] art = make_shared[ZimArticleWrapper](dereference(article.c_article));
309+
cdef shared_ptr[ZimArticleWrapper] art = shared_ptr[ZimArticleWrapper](
310+
new ZimArticleWrapper(<PyObject*>article));
315311
try:
316-
self.c_creator.addArticle(art)
312+
with nogil:
313+
self.c_creator.addArticle(art)
317314
except:
318315
raise
319316
else:
@@ -337,7 +334,8 @@ cdef class ZimCreator:
337334
raise RuntimeError("ZimCreator already finalized")
338335

339336
self.write_metadata(self._get_metadata())
340-
self.c_creator.finalize()
337+
with nogil:
338+
self.c_creator.finalize()
341339
self._finalized = True
342340

343341
def __repr__(self):

0 commit comments

Comments
 (0)