/** ****************************************************************************************
         * Invokes grand-parent's method and in addition, de-registers with
         * \ref cs::aworx::lib::ALIB::StdOutputStreamsLock "ALIB.StdOutputStreamsLock"
         * @param acquirer The acquirer to remove.
         * @return The new number of \e acquirers set.
         ******************************************************************************************/
        public override int   RemoveAcquirer( ThreadLock acquirer )
        {
            // d-register with ALIB lockers (if not done yet)
            if ( usesStdStreams )
            {
                ALIB.Lock.Acquire();
                    int  stdStreamLockRegistrationCounter= --this.stdStreamLockRegistrationCounter;
                ALIB.Lock.Release();

                if ( stdStreamLockRegistrationCounter == 0 )
                    ALIB.StdOutputStreamsLock.RemoveAcquirer( this );
            }

            Variable variable= new Variable();

            // export autosizes to configuration
            variable.Define( ALox.AUTO_SIZES, GetName() );
            AutoSizes.Export( variable.AddString() );
            variable.Store();

            // export "max elapsed time" to configuration
            variable.Define( ALox.MAX_ELAPSED_TIME, GetName() );
            AString destVal=  variable.Load() != 0  ?  variable.GetString()
                                                    :  variable.AddString();
            destVal._()._( MetaInfo.MaxElapsedTime.InSeconds() );
            variable.Store();

            // call parents' implementation
            return base.RemoveAcquirer( acquirer );
        }
Esempio n. 2
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);
        }
    // #############################################################################################
    // Reimplementing interface of grand-parent class SmartLock
    // #############################################################################################

        /** ****************************************************************************************
         * Invokes grand-parent's method and in addition, if field #usesStdStreams is set,
         * registers with
         * \ref cs::aworx::lib::ALIB::StdOutputStreamsLock "ALIB.StdOutputStreamsLock", respectively
         *
         * @param newAcquirer The acquirer to add.
         * @return The new number of \e acquirers set.
         ******************************************************************************************/
        public override int   AddAcquirer( ThreadLock newAcquirer )
        {
            // register with ALIB lockers (if not done yet)
            if ( usesStdStreams )
            {
                ALIB.Lock.Acquire();
                    int  stdStreamLockRegistrationCounter= this.stdStreamLockRegistrationCounter++;
                ALIB.Lock.Release();
                if ( stdStreamLockRegistrationCounter == 0 )
                    ALIB.StdOutputStreamsLock.AddAcquirer( this );
            }

            Variable variable= new Variable();

            // import autosizes from configuration (last session)
            if ( variable.Define( ALox.AUTO_SIZES, GetName()).Load() != 0 )
                AutoSizes.Import( variable.GetString() );

            // import "max elapsed time" from configuration (last session)
            if ( variable.Define( ALox.MAX_ELAPSED_TIME, GetName()).Load()  != 0 )
            {
                long maxInSecs= variable.GetInteger();
                Substring attrValue= new Substring();
                if ( variable.GetAttribute( "limit", attrValue ) )
                {
                    long maxMax;
                    attrValue.ConsumeLong( out maxMax );
                    if ( maxInSecs > maxMax )
                        maxInSecs= maxMax;
                }
                MetaInfo.MaxElapsedTime.FromSeconds( maxInSecs );
            }

            // Variable  <name>_FORMAT / <typeName>_FORMAT:
            ALIB.ASSERT_WARNING( ALox.FORMAT.DefaultValue == null,
                                 "Default value of variable FORMAT should be kept null" );
            if(    0 ==  variable.Define( ALox.FORMAT, GetName()     ).Load()
                && 0 ==  variable.Define( ALox.FORMAT, GetTypeName() ).Load() )
            {
                // no variable created, yet. Let's create a 'personal' one on our name
                variable.Define( ALox.FORMAT, GetName() );
                variable.AddString( MetaInfo.Format            );
                variable.AddString( MetaInfo.VerbosityError    );
                variable.AddString( MetaInfo.VerbosityWarning  );
                variable.AddString( MetaInfo.VerbosityInfo     );
                variable.AddString( MetaInfo.VerbosityVerbose  );
                variable.Store();
            }
            else
            {
                                           MetaInfo.Format          ._()._( variable.GetString(0) );
                if( variable.Size() >= 2 ) MetaInfo.VerbosityError  = variable.GetString(1).ToString();
                if( variable.Size() >= 3 ) MetaInfo.VerbosityWarning= variable.GetString(2).ToString();
                if( variable.Size() >= 4 ) MetaInfo.VerbosityInfo   = variable.GetString(3).ToString();
                if( variable.Size() >= 5 ) MetaInfo.VerbosityVerbose= variable.GetString(4).ToString();
            }
        
            // Variable  <name>_FORMAT_DATE_TIME / <typeName>_FORMAT_DATE_TIME:
            ALIB.ASSERT_WARNING( ALox.FORMAT_DATE_TIME.DefaultValue == null,
                                 "Default value of variable FORMAT_DATE_TIME should be kept null" );
            if(    0 ==  variable.Define( ALox.FORMAT_DATE_TIME, GetName()     ).Load()
                && 0 ==  variable.Define( ALox.FORMAT_DATE_TIME, GetTypeName() ).Load() )
            {
                // no variable created, yet. Let's create a 'personal' one on our name
                variable.Define( ALox.FORMAT_DATE_TIME, GetName() );
                variable.AddString( MetaInfo.DateFormat        );
                variable.AddString( MetaInfo.TimeOfDayFormat   );
                variable.AddString( MetaInfo.TimeElapsedDays   );
                variable.Store();
            }
            else
            {
                                           MetaInfo.DateFormat      = variable.GetString(0).ToString();
                if( variable.Size() >= 2 ) MetaInfo.TimeOfDayFormat = variable.GetString(1).ToString();
                if( variable.Size() >= 3 ) MetaInfo.TimeElapsedDays = variable.GetString(2).ToString();
            }
        
            // Variable  <name>FORMAT_TIME_DIFF / <typeName>FORMAT_TIME_DIFF:
            ALIB.ASSERT_WARNING( ALox.FORMAT_TIME_DIFF.DefaultValue == null,
                                 "Default value of variable FORMAT_TIME_DIFF should be kept null" );
            if(    0 ==  variable.Define( ALox.FORMAT_TIME_DIFF, GetName()     ).Load()
                && 0 ==  variable.Define( ALox.FORMAT_TIME_DIFF, GetTypeName() ).Load() )
            {
                // no variable created, yet. Let's create a 'personal' one on our name
                variable.Define( ALox.FORMAT_TIME_DIFF, GetName() );
                variable.AddInteger   ( MetaInfo.TimeDiffMinimum);
                variable.AddString( MetaInfo.TimeDiffNone   );
                variable.AddString( MetaInfo.TimeDiffNanos  );
                variable.AddString( MetaInfo.TimeDiffMicros );
                variable.AddString( MetaInfo.TimeDiffMillis );
                variable.AddString( MetaInfo.TimeDiffSecs   );
                variable.AddString( MetaInfo.TimeDiffMins   );
                variable.AddString( MetaInfo.TimeDiffHours  );
                variable.AddString( MetaInfo.TimeDiffDays   );
                variable.Store();
            }
            else
            {
                                           MetaInfo.TimeDiffMinimum= variable.GetInteger   (0);
                if( variable.Size() >= 2 ) MetaInfo.TimeDiffNone   = variable.GetString(1).ToString();
                if( variable.Size() >= 3 ) MetaInfo.TimeDiffNanos  = variable.GetString(2).ToString();
                if( variable.Size() >= 4 ) MetaInfo.TimeDiffMicros = variable.GetString(3).ToString();
                if( variable.Size() >= 5 ) MetaInfo.TimeDiffMillis = variable.GetString(4).ToString();
                if( variable.Size() >= 6 ) MetaInfo.TimeDiffSecs   = variable.GetString(5).ToString();
                if( variable.Size() >= 7 ) MetaInfo.TimeDiffMins   = variable.GetString(6).ToString();
                if( variable.Size() >= 8 ) MetaInfo.TimeDiffHours  = variable.GetString(7).ToString();
                if( variable.Size() >= 9 ) MetaInfo.TimeDiffDays   = variable.GetString(8).ToString();
            }

            // Variable  <name>FORMAT_MULTILINE / <typeName>FORMAT_MULTILINE:
            ALIB.ASSERT_WARNING( ALox.FORMAT_MULTILINE.DefaultValue == null,
                                 "Default value of variable FORMAT_MULTILINE should be kept null" );
            if(    0 ==  variable.Define( ALox.FORMAT_MULTILINE, GetName()     ).Load()
                && 0 ==  variable.Define( ALox.FORMAT_MULTILINE, GetTypeName() ).Load() )
            {
                // no variable created, yet. Let's create a 'personal' one on our name
                variable.Define( ALox.FORMAT_MULTILINE, GetName() );
                variable.AddInteger( MultiLineMsgMode );
                variable.AddString ( FmtMultiLineMsgHeadline   );
                variable.AddString ( FmtMultiLinePrefix  );
                variable.AddString ( FmtMultiLineSuffix );
                variable.Store();
            }
            else
            {
                                           MultiLineMsgMode=        (int) variable.GetInteger(0)  ;
                if( variable.Size() >= 2 ) FmtMultiLineMsgHeadline= variable.GetString(1).ToString();
                if( variable.Size() >= 3 ) FmtMultiLinePrefix     = variable.GetString(2).ToString();
                if( variable.Size() >= 4 ) FmtMultiLineSuffix     = variable.GetString(3).ToString();
                if( variable.Size() >= 5 ) { if (variable.GetString(4).Equals( "nulled" , Case.Ignore ) )
                                                MultiLineDelimiter= null;
                                             else
                                                MultiLineDelimiter= variable.GetString(4).ToString();
                                           }
                if( variable.Size() >= 6 ) MultiLineDelimiterRepl = variable.GetString(5).ToString();
            }

            // call parents' implementation
            return base.AddAcquirer( newAcquirer );
        }
        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();
        }
Esempio n. 5
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 Test_ThreadLock_TestThreadParams( ThreadLock aLock, int holdTime, int repeats, bool verbose, Test_ThreadLock_SharedInt shared )
 {
     this.aLock=        aLock;
     this.holdTime=  holdTime;
     this.repeats=    repeats;
     this.verbose=    verbose;
     this.shared=    shared;
 }
        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_HeavyLoad()
        {
            UT_INIT();
            Log.SetVerbosity( new ConsoleLogger(), Verbosity.Verbose, "/" );
            Log.MapThreadName( "UnitTest" );
            Log.SetDomain( "TestTLock", Scope.Filename );

            ThreadLock aLock= new ThreadLock();

            // uncomment this for unsafe mode
            // lock.setUnsafe( true );

            Test_ThreadLock_SharedInt    shared=        new Test_ThreadLock_SharedInt();
            int                            holdTime=    0;
            int                            repeats=    5000;
            bool                        verbose=    false;

            Test_ThreadLock_TestThreadParams p1= new Test_ThreadLock_TestThreadParams( aLock, holdTime, repeats, verbose, shared );
            Test_ThreadLock_TestThreadParams p2= new Test_ThreadLock_TestThreadParams( aLock, holdTime, repeats, verbose, shared );
            Test_ThreadLock_TestThreadParams p3= new Test_ThreadLock_TestThreadParams( aLock, holdTime, repeats, verbose, shared );
            Log.Info("starting three threads");

            Thread t1= new Thread( new ParameterizedThreadStart( Test_ThreadLock_Test_run ) );
            Thread t2= new Thread( new ParameterizedThreadStart( Test_ThreadLock_Test_run ) );
            Thread t3= new Thread( new ParameterizedThreadStart( Test_ThreadLock_Test_run ) );
            t1.Start( p1 );
            t2.Start( p2 );
            t3.Start( p3 );

            // wait until all ended
            while ( t1.IsAlive || t2.IsAlive || t3.IsAlive )
                ALIB.SleepMillis( 1 );

            Log.Info("All threads ended. Shared value=" + shared.val );

            UT_TRUE( shared.val == 0 );

        }
        public void SmartLock()
        {
            UT_INIT();

            Report.GetDefault().PushHaltFlags( false, false );
            
                // SmartLock with null-users
                {
                                                                                                                                                  utWriter.lox.CntLogCalls= 0;
                    SmartLock sl= new SmartLock();      UT_TRUE( sl.GetSafeness() == Safeness.Unsafe );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.AddAcquirer   ( null );          UT_TRUE( sl.GetSafeness() == Safeness.Unsafe );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.AddAcquirer   ( null );          UT_TRUE( sl.GetSafeness() == Safeness.Safe   );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.AddAcquirer   ( null );          UT_TRUE( sl.GetSafeness() == Safeness.Safe   );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.RemoveAcquirer( null );          UT_TRUE( sl.GetSafeness() == Safeness.Safe   );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.RemoveAcquirer( null );          UT_TRUE( sl.GetSafeness() == Safeness.Unsafe );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.RemoveAcquirer( null );          UT_TRUE( sl.GetSafeness() == Safeness.Unsafe );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.RemoveAcquirer( null );          UT_TRUE( sl.GetSafeness() == Safeness.Unsafe );  UT_TRUE( utWriter.lox.CntLogCalls== 1 ); utWriter.lox.CntLogCalls= 0;
                }
            
                // SmartLock with threadlocks
                {
                    ThreadLock tl1 = new ThreadLock();
                    ThreadLock tl2 = new ThreadLock();
                    ThreadLock tl3 = new ThreadLock();
                    SmartLock  sl= new SmartLock();    UT_TRUE( sl.GetSafeness() == Safeness.Unsafe );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.AddAcquirer   ( tl1 );          UT_TRUE( sl.GetSafeness() == Safeness.Unsafe );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.AddAcquirer   ( tl2 );          UT_TRUE( sl.GetSafeness() == Safeness.Safe   );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.AddAcquirer   ( tl3 );          UT_TRUE( sl.GetSafeness() == Safeness.Safe   );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.RemoveAcquirer( tl3 );          UT_TRUE( sl.GetSafeness() == Safeness.Safe   );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.RemoveAcquirer( tl3 );          UT_TRUE( sl.GetSafeness() == Safeness.Safe   );  UT_TRUE( utWriter.lox.CntLogCalls== 1 ); utWriter.lox.CntLogCalls= 0;
                    sl.RemoveAcquirer( tl2 );          UT_TRUE( sl.GetSafeness() == Safeness.Unsafe );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.RemoveAcquirer( tl1 );          UT_TRUE( sl.GetSafeness() == Safeness.Unsafe );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.RemoveAcquirer( tl1 );          UT_TRUE( sl.GetSafeness() == Safeness.Unsafe );  UT_TRUE( utWriter.lox.CntLogCalls== 1 ); utWriter.lox.CntLogCalls= 0;
                }
            
                // mixed
                {
                    ThreadLock tl1 = new ThreadLock();
                    ThreadLock tl2 = new ThreadLock();
                    ThreadLock tl3 = new ThreadLock();
                    SmartLock  sl= new SmartLock();     UT_TRUE( sl.GetSafeness() == Safeness.Unsafe );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.AddAcquirer   ( tl1  );          UT_TRUE( sl.GetSafeness() == Safeness.Unsafe );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.AddAcquirer   ( null );          UT_TRUE( sl.GetSafeness() == Safeness.Safe   );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.AddAcquirer   ( null );          UT_TRUE( sl.GetSafeness() == Safeness.Safe   );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.AddAcquirer   ( tl2  );          UT_TRUE( sl.GetSafeness() == Safeness.Safe   );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.AddAcquirer   ( null );          UT_TRUE( sl.GetSafeness() == Safeness.Safe   );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.AddAcquirer   ( tl2  );          UT_TRUE( sl.GetSafeness() == Safeness.Safe   );  UT_TRUE( utWriter.lox.CntLogCalls== 1 ); utWriter.lox.CntLogCalls= 0;
                    sl.AddAcquirer   ( null );          UT_TRUE( sl.GetSafeness() == Safeness.Safe   );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.AddAcquirer   ( tl3  );          UT_TRUE( sl.GetSafeness() == Safeness.Safe   );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.RemoveAcquirer( null );          UT_TRUE( sl.GetSafeness() == Safeness.Safe   );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.RemoveAcquirer( tl1  );          UT_TRUE( sl.GetSafeness() == Safeness.Safe   );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.RemoveAcquirer( tl1  );          UT_TRUE( sl.GetSafeness() == Safeness.Safe   );  UT_TRUE( utWriter.lox.CntLogCalls== 1 ); utWriter.lox.CntLogCalls= 0;
                    sl.RemoveAcquirer( null );          UT_TRUE( sl.GetSafeness() == Safeness.Safe   );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.RemoveAcquirer( tl3  );          UT_TRUE( sl.GetSafeness() == Safeness.Safe   );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.RemoveAcquirer( null );          UT_TRUE( sl.GetSafeness() == Safeness.Safe   );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.RemoveAcquirer( null );          UT_TRUE( sl.GetSafeness() == Safeness.Unsafe );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.RemoveAcquirer( null );          UT_TRUE( sl.GetSafeness() == Safeness.Unsafe );  UT_TRUE( utWriter.lox.CntLogCalls== 1 ); utWriter.lox.CntLogCalls= 0;
                    sl.RemoveAcquirer( null );          UT_TRUE( sl.GetSafeness() == Safeness.Unsafe );  UT_TRUE( utWriter.lox.CntLogCalls== 1 ); utWriter.lox.CntLogCalls= 0;
                    sl.RemoveAcquirer( tl3  );          UT_TRUE( sl.GetSafeness() == Safeness.Unsafe );  UT_TRUE( utWriter.lox.CntLogCalls== 1 ); utWriter.lox.CntLogCalls= 0;
                    sl.RemoveAcquirer( tl2  );          UT_TRUE( sl.GetSafeness() == Safeness.Unsafe );  UT_TRUE( utWriter.lox.CntLogCalls== 0 ); utWriter.lox.CntLogCalls= 0;
                    sl.RemoveAcquirer( null );          UT_TRUE( sl.GetSafeness() == Safeness.Unsafe );  UT_TRUE( utWriter.lox.CntLogCalls== 1 ); utWriter.lox.CntLogCalls= 0;
                }
                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 );

        }