1#
2# Support for the API of the multiprocessing package using threads
3#
4# multiprocessing/dummy/__init__.py
5#
6# Copyright (c) 2006-2008, R Oudkerk
7# All rights reserved.
8#
9# Redistribution and use in source and binary forms, with or without
10# modification, are permitted provided that the following conditions
11# are met:
12#
13# 1. Redistributions of source code must retain the above copyright
14#    notice, this list of conditions and the following disclaimer.
15# 2. Redistributions in binary form must reproduce the above copyright
16#    notice, this list of conditions and the following disclaimer in the
17#    documentation and/or other materials provided with the distribution.
18# 3. Neither the name of author nor the names of any contributors may be
19#    used to endorse or promote products derived from this software
20#    without specific prior written permission.
21#
22# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
23# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32# SUCH DAMAGE.
33#
34
35__all__ = [
36    'Process', 'current_process', 'active_children', 'freeze_support',
37    'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Condition',
38    'Event', 'Queue', 'Manager', 'Pipe', 'Pool', 'JoinableQueue'
39    ]
40
41#
42# Imports
43#
44
45import threading
46import sys
47import weakref
48import array
49import itertools
50
51from multiprocessing import TimeoutError, cpu_count
52from multiprocessing.dummy.connection import Pipe
53from threading import Lock, RLock, Semaphore, BoundedSemaphore
54from threading import Event
55from Queue import Queue
56
57#
58#
59#
60
61class DummyProcess(threading.Thread):
62
63    def __init__(self, group=None, target=None, name=None, args=(), kwargs={}):
64        threading.Thread.__init__(self, group, target, name, args, kwargs)
65        self._pid = None
66        self._children = weakref.WeakKeyDictionary()
67        self._start_called = False
68        self._parent = current_process()
69
70    def start(self):
71        assert self._parent is current_process()
72        self._start_called = True
73        if hasattr(self._parent, '_children'):
74            self._parent._children[self] = None
75        threading.Thread.start(self)
76
77    @property
78    def exitcode(self):
79        if self._start_called and not self.is_alive():
80            return 0
81        else:
82            return None
83
84#
85#
86#
87
88class Condition(threading._Condition):
89    notify_all = threading._Condition.notify_all.im_func
90
91#
92#
93#
94
95Process = DummyProcess
96current_process = threading.current_thread
97current_process()._children = weakref.WeakKeyDictionary()
98
99def active_children():
100    children = current_process()._children
101    for p in list(children):
102        if not p.is_alive():
103            children.pop(p, None)
104    return list(children)
105
106def freeze_support():
107    pass
108
109#
110#
111#
112
113class Namespace(object):
114    def __init__(self, **kwds):
115        self.__dict__.update(kwds)
116    def __repr__(self):
117        items = self.__dict__.items()
118        temp = []
119        for name, value in items:
120            if not name.startswith('_'):
121                temp.append('%s=%r' % (name, value))
122        temp.sort()
123        return 'Namespace(%s)' % str.join(', ', temp)
124
125dict = dict
126list = list
127
128def Array(typecode, sequence, lock=True):
129    return array.array(typecode, sequence)
130
131class Value(object):
132    def __init__(self, typecode, value, lock=True):
133        self._typecode = typecode
134        self._value = value
135    def _get(self):
136        return self._value
137    def _set(self, value):
138        self._value = value
139    value = property(_get, _set)
140    def __repr__(self):
141        return '<%s(%r, %r)>'%(type(self).__name__,self._typecode,self._value)
142
143def Manager():
144    return sys.modules[__name__]
145
146def shutdown():
147    pass
148
149def Pool(processes=None, initializer=None, initargs=()):
150    from multiprocessing.pool import ThreadPool
151    return ThreadPool(processes, initializer, initargs)
152
153JoinableQueue = Queue
154