def t2(): t1launched.wait() # This thread does the committing after t1 started but before it reads the value of refA self.d("** Creating ref") self.refA = Ref(5, None) self.refA.refSet(6)
def testBarge(self): # Barging happens when one transaction tries to do an in-transaction-write to a ref that has # an in-transaction-value from another transaction t1wait = Event() t2wait = Event() self.t1counter = 0 self.t2counter = 0 def t1(): # We do the first in-transaction-write self.refA.refSet(888) # Don't commit yet, we want t2 to run and barge us self.d("* Notify") t2wait.set() self.d("* Wait") t1wait.wait() self.d("* Done") self.t1counter += 1 def t2(): # Wait till t1 has done its write self.d("** Wait") t2wait.wait() # Try to write to the ref # We should try and succeed to barge them: we were started first # and should be long-lived enough self.d("** Before barge") self.refA.refSet(777) self.d("** After barge") sleep(.1) t1wait.set() self.t2counter += 1 self.refA = Ref(999, None) th1 = self.runTransactionInThread(t1, autostart=False) th2 = self.runTransactionInThread(t2, autostart=False) # Start thread 1 first, give the GIL a cycle so it waits for t2wait th2.start() sleep(.1) th1.start() # Wait for the test to finish self.join_all() # T2 should have successfully barged T1, so T1 should have been re-run # The final value of the ref should be 888, as T1 ran last self.assertEqual(self.t1counter, 2) self.assertEqual(self.t2counter, 1) self.assertEqual(self.refA.deref(), 888) self.d("Final value of ref: %s and t1 ran %s times" % (self.refA.deref(), self.t1counter))
def testCommutes(self): # Make sure multiple transactions that occur simultaneously each commute the same ref # Hard to check for this behaving properly---it should have fewer retries than if each # transaction did an alter, but if transactions commit at the same time one might have to retry # anyway. The difference is usually an order of magnitude, so this test is pretty safe self.numruns = AtomicInteger() self.numalterruns = AtomicInteger() numthreads = 20 def incr(curval): return curval + 1 def adder(curval, extraval): return curval + extraval def t1(): self.numruns.getAndIncrement() self.refA.commute(incr, []) def t2(): # self.d("Thread %s (%s): ALTER BEING RUN, total retry num: %s" % (current_thread().ident, id(current_thread()), self.numalterruns.getAndIncrement())) self.numalterruns.getAndIncrement() self.refB.alter(adder, [100]) self.refA = Ref(0, None) self.refB = Ref(0, None) for i in range(numthreads): self.runTransactionInThread(t1) self.join_all() for i in range(numthreads): self.runTransactionInThread(t2) self.join_all() self.d("Commute took %s runs and counter is %s" % (self.numruns.get(), self.refA.deref())) self.d("Alter took %s runs and counter is %s" % (self.numalterruns.get(), self.refB.deref())) self.assertEqual(self.refA.deref(), numthreads) self.assertEqual(self.refB.deref(), 2000) self.assertTrue(self.numalterruns.get() >= self.numruns.get())
def testSimpleConcurrency(self): def t1(): sleep(.1) self.ref0.refSet(1) def t2(): self.ref0.refSet(2) # Delaying t1 means it should commit after t2 self.ref0 = Ref(0, None) self.runTransactionInThread(t1) self.runTransactionInThread(t2) self.join_all() self.assertEqual(self.ref0.deref(), 1)
def testRun_PASS(self): # Now we'll run a transaction ourselves self.refOne = Ref(111, None) self.refTwo = Ref(222, None) # Our transaction body will do a ref-set and an alter (increment a ref by 1) def body(): # Body of the transaction! self.refZero.refSet(999) def incr(val): return val + 1 self.refOne.alter(incr, []) # Test our transaction actually made the changes it should have LockingTransaction.runInTransaction(body) self.assertEqual(self.refZero.deref(), 999) self.assertEqual(self.refOne.deref(), 112) self.assertEqual(self.refTwo.deref(), 222) # Test that the transaction ended properly self.assertRaises(IllegalStateException, self.refZero.refSet, 999)
def setUp(self): self.refZero = Ref(0, None) self.refOne = Ref(pv.vec(range(10)), None)
def setUp(self): self.refZero = Ref(0, None)