# PySoy _internals.Children class # # Copyright (C) 2006,2007,2008 PySoy Group # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program; if not, see http://www.gnu.org/licenses # # $Id$ cimport py cdef class Children : '''PySoy Children This is a thread-safe C array of Python objects for "Parent" classes. It's append, index, and remove methods are identical to Python lists. The raise, lower, top, bottom, and move methods move an object in the array. The lock and unlock methods control the mutex. ''' ############################################################################ # # Python functions # def __cinit__(self, name='') : cdef int _i, _l # self._size = 1 self._current = 0 self._iters = 0 self._list = py.PyMem_Malloc(sizeof(void*)) self._lockMain = py.PyThread_allocate_lock() self._lockIter = py.PyThread_allocate_lock() # # Copy name to self._name _l = len(name) self._name = py.PyMem_Malloc(len(name)+1) for _i from 0 <= _i < _l : self._name[_i] = name[_i] self._name[_l] = 0 def __dealloc__(self) : py.PyMem_Free(self._list) py.PyThread_free_lock(self._lockMain) py.PyThread_free_lock(self._lockIter) ############################################################################ # # Internal C functions # cdef int _offset(self, void* _child) nogil : cdef int _i for _i from 0 <= _i < self._current : if self._list[_i] == _child : return _i return -1 cdef void _swap(self, int _first, int _second) nogil : cdef void* _sibling _sibling = self._list[_first] self._list[_first] = self._list[_second] self._list[_second] = _sibling ############################################################################ # # External C functions # cdef void _append(self, void* _child) nogil : py.PyThread_acquire_lock(self._lockMain, 1) # # Wait until all iterations are complete while self._iters != 0 : _sleep(1) if self._size == self._current : self._size = self._size * 2 self._list = py.PyMem_Realloc(self._list, sizeof(void*) * (self._size)) self._list[self._current] = _child self._current = self._current + 1 py.PyThread_release_lock(self._lockMain) cdef void _top(self, void* _child) nogil : cdef int _offset py.PyThread_acquire_lock(self._lockMain, 1) # Wait until all iterations are complete while self._iters != 0 : _sleep(1) _offset = self._offset(_child) if _offset == -1 : return if _offset < self._current - 1 : # Swap the item with the one at the top of the list - # Probably not the expected semantics! self._swap(_offset, self._current - 1) py.PyThread_release_lock(self._lockMain) cdef void _bottom(self, void* _child) nogil : cdef int _offset py.PyThread_acquire_lock(self._lockMain, 1) # Wait until all iterations are complete while self._iters != 0 : _sleep(1) _offset = self._offset(_child) if _offset > 0 : # Swap the item with the one at the bottom of the list - # Probably not the expected semantics! self._swap(_offset, 0) py.PyThread_release_lock(self._lockMain) cdef void _empty(self) nogil : py.PyThread_acquire_lock(self._lockMain, 1) # Wait until all iterations are complete while self._iters != 0 : _sleep(1) py.PyMem_Free(self._list) self._size = 1 self._current = 0 self._list = py.PyMem_Malloc(sizeof(void*)) py.PyThread_release_lock(self._lockMain) cdef int _index(self, void* _child) nogil : cdef int _i self._iterStart() _i = self._offset(_child) self._iterDone() return _i cdef void _iterDone(self) nogil : py.PyThread_acquire_lock(self._lockIter, 1) self._iters = self._iters - 1 py.PyThread_release_lock(self._lockIter) cdef void _iterStart(self) nogil : py.PyThread_acquire_lock(self._lockMain, 1) py.PyThread_acquire_lock(self._lockIter, 1) self._iters = self._iters + 1 py.PyThread_release_lock(self._lockIter) py.PyThread_release_lock(self._lockMain) cdef void _lower(self, void* _child) nogil : cdef int _offset py.PyThread_acquire_lock(self._lockMain, 1) # Wait until all iterations are complete while self._iters != 0 : _sleep(1) _offset = self._offset(_child) if _offset > 0 : self._swap(_offset, _offset - 1) py.PyThread_release_lock(self._lockMain) cdef void _raise(self, void* _child) nogil : cdef int _offset py.PyThread_acquire_lock(self._lockMain, 1) # Wait until all iterations are complete while self._iters != 0 : _sleep(1) _offset = self._offset(_child) if _offset == -1 : return if _offset < self._current-1 : self._swap(_offset, _offset + 1) py.PyThread_release_lock(self._lockMain) cdef void _remove(self, void* _child) nogil : cdef int _i, _offset py.PyThread_acquire_lock(self._lockMain, 1) # # Wait until all iterations are complete while self._iters != 0 : _sleep(1) _offset = self._offset(_child) if _offset == -1 : py.PyThread_release_lock(self._lockMain) return for _i from _offset <= _i < (self._current - 1) : self._list[_i] = self._list[_i + 1] self._current = self._current - 1 py.PyThread_release_lock(self._lockMain)