1

I am trying to add the references of a function in a set (in exposed_setCallback method). The answer is given at the end. Somehow, it is not adding the reference for the second attempt. The links of the source files are: http://pastebin.com/BNde5Cgr

http://pastebin.com/aCi6yMT9

Below is the code:

    import rpyc
    test = ['hi']
    myReferences= set()
    class MyService(rpyc.Service):

      def on_connect(self):
        """Think o+ this as a constructor of the class, but with
        a new name so not to 'overload' the parent's init"""
        self.fn = None


      def exposed_setCallback(self,fn):
       # i = 0
        self.fn = fn  # Saves the remote function for calling later
        print self.fn
        myReferences.add(self.fn)
        #abc.append(i)
        #i+=1
        print myReferences
        for x in myReferences:
          print x
        #print abc



    if __name__ == "__main__":
        # lists are pass by reference, so the same 'test'  
          # will be available to all threads
          # While not required, think about locking!
       from rpyc.utils.server import ThreadedServer
       t = ThreadedServer(MyService, port = 18888)
       t.start()

Answer:
<function myprint at 0x01FFD370>
set([<function myprint at 0x01FFD370>])
<function myprint at 0x01FFD370>
<function myprint at 0x022DD370>
set([<function myprint at 0x022DD370>,

Please help

Megatron
  • 11
  • 2

2 Answers2

0

I think the issue is because you have a ThreadedServer which is of course going to be multithreaded.

However, Python sets are not threadsafe, (they are not allowed to be accessed by multiple threads at the same time) so you need to implement a lock for whenever you access the set. You use the lock with a Python context manager (the with statement), which handle acquiring/releasing the lock for you and the Lock itself can only be acquired by one context manager at a time, thus preventing simultaneous access to your set. See the modified code below:

import rpyc
import threading
test = ['hi']
myReferences= set()
myReferencesLock = threading.Lock()
class MyService(rpyc.Service):

  def on_connect(self):
    """Think o+ this as a constructor of the class, but with
    a new name so not to 'overload' the parent's init"""
    self.fn = None


  def exposed_setCallback(self,fn):
   # i = 0
    self.fn = fn  # Saves the remote function for calling later
    print self.fn
    with myReferencesLock:
        myReferences.add(self.fn)
    #abc.append(i)
    #i+=1
    with myReferencesLock:
        print myReferences
        for x in myReferences:
             print x
    #print abc



if __name__ == "__main__":
    # lists are pass by reference, so the same 'test'  
      # will be available to all threads
      # While not required, think about locking!
   from rpyc.utils.server import ThreadedServer
   t = ThreadedServer(MyService, port = 18888)
   t.start()

Welcome to the world of threaded programming. Make sure you protect data shared between threads with locks!

Community
  • 1
  • 1
three_pineapples
  • 11,579
  • 5
  • 38
  • 75
  • I tried using this.. it didnt work.. can u share ur email address.. I can forward you my 2 python files so that u can have a clearer picture.. Thanks for the help! Highly appreciated.. – Megatron Jan 19 '14 at 07:46
  • Use http://pastebin.com/ to upload the contents of your files, and edit your main post to include the links. That way everyone can see and help. Also, even if this did not solve your problem, it IS still an issue with your code that should be fixed (and would have caused you problems down the line) – three_pineapples Jan 19 '14 at 07:51
  • Done.. also I tried using simple Lock and Rlock.. it didnt work for both the issues... Please suggest.. Thanks! – Megatron Jan 19 '14 at 07:57
-2

If you want to modify a global variable, you should use global statement on top of your function

def exposed_setCallback(self, fn):
    global myReferences
    # i = 0
    self.fn = fn  # Saves the remote function for calling later
    print self.fn
    myReferences.add(self.fn)
saeedgnu
  • 4,110
  • 2
  • 31
  • 48