root / trunk / pysoy / src / _internals / Children.pym

Revision 1265, 6.0 kB (checked in by ArcRiley, 7 weeks ago)

Pyrex 0.9.8.2 fixes :

  • now requires 0.9.8.2
  • nogil goes everywhere
  • a few functions got GIL-cleaned
  • still doesn't compile, but many steps closer
  • Property svn:keywords set to Id
Line 
1# PySoy _internals.Children class
2#
3# Copyright (C) 2006,2007,2008 PySoy Group
4#
5#  This program is free software; you can redistribute it and/or modify
6#  it under the terms of the GNU Affero General Public License as published
7#  by the Free Software Foundation, either version 3 of the License, or
8#  (at your option) any later version.
9#
10#  This program is distributed in the hope that it will be useful,
11#  but WITHOUT ANY WARRANTY; without even the implied warranty of
12#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13#  GNU Affero General Public License for more details.
14#
15#  You should have received a copy of the GNU Affero General Public License
16#  along with this program; if not, see http://www.gnu.org/licenses
17#
18# $Id$
19
20cimport py
21
22cdef class Children :
23  '''PySoy Children
24
25    This is a thread-safe C array of Python objects for "Parent" classes.
26    It's append, index, and remove methods are identical to Python lists.
27    The raise, lower, top, bottom, and move methods move an object in the array.
28    The lock and unlock methods control the mutex.
29  '''
30
31  ############################################################################
32  #
33  # Python functions
34  #
35
36  def __cinit__(self, name='') :
37    cdef int _i, _l
38    #
39    self._size     = 1
40    self._current  = 0
41    self._iters    = 0
42    self._list     = <void**> py.PyMem_Malloc(sizeof(void*))
43    self._lockMain = py.PyThread_allocate_lock()
44    self._lockIter = py.PyThread_allocate_lock()
45    #
46    # Copy name to self._name
47    _l = len(name)
48    self._name     = <char*> py.PyMem_Malloc(len(name)+1)
49    for _i from 0 <= _i < _l :
50      self._name[_i] = name[_i]
51    self._name[_l] = 0
52
53
54  def __dealloc__(self) :
55    py.PyMem_Free(self._list)
56    py.PyThread_free_lock(self._lockMain)
57    py.PyThread_free_lock(self._lockIter)
58
59
60  ############################################################################
61  #
62  # Internal C functions
63  #
64
65  cdef int _offset(self, void* _child) nogil :
66    cdef int _i
67    for _i from 0 <= _i < self._current :
68      if self._list[_i] == _child :
69        return _i
70    return -1
71
72
73  cdef void _swap(self, int _first, int _second) nogil :
74    cdef void* _sibling
75    _sibling = self._list[_first]
76    self._list[_first] = self._list[_second]
77    self._list[_second] = _sibling
78
79
80  ############################################################################
81  #
82  # External C functions
83  #
84
85  cdef void _append(self, void* _child) nogil :
86    py.PyThread_acquire_lock(self._lockMain, 1)
87    #
88    # Wait until all iterations are complete
89    while self._iters != 0 :
90      _sleep(1)
91    if self._size == self._current :
92      self._size = self._size * 2
93      self._list = <void**> py.PyMem_Realloc(self._list,
94                                             sizeof(void*) * (self._size))
95    self._list[self._current] = <void*> _child
96    self._current = self._current + 1
97    py.PyThread_release_lock(self._lockMain)
98
99
100  cdef void _top(self, void* _child) nogil :
101    cdef int _offset
102    py.PyThread_acquire_lock(self._lockMain, 1)
103    # Wait until all iterations are complete
104    while self._iters != 0 :
105      _sleep(1)
106    _offset = self._offset(_child)
107    if _offset == -1 :
108      return 
109    if _offset < self._current - 1 :
110      # Swap the item with the one at the top of the list -
111      # Probably not the expected semantics!
112      self._swap(_offset, self._current - 1)
113    py.PyThread_release_lock(self._lockMain)
114
115
116  cdef void _bottom(self, void* _child) nogil :
117    cdef int _offset
118    py.PyThread_acquire_lock(self._lockMain, 1)
119    # Wait until all iterations are complete
120    while self._iters != 0 :
121      _sleep(1)
122    _offset = self._offset(_child)
123    if _offset > 0 :
124      # Swap the item with the one at the bottom of the list -
125      # Probably not the expected semantics!
126      self._swap(_offset, 0)
127    py.PyThread_release_lock(self._lockMain)
128
129
130  cdef void _empty(self) nogil :
131    py.PyThread_acquire_lock(self._lockMain, 1)
132    # Wait until all iterations are complete
133    while self._iters != 0 :
134      _sleep(1)
135    py.PyMem_Free(self._list)
136    self._size = 1
137    self._current = 0
138    self._list = <void**> py.PyMem_Malloc(sizeof(void*))
139    py.PyThread_release_lock(self._lockMain)
140
141
142  cdef int _index(self, void* _child) nogil :
143    cdef int _i
144    self._iterStart()
145    _i = self._offset(_child)
146    self._iterDone()
147    return _i
148   
149
150  cdef void _iterDone(self) nogil :
151    py.PyThread_acquire_lock(self._lockIter, 1)
152    self._iters = self._iters - 1
153    py.PyThread_release_lock(self._lockIter)
154 
155
156  cdef void _iterStart(self) nogil :
157    py.PyThread_acquire_lock(self._lockMain, 1)
158    py.PyThread_acquire_lock(self._lockIter, 1)
159    self._iters = self._iters + 1
160    py.PyThread_release_lock(self._lockIter)
161    py.PyThread_release_lock(self._lockMain)
162
163
164  cdef void _lower(self, void* _child) nogil :
165    cdef int _offset
166    py.PyThread_acquire_lock(self._lockMain, 1)
167    # Wait until all iterations are complete
168    while self._iters != 0 :
169      _sleep(1)
170    _offset = self._offset(_child)
171    if _offset > 0 :
172      self._swap(_offset, _offset - 1)
173    py.PyThread_release_lock(self._lockMain)
174
175
176  cdef void _raise(self, void* _child) nogil :
177    cdef int _offset
178    py.PyThread_acquire_lock(self._lockMain, 1)
179    # Wait until all iterations are complete
180    while self._iters != 0 :
181      _sleep(1)
182    _offset = self._offset(_child)
183    if _offset == -1 :
184      return 
185    if _offset < self._current-1 :
186      self._swap(_offset, _offset + 1)
187    py.PyThread_release_lock(self._lockMain)
188
189
190  cdef void _remove(self, void* _child) nogil :
191    cdef int _i, _offset
192    py.PyThread_acquire_lock(self._lockMain, 1)
193    #
194    # Wait until all iterations are complete
195    while self._iters != 0 :
196      _sleep(1)
197    _offset = self._offset(_child)
198    if _offset == -1 :
199      py.PyThread_release_lock(self._lockMain)
200      return
201    for _i from _offset <= _i < (self._current - 1) :
202      self._list[_i] = self._list[_i + 1]
203    self._current = self._current - 1
204    py.PyThread_release_lock(self._lockMain)
205
Note: See TracBrowser for help on using the browser.