3 # Copyright 2008,2009 Free Software Foundation, Inc.
5 # This file is part of GNU Radio
7 # GNU Radio is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3, or (at your option)
12 # GNU Radio is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with GNU Radio; see the file COPYING. If not, write to
19 # the Free Software Foundation, Inc., 51 Franklin Street,
20 # Boston, MA 02110-1301, USA.
24 Abstract GNU Radio publisher/subscriber interface
26 This is a proof of concept implementation, will likely change significantly.
31 self._publishers = { }
32 self._subscribers = { }
35 def __missing__(self, key, value=None):
36 dict.__setitem__(self, key, value)
37 self._publishers[key] = None
38 self._subscribers[key] = []
39 self._proxies[key] = None
41 def __setitem__(self, key, val):
42 if not self.has_key(key):
43 self.__missing__(key, val)
44 elif self._proxies[key] is not None:
45 (p, newkey) = self._proxies[key]
48 dict.__setitem__(self, key, val)
49 for sub in self._subscribers[key]:
50 # Note this means subscribers will get called in the thread
51 # context of the 'set' caller.
54 def __getitem__(self, key):
55 if not self.has_key(key): self.__missing__(key)
56 if self._proxies[key] is not None:
57 (p, newkey) = self._proxies[key]
59 elif self._publishers[key] is not None:
60 return self._publishers[key]()
62 return dict.__getitem__(self, key)
64 def publish(self, key, publisher):
65 if not self.has_key(key): self.__missing__(key)
66 if self._proxies[key] is not None:
67 (p, newkey) = self._proxies[key]
68 p.publish(newkey, publisher)
70 self._publishers[key] = publisher
72 def subscribe(self, key, subscriber):
73 if not self.has_key(key): self.__missing__(key)
74 if self._proxies[key] is not None:
75 (p, newkey) = self._proxies[key]
76 p.subscribe(newkey, subscriber)
78 self._subscribers[key].append(subscriber)
80 def unpublish(self, key):
81 if self._proxies[key] is not None:
82 (p, newkey) = self._proxies[key]
85 self._publishers[key] = None
87 def unsubscribe(self, key, subscriber):
88 if self._proxies[key] is not None:
89 (p, newkey) = self._proxies[key]
90 p.unsubscribe(newkey, subscriber)
92 self._subscribers[key].remove(subscriber)
94 def proxy(self, key, p, newkey=None):
95 if not self.has_key(key): self.__missing__(key)
96 if newkey is None: newkey = key
97 self._proxies[key] = (p, newkey)
99 def unproxy(self, key):
100 self._proxies[key] = None
103 if __name__ == "__main__":
107 # Non-existent key gets auto-created with None value
108 print "Auto-created key 'foo' value:", o['foo']
110 # Add some subscribers
111 # First is a bare function
113 print "len=%i" % (len(x), )
114 o.subscribe('foo', print_len)
116 # The second is a class member function
117 class subber(object):
118 def __init__(self, param):
120 def printer(self, x):
121 print self._param, `x`
123 o.subscribe('foo', s.printer)
125 # The third is a lambda function
126 o.subscribe('foo', lambda x: sys.stdout.write('val='+`x`+'\n'))
128 # Update key 'foo', will notify subscribers
129 print "Updating 'foo' with three subscribers:"
132 # Remove first subscriber
133 o.unsubscribe('foo', print_len)
135 # Update now will only trigger second and third subscriber
136 print "Updating 'foo' after removing a subscriber:"
139 # Publish a key as a function, in this case, a lambda function
140 o.publish('baz', lambda : 42)
141 print "Published value of 'baz':", o['baz']
146 # This will return None, as there is no publisher
147 print "Value of 'baz' with no publisher:", o['baz']
149 # Set 'baz' key, it gets cached
152 # Now will return cached value, since no provider
153 print "Cached value of 'baz' after being set:", o['baz']