viff

changeset 1191:8ec45943c12a

Merged with Marcel.
author Martin Geisler <mg@cs.au.dk>
date Wed, 27 May 2009 22:29:31 +0200
parents b5eea8738968 b1ee0d5e116f
children c1259ceebc55
files viff/test/util.py
diffstat 30 files changed, 229 insertions(+), 6 deletions(-) [+]
line diff
     1.1 --- a/apps/aes.py	Wed May 20 09:34:42 2009 +0200
     1.2 +++ b/apps/aes.py	Wed May 27 22:29:31 2009 +0200
     1.3 @@ -23,6 +23,8 @@
     1.4  import time
     1.5  from optparse import OptionParser
     1.6  
     1.7 +import viff.reactor
     1.8 +viff.reactor.install()
     1.9  from twisted.internet import reactor
    1.10  
    1.11  from viff.field import GF256
    1.12 @@ -81,7 +83,7 @@
    1.13          rt.shutdown()
    1.14  
    1.15      g = gather_shares(opened_ciphertext)
    1.16 -    rt.schedule_callback(g, fin)
    1.17 +    rt.schedule_complex_callback(g, fin)
    1.18  
    1.19  def share_key(rt):
    1.20      key =  []
    1.21 @@ -94,7 +96,7 @@
    1.22              key.append(rt.input([inputter], GF256))
    1.23  
    1.24      s = rt.synchronize()
    1.25 -    s.addCallback(encrypt, rt, key)
    1.26 +    rt.schedule_complex_callback(s, encrypt, rt, key)
    1.27  
    1.28  rt = create_runtime(id, players, 1, options)
    1.29  rt.addCallback(share_key)
     2.1 --- a/apps/aes_inversion.py	Wed May 20 09:34:42 2009 +0200
     2.2 +++ b/apps/aes_inversion.py	Wed May 27 22:29:31 2009 +0200
     2.3 @@ -24,6 +24,8 @@
     2.4  import time
     2.5  from optparse import OptionParser
     2.6  
     2.7 +import viff.reactor
     2.8 +viff.reactor.install()
     2.9  from twisted.internet import reactor
    2.10  
    2.11  from viff.field import GF256
     3.1 --- a/apps/beginner.py	Wed May 20 09:34:42 2009 +0200
     3.2 +++ b/apps/beginner.py	Wed May 27 22:29:31 2009 +0200
     3.3 @@ -37,6 +37,8 @@
     3.4  # Some useful imports.
     3.5  import sys
     3.6  
     3.7 +import viff.reactor
     3.8 +viff.reactor.install()
     3.9  from twisted.internet import reactor
    3.10  
    3.11  from viff.field import GF
     4.1 --- a/apps/benchmark.py	Wed May 20 09:34:42 2009 +0200
     4.2 +++ b/apps/benchmark.py	Wed May 27 22:29:31 2009 +0200
     4.3 @@ -60,6 +60,8 @@
     4.4  import operator
     4.5  from pprint import pformat
     4.6  
     4.7 +import viff.reactor
     4.8 +viff.reactor.install()
     4.9  from twisted.internet import reactor
    4.10  
    4.11  from viff.field import GF, GF256, FakeGF
    4.12 @@ -176,7 +178,7 @@
    4.13              # run with no preprocessing. So they are quite brittle.
    4.14              if self.operation == operator.mul:
    4.15                  key = ("generate_triples", (Zp,))
    4.16 -                desc = [(i, 1, 0) for i in range(2, 2 + count)]
    4.17 +                desc = [(i, 1, 0) for i in range(3, 3 + count)]
    4.18                  program_desc.setdefault(key, []).extend(desc)
    4.19              elif isinstance(self.rt, ComparisonToft05Mixin):
    4.20                  key = ("generate_triples", (GF256,))
     5.1 --- a/apps/compare.py	Wed May 20 09:34:42 2009 +0200
     5.2 +++ b/apps/compare.py	Wed May 27 22:29:31 2009 +0200
     5.3 @@ -20,6 +20,8 @@
     5.4  import sys
     5.5  import random
     5.6  
     5.7 +import viff.reactor
     5.8 +viff.reactor.install()
     5.9  from twisted.internet import reactor
    5.10  from twisted.internet.defer import gatherResults
    5.11  
     6.1 --- a/apps/divide.py	Wed May 20 09:34:42 2009 +0200
     6.2 +++ b/apps/divide.py	Wed May 27 22:29:31 2009 +0200
     6.3 @@ -32,6 +32,8 @@
     6.4  """
     6.5  
     6.6  from optparse import OptionParser
     6.7 +import viff.reactor
     6.8 +viff.reactor.install()
     6.9  from twisted.internet import reactor
    6.10  
    6.11  from viff.field import GF
     7.1 --- a/apps/double-auction/double-auction.py	Wed May 20 09:34:42 2009 +0200
     7.2 +++ b/apps/double-auction/double-auction.py	Wed May 27 22:29:31 2009 +0200
     7.3 @@ -38,6 +38,8 @@
     7.4  import time, random
     7.5  from optparse import OptionParser
     7.6  
     7.7 +import viff.reactor
     7.8 +viff.reactor.install()
     7.9  from twisted.internet import reactor
    7.10  
    7.11  from viff import shamir
     8.1 --- a/apps/equality.py	Wed May 20 09:34:42 2009 +0200
     8.2 +++ b/apps/equality.py	Wed May 27 22:29:31 2009 +0200
     8.3 @@ -31,6 +31,8 @@
     8.4  """
     8.5  
     8.6  from optparse import OptionParser
     8.7 +import viff.reactor
     8.8 +viff.reactor.install()
     8.9  from twisted.internet import reactor
    8.10  
    8.11  from viff.field import GF
     9.1 --- a/apps/eval-poly.py	Wed May 20 09:34:42 2009 +0200
     9.2 +++ b/apps/eval-poly.py	Wed May 27 22:29:31 2009 +0200
     9.3 @@ -26,6 +26,8 @@
     9.4  from time import time
     9.5  
     9.6  from optparse import OptionParser
     9.7 +import viff.reactor
     9.8 +viff.reactor.install()
     9.9  from twisted.internet import reactor
    9.10  
    9.11  from viff.field import GF
    10.1 --- a/apps/gc-test.py	Wed May 20 09:34:42 2009 +0200
    10.2 +++ b/apps/gc-test.py	Wed May 27 22:29:31 2009 +0200
    10.3 @@ -26,6 +26,8 @@
    10.4  import sys
    10.5  from time import time
    10.6  
    10.7 +import viff.reactor
    10.8 +viff.reactor.install()
    10.9  from twisted.internet import reactor
   10.10  
   10.11  from viff.field import GF
    11.1 --- a/apps/int-bit-conversion.py	Wed May 20 09:34:42 2009 +0200
    11.2 +++ b/apps/int-bit-conversion.py	Wed May 27 22:29:31 2009 +0200
    11.3 @@ -19,6 +19,8 @@
    11.4  
    11.5  import sys
    11.6  
    11.7 +import viff.reactor
    11.8 +viff.reactor.install()
    11.9  from twisted.internet import reactor
   11.10  
   11.11  from viff.field import GF, GF256
    12.1 --- a/apps/millionaires.py	Wed May 20 09:34:42 2009 +0200
    12.2 +++ b/apps/millionaires.py	Wed May 27 22:29:31 2009 +0200
    12.3 @@ -32,6 +32,8 @@
    12.4  # the example with '--help' for help with the command line options.
    12.5  
    12.6  from optparse import OptionParser
    12.7 +import viff.reactor
    12.8 +viff.reactor.install()
    12.9  from twisted.internet import reactor
   12.10  
   12.11  from viff.field import GF
    13.1 --- a/apps/multiply.py	Wed May 20 09:34:42 2009 +0200
    13.2 +++ b/apps/multiply.py	Wed May 27 22:29:31 2009 +0200
    13.3 @@ -18,6 +18,8 @@
    13.4  # License along with VIFF. If not, see <http://www.gnu.org/licenses/>.
    13.5  
    13.6  from optparse import OptionParser
    13.7 +import viff.reactor
    13.8 +viff.reactor.install()
    13.9  from twisted.internet import reactor
   13.10  
   13.11  from viff.field import GF
    14.1 --- a/apps/online-comparison-benchmark.py	Wed May 20 09:34:42 2009 +0200
    14.2 +++ b/apps/online-comparison-benchmark.py	Wed May 27 22:29:31 2009 +0200
    14.3 @@ -21,6 +21,8 @@
    14.4  import signal
    14.5  from optparse import OptionParser
    14.6  
    14.7 +import viff.reactor
    14.8 +viff.reactor.install()
    14.9  from twisted.internet import reactor
   14.10  from twisted.internet.defer import DeferredList, gatherResults
   14.11  
    15.1 --- a/apps/paillier.py	Wed May 20 09:34:42 2009 +0200
    15.2 +++ b/apps/paillier.py	Wed May 27 22:29:31 2009 +0200
    15.3 @@ -26,6 +26,8 @@
    15.4  
    15.5  import sys
    15.6  
    15.7 +import viff.reactor
    15.8 +viff.reactor.install()
    15.9  from twisted.internet import reactor
   15.10  
   15.11  from viff.field import GF
    16.1 --- a/apps/prss-and-open.py	Wed May 20 09:34:42 2009 +0200
    16.2 +++ b/apps/prss-and-open.py	Wed May 27 22:29:31 2009 +0200
    16.3 @@ -19,6 +19,8 @@
    16.4  
    16.5  import sys
    16.6  
    16.7 +import viff.reactor
    16.8 +viff.reactor.install()
    16.9  from twisted.internet import reactor
   16.10  from twisted.internet.defer import gatherResults
   16.11  
    17.1 --- a/apps/seq-mul.py	Wed May 20 09:34:42 2009 +0200
    17.2 +++ b/apps/seq-mul.py	Wed May 27 22:29:31 2009 +0200
    17.3 @@ -18,6 +18,8 @@
    17.4  # License along with VIFF. If not, see <http://www.gnu.org/licenses/>.
    17.5  
    17.6  from optparse import OptionParser
    17.7 +import viff.reactor
    17.8 +viff.reactor.install()
    17.9  from twisted.internet import reactor
   17.10  
   17.11  from viff.field import GF
    18.1 --- a/apps/shamir-share-open.py	Wed May 20 09:34:42 2009 +0200
    18.2 +++ b/apps/shamir-share-open.py	Wed May 27 22:29:31 2009 +0200
    18.3 @@ -19,6 +19,8 @@
    18.4  
    18.5  import sys
    18.6  
    18.7 +import viff.reactor
    18.8 +viff.reactor.install()
    18.9  from twisted.internet import reactor
   18.10  
   18.11  from viff.field import GF
    19.1 --- a/apps/share-open.py	Wed May 20 09:34:42 2009 +0200
    19.2 +++ b/apps/share-open.py	Wed May 27 22:29:31 2009 +0200
    19.3 @@ -19,6 +19,8 @@
    19.4  
    19.5  import sys
    19.6  
    19.7 +import viff.reactor
    19.8 +viff.reactor.install()
    19.9  from twisted.internet import reactor
   19.10  
   19.11  from viff.field import GF256
    20.1 --- a/apps/sort.py	Wed May 20 09:34:42 2009 +0200
    20.2 +++ b/apps/sort.py	Wed May 27 22:29:31 2009 +0200
    20.3 @@ -51,6 +51,8 @@
    20.4  
    20.5  from math import log, floor
    20.6  from optparse import OptionParser
    20.7 +import viff.reactor
    20.8 +viff.reactor.install()
    20.9  from twisted.internet import reactor
   20.10  
   20.11  from progressbar import ProgressBar, Percentage, Bar, ETA, ProgressBarWidget
    21.1 --- a/apps/sum.py	Wed May 20 09:34:42 2009 +0200
    21.2 +++ b/apps/sum.py	Wed May 27 22:29:31 2009 +0200
    21.3 @@ -18,6 +18,8 @@
    21.4  # License along with VIFF. If not, see <http://www.gnu.org/licenses/>.
    21.5  
    21.6  from optparse import OptionParser
    21.7 +import viff.reactor
    21.8 +viff.reactor.install()
    21.9  from twisted.internet import reactor
   21.10  
   21.11  from viff.field import GF
    22.1 --- a/apps/two-fields.py	Wed May 20 09:34:42 2009 +0200
    22.2 +++ b/apps/two-fields.py	Wed May 27 22:29:31 2009 +0200
    22.3 @@ -19,6 +19,8 @@
    22.4  
    22.5  import sys
    22.6  
    22.7 +import viff.reactor
    22.8 +viff.reactor.install()
    22.9  from twisted.internet import reactor
   22.10  
   22.11  from viff.field import GF
    23.1 --- a/apps/xor-all.py	Wed May 20 09:34:42 2009 +0200
    23.2 +++ b/apps/xor-all.py	Wed May 27 22:29:31 2009 +0200
    23.3 @@ -19,6 +19,8 @@
    23.4  
    23.5  import sys
    23.6  
    23.7 +import viff.reactor
    23.8 +viff.reactor.install()
    23.9  from twisted.internet import reactor
   23.10  
   23.11  from viff.field import GF256
    24.1 --- a/viff/active.py	Wed May 20 09:34:42 2009 +0200
    24.2 +++ b/viff/active.py	Wed May 27 22:29:31 2009 +0200
    24.3 @@ -70,6 +70,9 @@
    24.4              for protocol in self.protocols.itervalues():
    24.5                  protocol.sendData(pc, data_type, message)
    24.6  
    24.7 +            # do actual communication
    24.8 +            self.activate_reactor()
    24.9 +
   24.10          def echo_received(message, peer_id):
   24.11              # This is called when we receive an echo message. It
   24.12              # updates the echo count for the message and enters the
   24.13 @@ -133,6 +136,8 @@
   24.14              d_send = Deferred().addCallback(send_received)
   24.15              self._expect_data(sender, SEND, d_send)
   24.16  
   24.17 +        # do actual communication
   24.18 +        self.activate_reactor()
   24.19  
   24.20          return result
   24.21  
   24.22 @@ -261,6 +266,9 @@
   24.23                  # first T shares.
   24.24                  return rvec[:T]
   24.25  
   24.26 +            # do actual communication
   24.27 +            self.activate_reactor()
   24.28 +
   24.29          result = gather_shares(svec[T:])
   24.30          self.schedule_callback(result, exchange)
   24.31          return result
   24.32 @@ -361,6 +369,9 @@
   24.33                  # first T shares.
   24.34                  return (rvec1[:T], rvec2[:T])
   24.35  
   24.36 +            # do actual communication
   24.37 +            self.activate_reactor()
   24.38 +
   24.39          result = gather_shares([gather_shares(svec1[T:]), gather_shares(svec2[T:])])
   24.40          self.schedule_callback(result, exchange)
   24.41          return result
    25.1 --- a/viff/aes.py	Wed May 20 09:34:42 2009 +0200
    25.2 +++ b/viff/aes.py	Wed May 27 22:29:31 2009 +0200
    25.3 @@ -377,9 +377,9 @@
    25.4                  trigger.addCallback(progress, i, time.time())
    25.5  
    25.6                  if (i < self.rounds - 1):
    25.7 -                    self.runtime.schedule_callback(trigger, round, state, i + 1)
    25.8 +                    self.runtime.schedule_complex_callback(trigger, round, state, i + 1)
    25.9                  else:
   25.10 -                    self.runtime.schedule_callback(trigger, final_round, state)
   25.11 +                    self.runtime.schedule_complex_callback(trigger, final_round, state)
   25.12  
   25.13              prep_progress(i, start_round)
   25.14  
    26.1 --- a/viff/passive.py	Wed May 20 09:34:42 2009 +0200
    26.2 +++ b/viff/passive.py	Wed May 27 22:29:31 2009 +0200
    26.3 @@ -104,6 +104,10 @@
    26.4  
    26.5          result = share.clone()
    26.6          self.schedule_callback(result, exchange)
    26.7 +
    26.8 +        # do actual communication
    26.9 +        self.activate_reactor()
   26.10 +
   26.11          if self.id in receivers:
   26.12              return result
   26.13  
   26.14 @@ -204,6 +208,10 @@
   26.15          result = gather_shares([share_a, share_b])
   26.16          result.addCallback(lambda (a, b): a * b)
   26.17          self.schedule_callback(result, share_recombine)
   26.18 +
   26.19 +        # do actual communication
   26.20 +        self.activate_reactor()
   26.21 +
   26.22          return result
   26.23  
   26.24      def pow(self, share, exponent):
   26.25 @@ -501,6 +509,9 @@
   26.26              else:
   26.27                  results.append(self._expect_share(peer_id, field))
   26.28  
   26.29 +        # do actual communication
   26.30 +        self.activate_reactor()
   26.31 +
   26.32          # Unpack a singleton list.
   26.33          if len(results) == 1:
   26.34              return results[0]
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/viff/reactor.py	Wed May 27 22:29:31 2009 +0200
    27.3 @@ -0,0 +1,55 @@
    27.4 +# -*- coding: utf-8 -*-
    27.5 +#
    27.6 +# Copyright 2009 VIFF Development Team.
    27.7 +#
    27.8 +# This file is part of VIFF, the Virtual Ideal Functionality Framework.
    27.9 +#
   27.10 +# VIFF is free software: you can redistribute it and/or modify it
   27.11 +# under the terms of the GNU Lesser General Public License (LGPL) as
   27.12 +# published by the Free Software Foundation, either version 3 of the
   27.13 +# License, or (at your option) any later version.
   27.14 +#
   27.15 +# VIFF is distributed in the hope that it will be useful, but WITHOUT
   27.16 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   27.17 +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
   27.18 +# Public License for more details.
   27.19 +#
   27.20 +# You should have received a copy of the GNU Lesser General Public
   27.21 +# License along with VIFF. If not, see <http://www.gnu.org/licenses/>.
   27.22 +
   27.23 +"""VIFF reactor to have control over the scheduling."""
   27.24 +
   27.25 +__docformat__ = "restructuredtext"
   27.26 +
   27.27 +from twisted.internet.selectreactor import SelectReactor
   27.28 +
   27.29 +
   27.30 +class ViffReactor(SelectReactor):
   27.31 +    """VIFF reactor.
   27.32 +
   27.33 +    The only difference to the SelectReactor is the loop call.
   27.34 +    From there, doIteration() can be called recursively."""
   27.35 +
   27.36 +    def __init__(self):
   27.37 +        SelectReactor.__init__(self)
   27.38 +        self.loopCall = lambda: None
   27.39 +   
   27.40 +    def setLoopCall(self, f):
   27.41 +        self.loopCall = f
   27.42 +
   27.43 +    def doIteration(self, t):
   27.44 +        # Do the same as in mainLoop() first.
   27.45 +        self.runUntilCurrent()
   27.46 +        t2 = self.timeout()
   27.47 +
   27.48 +        if (t2 is not None):
   27.49 +            t = min(t, self.running and t2)
   27.50 +
   27.51 +        SelectReactor.doIteration(self, t)
   27.52 +        self.loopCall()
   27.53 +
   27.54 +def install():
   27.55 +    """Use the VIFF reactor."""
   27.56 +    reactor = ViffReactor()
   27.57 +    from twisted.internet.main import installReactor
   27.58 +    installReactor(reactor)
    28.1 --- a/viff/runtime.py	Wed May 20 09:34:42 2009 +0200
    28.2 +++ b/viff/runtime.py	Wed May 27 22:29:31 2009 +0200
    28.3 @@ -40,6 +40,7 @@
    28.4  
    28.5  from viff.field import GF256, FieldElement
    28.6  from viff.util import wrapper, rand, deep_wait, track_memory_usage
    28.7 +import viff.reactor
    28.8  
    28.9  from twisted.internet import reactor
   28.10  from twisted.internet.task import LoopingCall
   28.11 @@ -318,7 +319,7 @@
   28.12                      deferred = deq.popleft()
   28.13                      if not deq:
   28.14                          del self.waiting_deferreds[key]
   28.15 -                    deferred.callback(data)
   28.16 +                    self.factory.runtime.handle_deferred_data(deferred, data)
   28.17                  else:
   28.18                      deq = self.incoming_data.setdefault(key, deque())
   28.19                      deq.append(data)
   28.20 @@ -533,6 +534,17 @@
   28.21          # communicating with ourselves.
   28.22          self.add_player(player, None)
   28.23  
   28.24 +        #: Queue of deferreds and data.
   28.25 +        self.deferred_queue = deque()
   28.26 +        self.complex_deferred_queue = deque()
   28.27 +        #: Counter for calls of activate_reactor().
   28.28 +        self.activation_counter = 0
   28.29 +        #: Record the recursion depth.
   28.30 +        self.depth_counter = 0
   28.31 +        self.max_depth = 0
   28.32 +        #: Use deferred queues only if the ViffReactor is running.
   28.33 +        self.using_viff_reactor = isinstance(reactor, viff.reactor.ViffReactor)
   28.34 +
   28.35      def add_player(self, player, protocol):
   28.36          self.players[player.id] = player
   28.37          self.num_players = len(self.players)
   28.38 @@ -617,6 +629,25 @@
   28.39  
   28.40          return deferred.addCallback(callback_wrapper, *args, **kwargs)
   28.41  
   28.42 +    def schedule_complex_callback(self, deferred, func, *args, **kwargs):
   28.43 +        """Schedule a complex callback, i.e. a callback which blocks a
   28.44 +        long time.
   28.45 +
   28.46 +        Consider that the deferred is forked, i.e. if the callback returns
   28.47 +        something to be used afterwards, add further callbacks to the returned
   28.48 +        deferred."""
   28.49 +
   28.50 +        if isinstance(deferred, Share):
   28.51 +            fork = Share(deferred.runtime, deferred.field)
   28.52 +        else:
   28.53 +            fork = Deferred()
   28.54 +
   28.55 +        def queue_callback(result, runtime, fork):
   28.56 +            runtime.complex_deferred_queue.append((fork, result))
   28.57 +
   28.58 +        deferred.addCallback(queue_callback, self, fork)
   28.59 +        return self.schedule_callback(fork, func, *args, **kwargs)
   28.60 +
   28.61      @increment_pc
   28.62      def synchronize(self):
   28.63          """Introduce a synchronization point.
   28.64 @@ -761,6 +792,54 @@
   28.65          Python integer."""
   28.66          raise NotImplemented("Override this abstract method in a subclass.")
   28.67  
   28.68 +    def handle_deferred_data(self, deferred, data):
   28.69 +        """Put deferred and data into the queue if the ViffReactor is running. 
   28.70 +        Otherwise, just execute the callback."""
   28.71 +
   28.72 +        if (self.using_viff_reactor):
   28.73 +            self.deferred_queue.append((deferred, data))
   28.74 +        else:
   28.75 +            deferred.callback(data)
   28.76 +
   28.77 +    def process_deferred_queue(self):
   28.78 +        """Execute the callbacks of the deferreds in the queue.
   28.79 +
   28.80 +        If this function is not called via activate_reactor(), also
   28.81 +        complex callbacks are executed."""
   28.82 +
   28.83 +        self.process_queue(self.deferred_queue)
   28.84 +
   28.85 +        if self.depth_counter == 0:
   28.86 +            self.process_queue(self.complex_deferred_queue)
   28.87 +
   28.88 +    def process_queue(self, queue):
   28.89 +        """Execute the callbacks of the deferreds in *queue*."""
   28.90 +
   28.91 +        while(queue):
   28.92 +            deferred, data = queue.popleft()
   28.93 +            deferred.callback(data)
   28.94 +
   28.95 +    def activate_reactor(self):
   28.96 +        """Activate the reactor to do actual communcation.
   28.97 +
   28.98 +        This is where the recursion happens."""
   28.99 +
  28.100 +        self.activation_counter += 1
  28.101 +
  28.102 +        # setting the number to n makes the reactor called 
  28.103 +        # only every n-th time
  28.104 +        if (self.activation_counter >= 2):
  28.105 +            self.depth_counter += 1
  28.106 +
  28.107 +            if (self.depth_counter > self.max_depth):
  28.108 +                # Record the maximal depth reached.
  28.109 +                self.max_depth = self.depth_counter
  28.110 +
  28.111 +            reactor.doIteration(0)
  28.112 +
  28.113 +            self.depth_counter -= 1
  28.114 +            self.activation_counter = 0
  28.115 +
  28.116  
  28.117  def make_runtime_class(runtime_class=None, mixins=None):
  28.118      """Creates a new runtime class with *runtime_class* as a base
  28.119 @@ -912,6 +991,10 @@
  28.120              print "Will connect to %s" % player
  28.121              connect(player.host, player.port)
  28.122  
  28.123 +    if runtime.using_viff_reactor:
  28.124 +        # Process the deferred queue after every reactor iteration.
  28.125 +        reactor.setLoopCall(runtime.process_deferred_queue)
  28.126 +
  28.127      return result
  28.128  
  28.129  if __name__ == "__main__":
    29.1 --- a/viff/test/__init__.py	Wed May 20 09:34:42 2009 +0200
    29.2 +++ b/viff/test/__init__.py	Wed May 27 22:29:31 2009 +0200
    29.3 @@ -14,3 +14,6 @@
    29.4  #
    29.5  # You should have received a copy of the GNU Lesser General Public
    29.6  # License along with VIFF. If not, see <http://www.gnu.org/licenses/>.
    29.7 +
    29.8 +import viff.reactor
    29.9 +viff.reactor.install()
    30.1 --- a/viff/test/util.py	Wed May 20 09:34:42 2009 +0200
    30.2 +++ b/viff/test/util.py	Wed May 27 22:29:31 2009 +0200
    30.3 @@ -19,6 +19,7 @@
    30.4  
    30.5  from twisted.internet.defer import Deferred, gatherResults, maybeDeferred
    30.6  from twisted.trial.unittest import TestCase
    30.7 +from twisted.internet import reactor
    30.8  
    30.9  from viff.passive import PassiveRuntime
   30.10  from viff.runtime import Share, ShareExchanger, ShareExchangerFactory
   30.11 @@ -134,6 +135,7 @@
   30.12          self.close_sentinels = []
   30.13  
   30.14          self.runtimes = []
   30.15 +        self.real_runtimes = []
   30.16          for id in reversed(range(1, self.num_players+1)):
   30.17              _, players = load_config(configs[id])
   30.18              self.create_loopback_runtime(id, players)
   30.19 @@ -177,6 +179,18 @@
   30.20          # the Runtime, since we want everybody to wait until all
   30.21          # runtimes are ready.
   30.22          self.runtimes.append(result)
   30.23 +        self.real_runtimes.append(runtime)
   30.24 +        self.i = 0
   30.25 +
   30.26 +        # This loop call should ensure the queues of the parties are
   30.27 +        # processed in a more or less fair manner. This is necessary
   30.28 +        # because we have only one reactor for all parties here.
   30.29 +        def loop_call():
   30.30 +            for runtime in self.real_runtimes[self.i:] + self.real_runtimes[:self.i]:
   30.31 +                runtime.process_deferred_queue()
   30.32 +                self.i = (self.i + 1) % len(self.real_runtimes)
   30.33 +
   30.34 +        reactor.setLoopCall(loop_call)
   30.35  
   30.36          for peer_id in players:
   30.37              if peer_id != id: