예제 #1
0
        // #############################################################################################
        // Interface
        // #############################################################################################

        /** ****************************************************************************************
         * Adds an acquirer.
         * @param newAcquirer The acquirer to add.
         * @return The new number of \e acquirers set.
         ******************************************************************************************/
        public virtual int AddAcquirer(ThreadLock newAcquirer)
        {
            int count = -1;

            #if DEBUG
            bool errAllreadyAdded    = true;
            bool errHasToBeRecursive = false;
            int  errWasAcquired      = 0;
            #endif

            try { ALIB.Lock.Acquire();

                  count = acquirers.Count;

                  // check doubly added
                  if (newAcquirer == null ||
                      acquirers.IndexOf(newAcquirer) < 0)
                  {
                    #if DEBUG
                      errAllreadyAdded = false;
                      errWasAcquired   = DbgCountAcquirements() == 0 ? 0 : 1;
                    #endif

                      // switch on?
                      if (acquirers.Count == 1)
                      {
                        #if DEBUG
                          errAllreadyAdded = false;
                        #endif
                          ThreadLock firstAcquirer = acquirers[0];

                          // non-anonymous acquirer?
                          if (firstAcquirer != null)
                          {
                              if (firstAcquirer.GetMode() == LockMode.Recursive)
                              {
                                  firstAcquirer.Acquire();
                                  SetSafeness(Safeness.Safe);
                                  acquirers.Add(newAcquirer);
                                  count++;
                                  firstAcquirer.Release();
                              }
                            #if DEBUG
                              else
                              {
                                  errHasToBeRecursive = false;
                              }
                            #endif
                          }
                          // critical section: our first acquirer is anonymous. As documented in class,
                          // this must happen only in situations, when we are sure, that we are safe, e.g. still
                          // single threaded execution of process bootstrap.
                          else
                          {
                              // If this assert happens, its only good luck: we detected a misuse. But it should
                              // be very seldom to be detected this way :-/
                            #if DEBUG
                              if (errWasAcquired == 1)
                              {
                                  errWasAcquired = 2;
                              }
                            #endif

                              SetSafeness(Safeness.Safe);
                              acquirers.Add(newAcquirer);
                              count++;
                          }
                      }
                      else
                      {
                          acquirers.Add(newAcquirer);
                      }
                  }
            } finally { ALIB.Lock.Release(); }

            #if DEBUG
            ALIB.ASSERT_ERROR(!errAllreadyAdded, "Acquirer already registered.");
            ALIB.ASSERT_ERROR(!errHasToBeRecursive, "Acquireres need to be in recursive mode ");
            ALIB.ASSERT_ERROR(errWasAcquired != 1, "Already aquired. Hint: Acquirer[0] must not acquire this before adding itself!");
            ALIB.ASSERT_ERROR(errWasAcquired != 2, "Aquired and acquirer[0] anonymous. Misuse of SmartLock!");
            #endif

            return(count);
        }
예제 #2
0
        /** ****************************************************************************************
         * Removes an acquirer.
         * @param acquirerToRemove The acquirer to remove.
         * @return The new number of \e acquirers set.
         ******************************************************************************************/
        public virtual int RemoveAcquirer(ThreadLock acquirerToRemove)
        {
            int  count          = 0;
            bool errNotFound    = true;
            bool errWasAcquired = false;

            try { ALIB.Lock.Acquire();

                #if DEBUG
                  errWasAcquired = DbgCountAcquirements() != 0;
                #endif

                  // search acquirer
                  if (acquirers.IndexOf(acquirerToRemove) >= 0)
                  {
                      errNotFound = false;

                      // switch off?
                      if (acquirers.Count == 2)
                      {
                          ThreadLock acquirer1 = acquirers[0];
                          ThreadLock acquirer2 = acquirers[1];
                          if (acquirer1 == acquirerToRemove)
                          {
                              acquirer1 = null;
                          }
                          if (acquirer2 == acquirerToRemove)
                          {
                              acquirer2 = null;
                          }

                          // Aquire acquirers in their order of appearance
                          if (acquirer1 != null)
                          {
                              acquirer1.Acquire();
                          }
                          if (acquirer2 != null)
                          {
                              acquirer2.Acquire();
                          }
                          SetSafeness(Safeness.Unsafe);
                          acquirers.Remove(acquirerToRemove);
                          if (acquirer2 != null)
                          {
                              acquirer2.Release();
                          }
                          if (acquirer1 != null)
                          {
                              acquirer1.Release();
                          }
                      }

                      // just remove acquirer, keep mode
                      else
                      {
                          acquirers.Remove(acquirerToRemove);
                      }
                  }

                  count = acquirers.Count; } finally { ALIB.Lock.Release(); }

            ALIB.ASSERT_ERROR(!errNotFound, "Acquirer not found.");
            ALIB.ASSERT_ERROR(!errWasAcquired, "Aquired on release. Hint: Acquirers must acquire only when acquired themselves!");
            return(count);
        }
        public void ThreadLock_SpeedTest()
        {
            UT_INIT();

            Log.SetVerbosity( new ConsoleLogger(), Verbosity.Verbose, "/" );
            Log.MapThreadName( "UnitTest" );
            Log.SetDomain( "TestTLock", Scope.Method );

            ThreadLock aLock= new ThreadLock();

            int        repeats=    100000;
            int        rrepeats=    5;

            Ticks stopwatch= new Ticks();
            for ( int r= 0; r < rrepeats; r ++)
            {
                Log.Info("Run " + rrepeats );

                aLock.SetSafeness( Safeness.Unsafe );
                stopwatch.Set();
                for ( int i= 0; i < repeats; i++ )
                {
                    aLock.Acquire();
                    aLock.Release();
                }
                long time= stopwatch.Age().InMillis();
                Log.Info("Safe mode, " + repeats + " lock/unlock ops: " + time + " ms" );

                aLock.SetSafeness( Safeness.Safe );
                stopwatch.Set();
                for ( int i= 0; i < repeats; i++ )
                {
                    //aLock.acquire();
                    //aLock.release();

                    // in java, adding the following two loops, results in similar execution speed
                    for ( int tt= 0; tt < 70; tt++ )
                        i+= tt;
                    for ( int tt= 0; tt < 70; tt++ )
                        i-= tt;
                }
                time= stopwatch.Age().InMillis();
                Log.Info("Unsafe mode, " + repeats + " lock/unlock ops: " + time + " ms" );
            }
        }
        public void ThreadLock_Simple()
        {
            UT_INIT();
            Report.GetDefault().PushHaltFlags( false, false );

            Log.AddDebugLogger();
            Log.MapThreadName( "UnitTest" );
            Log.SetDomain( "TestTLock", Scope.Method );
            Log.SetVerbosity( Log.DebugLogger, Verbosity.Verbose, "ALIB" );

            // lock a recursive lock
            ThreadLock aLock= new ThreadLock();

            aLock.Acquire();
            aLock.Release();

            aLock.Acquire();                                UT_TRUE (  aLock.ToString().StartsWith("Locked")   );
            aLock.Acquire();                                UT_TRUE (  aLock.ToString().StartsWith("Locked")   );
            aLock.Release();                                UT_TRUE (  aLock.ToString().StartsWith("Locked")   );
                                                                                                    
            aLock.Acquire();                                UT_TRUE (  aLock.ToString().StartsWith("Locked")   );
            aLock.Release();                                UT_TRUE (  aLock.ToString().StartsWith("Locked")   );
            aLock.Release();                                UT_TRUE (  aLock.ToString().StartsWith("Unlocked") );

            // set unsafe
            aLock.SetSafeness( Safeness.Unsafe );           UT_TRUE (  aLock.ToString().StartsWith("Unlocked") );
                                                            UT_TRUE (  aLock.ToString().Contains  ("Unsafe")   );
            aLock.SetSafeness( Safeness.Safe );             UT_TRUE ( !aLock.ToString().Contains  ("Unsafe")   );

            aLock.SetSafeness( Safeness.Unsafe );           UT_TRUE (  aLock.ToString().StartsWith("Unlocked") );
                                                            UT_TRUE (  aLock.ToString().Contains  ("Unsafe")   );
            aLock.Acquire();                                UT_TRUE (  aLock.ToString().StartsWith("Locked")   );
            aLock.Release();                                UT_TRUE (  aLock.ToString().StartsWith("Unlocked") );
                                                            UT_TRUE (  aLock.ToString().Contains  ("Unsafe")   );

            // unsafe
            aLock.Acquire();                                UT_TRUE (  aLock.ToString().StartsWith("Locked")   );
            Log.Info("One warning should come now: ");
            aLock.SetSafeness( Safeness.Safe );             UT_TRUE (  aLock.ToString().StartsWith("Locked")   );
                                                            UT_TRUE (  aLock.ToString().Contains  ("Unsafe")   );

            // safe (new lock)
            aLock= new ThreadLock();
            aLock.Acquire();                                UT_TRUE (  aLock.ToString().StartsWith("Locked")   );
                                                            UT_TRUE ( !aLock.ToString().Contains  ("Unsafe")   );
            Log.Info("One warning should come now: ");
            aLock.SetSafeness( Safeness.Unsafe );           UT_TRUE ( !aLock.ToString().StartsWith("null")     );
                                                            UT_TRUE ( !aLock.ToString().Contains  ("Unsafe")   );


            // test warnings (10) locks:
            aLock= new ThreadLock();
            Log.Info("Two warnings should come now: ");
            for (int i= 0; i<20; i++)
                aLock.Acquire();
            UT_TRUE (  aLock.ToString().StartsWith("Locked") );
            for (int i= 0; i<20; i++)
                aLock.Release();
            UT_TRUE (  aLock.ToString().StartsWith("Unlocked") );

            // test a non-recursive lock
            aLock= new ThreadLock( LockMode.SingleLocks );
            aLock.Acquire();                UT_TRUE (  aLock.ToString().StartsWith("Locked")   );
            aLock.Acquire();                UT_TRUE (  aLock.ToString().StartsWith("Locked")   );
            aLock.Release();                UT_TRUE (  aLock.ToString().StartsWith("Unlocked") );

            Log.Info("One warning should come now: ");
            aLock.Release();                UT_TRUE (  aLock.ToString().StartsWith("Unlocked") );

            Report.GetDefault().PopHaltFlags();
        }
        public void ThreadLock_Threaded()
        {
            UT_INIT();

            Log.SetVerbosity( new ConsoleLogger(),Verbosity.Verbose, "/" );
            Log.MapThreadName( "UnitTest" );
            Log.SetDomain( "TestTLock", Scope.Filename );
            Log.SetVerbosity( "CONSOLE", Verbosity.Verbose, "ALIB" );

            ThreadLock aLock= new ThreadLock();

            Test_ThreadLock_SharedInt shared= new Test_ThreadLock_SharedInt();

            Log.Info("starting thread locked");
            aLock.Acquire();
            Test_ThreadLock_TestThreadParams tParam= new Test_ThreadLock_TestThreadParams( aLock, 10, 1, true, shared );

            Thread thread = new Thread( new ParameterizedThreadStart( Test_ThreadLock_Test_run ) );
            thread.Name= "A Thread";
            thread.Start( tParam );

            Log.Info("We wait 1100 ms. This should give a warning! ");
            ALIB.SleepMillis( 1100 );
            aLock.Release();

            // wait until t ended
            while (thread.IsAlive)
                ALIB.SleepMillis( 1 );

            // now we do the same with a higher wait limit, no erro should come
            aLock.waitWarningTimeLimitInMillis= 5;
            aLock.Acquire();
            tParam= new Test_ThreadLock_TestThreadParams( aLock, 10, 1, true, shared );
            thread = new Thread( new ParameterizedThreadStart( Test_ThreadLock_Test_run ) );
            thread.Start( tParam );
            Log.Info("We wait 1 ms. This should NOT give a warning! ");
            ALIB.SleepMillis( 1 );
            aLock.Release();

            // wait until t ended
            while (thread.IsAlive)
                ALIB.SleepMillis( 1 );

        }