Exemplo n.º 1
0
int Thread::_threadLoop(void* user)
{
    Thread* const self = static_cast<Thread*>(user);

    sp<Thread> strong(self->mHoldSelf);
    wp<Thread> weak(strong);
    self->mHoldSelf.clear();

#ifdef HAVE_ANDROID_OS
    // this is very useful for debugging with gdb
    self->mTid = gettid();
#endif

    bool first = true;

    do {
        bool result;
        if (first) {
            first = false;
            self->mStatus = self->readyToRun();
            result = (self->mStatus == NO_ERROR);

            if (result && !self->exitPending()) {
                // Binder threads (and maybe others) rely on threadLoop
                // running at least once after a successful ::readyToRun()
                // (unless, of course, the thread has already been asked to exit
                // at that point).
                // This is because threads are essentially used like this:
                //   (new ThreadSubclass())->run();
                // The caller therefore does not retain a strong reference to
                // the thread and the thread would simply disappear after the
                // successful ::readyToRun() call instead of entering the
                // threadLoop at least once.
                result = self->threadLoop();
            }
        } else {
            result = self->threadLoop();
        }

        // establish a scope for mLock
        {
        Mutex::Autolock _l(self->mLock);
        if (result == false || self->mExitPending) {
            self->mExitPending = true;
            self->mRunning = false;
            // clear thread ID so that requestExitAndWait() does not exit if
            // called by a new thread using the same thread ID as this one.
            self->mThread = thread_id_t(-1);
            // note that interested observers blocked in requestExitAndWait are
            // awoken by broadcast, but blocked on mLock until break exits scope
            self->mThreadExitedCondition.broadcast();
            break;
        }
        }
        
        // Release our strong reference, to let a chance to the thread
        // to die a peaceful death.
        strong.clear();
        // And immediately, re-acquire a strong reference for the next loop
        strong = weak.promote();
    } while(strong != 0);
    
    return 0;
}
Exemplo n.º 2
0
void tst_QSharedPointer::basics()
{
    {
        QSharedPointer<Data> ptr;
        QWeakPointer<Data> weakref;

        QCOMPARE(sizeof(ptr), 2*sizeof(void*));
        QCOMPARE(sizeof(weakref), 2*sizeof(void*));
    }

    QFETCH(bool, isNull);
    Data *aData = 0;
    if (!isNull)
        aData = new Data;
    Data *otherData = new Data;
    QSharedPointer<Data> ptr(aData);

    {
        // basic self tests
        QCOMPARE(ptr.isNull(), isNull);
        QCOMPARE(bool(ptr), !isNull);
        QCOMPARE(!ptr, isNull);

        QCOMPARE(ptr.data(), aData);
        QCOMPARE(ptr.operator->(), aData);
        Data &dataReference = *ptr;
        QCOMPARE(&dataReference, aData);

        QVERIFY(ptr == aData);
        QVERIFY(!(ptr != aData));
        QVERIFY(aData == ptr);
        QVERIFY(!(aData != ptr));

        QVERIFY(ptr != otherData);
        QVERIFY(otherData != ptr);
        QVERIFY(! (ptr == otherData));
        QVERIFY(! (otherData == ptr));
    }
    QVERIFY(!ptr.d || ptr.d->weakref == 1);
    QVERIFY(!ptr.d || ptr.d->strongref == 1);

    {
        // create another object:
        QSharedPointer<Data> otherCopy(otherData);
        QVERIFY(ptr != otherCopy);
        QVERIFY(otherCopy != ptr);
        QVERIFY(! (ptr == otherCopy));
        QVERIFY(! (otherCopy == ptr));

        // otherData is deleted here
    }
    QVERIFY(!ptr.d || ptr.d->weakref == 1);
    QVERIFY(!ptr.d || ptr.d->strongref == 1);

    {
        // create a copy:
        QSharedPointer<Data> copy(ptr);
        QVERIFY(copy == ptr);
        QVERIFY(ptr == copy);
        QVERIFY(! (copy != ptr));
        QVERIFY(! (ptr != copy));
        QCOMPARE(copy, ptr);
        QCOMPARE(ptr, copy);

        QCOMPARE(copy.isNull(), isNull);
        QCOMPARE(copy.data(), aData);
        QVERIFY(copy == aData);
    }
    QVERIFY(!ptr.d || ptr.d->weakref == 1);
    QVERIFY(!ptr.d || ptr.d->strongref == 1);

    {
        // create a weak reference:
        QWeakPointer<Data> weak(ptr);
        QCOMPARE(weak.isNull(), isNull);
        QCOMPARE(!weak, isNull);
        QCOMPARE(bool(weak), !isNull);

        QVERIFY(ptr == weak);
        QVERIFY(weak == ptr);
        QVERIFY(! (ptr != weak));
        QVERIFY(! (weak != ptr));

        // create another reference:
        QWeakPointer<Data> weak2(weak);
        QCOMPARE(weak2.isNull(), isNull);
        QCOMPARE(!weak2, isNull);
        QCOMPARE(bool(weak2), !isNull);

        QVERIFY(weak2 == weak);
        QVERIFY(weak == weak2);
        QVERIFY(! (weak2 != weak));
        QVERIFY(! (weak != weak2));

        // create a strong reference back:
        QSharedPointer<Data> strong(weak);
        QVERIFY(strong == weak);
        QVERIFY(strong == ptr);
        QCOMPARE(strong.data(), aData);
    }
    QVERIFY(!ptr.d || ptr.d->weakref == 1);
    QVERIFY(!ptr.d || ptr.d->strongref == 1);

    // aData is deleted here
}
Exemplo n.º 3
0
	int Thread::_threadLoop(void* user)
	{
		Thread* const self = static_cast<Thread*>(user);

		sp<Thread> strong(self->mThreadData->mHoldSelf);
		wp<Thread> weak(strong);
		self->mThreadData->mHoldSelf.clear();
		bool first = true;
		bool exec_thread_exit = false;

		{//
		 //  等待run函数返回成功
		//
			CMutex::Autolock _l(self->mThreadData->mLock);
			if (self->mThreadData->mThread == NULL) {
				self->mThreadData->mThreadReadyCondition.wait(self->mThreadData->mLock);
			}
		}

		//
		//  保存一下线程名称
		//	
        unsigned long tid=self->mThreadData->mTid = FFL_CurrentThreadID();
		char threadName[256] = { 0 };
		const  char* tmpName = FFL_GetThreadName(self->mThreadData->mThread);
		if (tmpName != NULL && tmpName[0] != 0) {
			memcpy(threadName, tmpName, FFL_MIN(strlen(tmpName), 255));
		}
		INTERNAL_FFL_LOG_DEBUG("Thread(%d)(%s) run", tid, threadName);

		if (self->mThreadData->mPriority != FFL_THREAD_PRIORITY_NORMAL) {
			FFL_SetThreadPriority(self->mThreadData->mPriority);
		}


		self->threadLoopStart();		
		do {
			bool result;
			if (first) {
				first = false;
				self->mThreadData->mStatus = self->readyToRun();
				result = (self->mThreadData->mStatus == FFL_NO_ERROR);

				if (result && !self->exitPending()) {
					// Binder threads (and maybe others) rely on threadLoop
					// running at least once after a successful ::readyToRun()
					// (unless, of course, the thread has already been asked to exit
					// at that point).
					// This is because threads are essentially used like this:
					//   (new ThreadSubclass())->run();
					// The caller therefore does not retain a strong reference to
					// the thread and the thread would simply disappear after the
					// successful ::readyToRun() call instead of entering the
					// threadLoop at least once.
					result = self->threadLoop();
				}
			}
			else {
				result = self->threadLoop();
			}

			// establish a scope for mLock
			{
				CMutex::Autolock _l(self->mThreadData->mLock);
				if (result == false || self->mThreadData->mExitPending) {
					self->mThreadData->mExitPending = true;
					self->mThreadData->mRunning = false;
					
					// clear thread ID so that requestExitAndWait() does not exit if
					// called by a new thread using the same thread ID as this one.
					self->mThreadData->mThread = 0;
					
					self->threadLoopExit(self);
					exec_thread_exit = true;

					// note that interested observers blocked in requestExitAndWait are
					// awoken by broadcast, but blocked on mLock until break exits scope
					self->mThreadData->mThreadExitedCondition.broadcast();
					break;
				}
			}

			// Release our strong reference, to let a chance to the thread
			// to die a peaceful death.
			strong.clear();
			// And immediately, re-acquire a strong reference for the next loop
			strong = weak.promote();
		} while (!strong.is_empty());

		if(!exec_thread_exit)
		   self->threadLoopExit(0);

		INTERNAL_FFL_LOG_DEBUG("Thread(%d)(%s) exit", tid, threadName);
		return 0;
	}
Exemplo n.º 4
0
int doBaCParam (CoinParam *param)

{
    assert (param != 0) ;
    CbcGenParam *genParam = dynamic_cast<CbcGenParam *>(param) ;
    assert (genParam != 0) ;
    CbcGenCtlBlk *ctlBlk = genParam->obj() ;
    assert (ctlBlk != 0) ;
    CbcModel *model = ctlBlk->model_ ;
    assert (model != 0) ;
    /*
      Setup to return nonfatal/fatal error (1/-1) by default.
    */
    int retval ;
    if (CoinParamUtils::isInteractive()) {
        retval = 1 ;
    } else {
        retval = -1 ;
    }
    ctlBlk->setBaBStatus(CbcGenCtlBlk::BACAbandon, CbcGenCtlBlk::BACmInvalid,
                         CbcGenCtlBlk::BACwNotStarted, false, 0) ;
    /*
      We ain't gonna do squat without a good model.
    */
    if (!ctlBlk->goodModel_) {
        std::cout << "** Current model not valid!" << std::endl ;
        return (retval) ;
    }
    /*
      Start the clock ticking.
    */
    double time1 = CoinCpuTime() ;
    double time2 ;
    /*
      Create a clone of the model which we can modify with impunity. Extract
      the underlying solver for convenient access.
    */
    CbcModel babModel(*model) ;
    OsiSolverInterface *babSolver = babModel.solver() ;
    assert (babSolver != 0) ;
# if CBC_TRACK_SOLVERS > 0
    std::cout
        << "doBaCParam: initial babSolver is "
        << std::hex << babSolver << std::dec
        << ", log level " << babSolver->messageHandler()->logLevel()
        << "." << std::endl ;
# endif
    /*
      Solve the root relaxation. Bail unless it solves to optimality.
    */
    if (!solveRelaxation(&babModel)) {
        ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwBareRoot) ;
        return (0) ;
    }
# if COIN_CBC_VERBOSITY > 0
    std::cout
        << "doBaCParam: initial relaxation z = "
        << babSolver->getObjValue() << "." << std::endl ;
# endif
    /*
      Are we up for fixing variables based on reduced cost alone?
    */
    if (ctlBlk->djFix_.action_ == true) {
        reducedCostHack(babSolver, ctlBlk->djFix_.threshold_) ;
    }
    /*
      Time to consider preprocessing. We'll do a bit of setup before getting to
      the meat of the issue.

      preIppSolver will hold a clone of the unpreprocessed constraint system.
      We'll need it when we postprocess. ippSolver holds the preprocessed
      constraint system.  Again, we clone it and give the clone to babModel for
      B&C. Presumably we need an unmodified copy of the preprocessed system to
      do postprocessing, but the copy itself is hidden inside the preprocess
      object.
    */
    OsiSolverInterface *preIppSolver = 0 ;
    CglPreProcess ippObj ;
    bool didIPP = false ;

    int numberChanged = 0 ;
    int numberOriginalColumns = babSolver->getNumCols() ;
    CbcGenCtlBlk::IPPControl ippAction = ctlBlk->getIPPAction() ;

    if (!(ippAction == CbcGenCtlBlk::IPPOff ||
            ippAction == CbcGenCtlBlk::IPPStrategy)) {
        double timeLeft = babModel.getMaximumSeconds() ;
        preIppSolver = babSolver->clone() ;
        OsiSolverInterface *ippSolver ;
#   if CBC_TRACK_SOLVERS > 0
        std::cout
            << "doBaCParam: clone made prior to IPP is "
            << std::hex << preIppSolver << std::dec
            << ", log level " << preIppSolver->messageHandler()->logLevel()
            << "." << std::endl ;
#   endif

        preIppSolver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo) ;
        ippObj.messageHandler()->setLogLevel(babModel.logLevel()) ;

        CglProbing probingGen ;
        probingGen.setUsingObjective(true) ;
        probingGen.setMaxPass(3) ;
        probingGen.setMaxProbeRoot(preIppSolver->getNumCols()) ;
        probingGen.setMaxElements(100) ;
        probingGen.setMaxLookRoot(50) ;
        probingGen.setRowCuts(3) ;
        ippObj.addCutGenerator(&probingGen) ;
        /*
          For preProcessNonDefault, the 2nd parameter controls the conversion of
          clique and SOS constraints. 0 does nothing, -1 converts <= to ==, and
          2 and 3 form SOS sets under strict and not-so-strict conditions,
          respectively.
        */
        int convert = 0 ;
        if (ippAction == CbcGenCtlBlk::IPPEqual) {
            convert = -1 ;
        } else if (ippAction == CbcGenCtlBlk::IPPEqualAll) {
            convert = -2 ;
        } else if (ippAction == CbcGenCtlBlk::IPPSOS) {
            convert = 2 ;
        } else if (ippAction == CbcGenCtlBlk::IPPTrySOS) {
            convert = 3 ;
        }

        ippSolver = ippObj.preProcessNonDefault(*preIppSolver, convert, 10) ;
#   if CBC_TRACK_SOLVERS > 0
        std::cout
            << "doBaCParam: solver returned from IPP is "
            << std::hex << ippSolver << std::dec ;
        if (ippSolver) {
            std::cout
                << ", log level " << ippSolver->messageHandler()->logLevel() ;
        }
        std::cout << "." << std::endl ;
#   endif
        /*
          ippSolver == 0 is success of a sort --- integer preprocess has found the
          problem to be infeasible or unbounded. Need to think about how to indicate
          status.
        */
        if (!ippSolver) {
            std::cout
                << "Integer preprocess says infeasible or unbounded" << std::endl ;
            delete preIppSolver ;
            ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwIPP) ;
            return (0) ;
        }
#   if COIN_CBC_VERBOSITY > 0
        else {
            std::cout
                << "After integer preprocessing, model has "
                << ippSolver->getNumRows()
                << " rows, " << ippSolver->getNumCols() << " columns, and "
                << ippSolver->getNumElements() << " elements." << std::endl ;
        }
#   endif

        preIppSolver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ;
        ippSolver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ;

        if (ippAction == CbcGenCtlBlk::IPPSave) {
            ippSolver->writeMps("presolved", "mps", 1.0) ;
            std::cout
                << "Integer preprocessed model written to `presolved.mps' "
                << "as minimisation problem." << std::endl ;
        }

        OsiSolverInterface *osiTmp = ippSolver->clone() ;
        babModel.assignSolver(osiTmp) ;
        babSolver = babModel.solver() ;
#   if CBC_TRACK_SOLVERS > 0
        std::cout
            << "doBaCParam: clone of IPP solver passed to babModel is "
            << std::hex << babSolver << std::dec
            << ", log level " << babSolver->messageHandler()->logLevel()
            << "." << std::endl ;
#   endif
        if (!solveRelaxation(&babModel)) {
            delete preIppSolver ;
            ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwIPPRelax) ;
            return (0) ;
        }
#   if COIN_CBC_VERBOSITY > 0
        std::cout
            << "doBaCParam: presolved relaxation z = "
            << babSolver->getObjValue() << "." << std::endl ;
#   endif
        babModel.setMaximumSeconds(timeLeft - (CoinCpuTime() - time1)) ;
        didIPP = true ;
    }
    /*
      At this point, babModel and babSolver hold the constraint system we'll use
      for B&C (either the original system or the preprocessed system) and we have
      a solution to the lp relaxation.

      If we're using the COSTSTRATEGY option, set up priorities here and pass
      them to the babModel.
    */
    if (ctlBlk->priorityAction_ != CbcGenCtlBlk::BPOff) {
        setupPriorities(&babModel, ctlBlk->priorityAction_) ;
    }
    /*
      Install heuristics and cutting planes.
    */
    installHeuristics(ctlBlk, &babModel) ;
    installCutGenerators(ctlBlk, &babModel) ;
    /*
      Set up status print frequency for babModel.
    */
    if (babModel.getNumCols() > 2000 || babModel.getNumRows() > 1500 ||
            babModel.messageHandler()->logLevel() > 1)
        babModel.setPrintFrequency(100) ;
    /*
      If we've read in a known good solution for debugging, activate the row cut
      debugger.
    */
    if (ctlBlk->debugSol_.values_) {
        if (ctlBlk->debugSol_.numCols_ == babModel.getNumCols()) {
            babSolver->activateRowCutDebugger(ctlBlk->debugSol_.values_) ;
        } else {
            std::cout
                << "doBaCParam: debug file has incorrect number of columns."
                << std::endl ;
        }
    }
    /*
      Set ratio-based integrality gap, if specified by user.
    */
    if (ctlBlk->setByUser_[CbcCbcParam::GAPRATIO] == true) {
        double obj = babSolver->getObjValue() ;
        double gapRatio = babModel.getDblParam(CbcModel::CbcAllowableFractionGap) ;
        double gap = gapRatio * (1.0e-5 + fabs(obj)) ;
        babModel.setAllowableGap(gap) ;
        std::cout
            << "doBaCParam: Continuous objective = " << obj
            << ", so allowable gap set to " << gap << std::endl ;
    }
    /*
      A bit of mystery code. As best I can figure, setSpecialOptions(2) suppresses
      the removal of warm start information when checkSolution runs an lp to check
      a solution. John's comment, ``probably faster to use a basis to get integer
      solutions'' makes some sense in this context. Didn't try to track down
      moreMipOptions just yet.
    */
    babModel.setSpecialOptions(babModel.specialOptions() | 2) ;
    /*
      { int ndx = whichParam(MOREMIPOPTIONS,numberParameters,parameters) ;
        int moreMipOptions = parameters[ndx].intValue() ;
        if (moreMipOptions >= 0)
        { printf("more mip options %d\n",moreMipOptions);
          babModel.setSearchStrategy(moreMipOptions); } }
    */
    /*
      Begin the final run-up to branch-and-cut.

      Make sure that objects are set up in the solver. It's possible that whoever
      loaded the model into the solver also set up objects. But it's also
      entirely likely that none exist to this point (and interesting to note that
      IPP doesn't need to know anything about objects).
    */
    setupObjects(babSolver, didIPP, &ippObj) ;
    /*
      Set the branching method. We can't do this until we establish objects,
      because the constructor will set up arrays based on the number of objects,
      and there's no provision to set this information after creation. Arguably not
      good --- it'd be nice to set this in the prototype model that's cloned for
      this routine. In CoinSolve, shadowPriceMode is handled with the TESTOSI
      option.
    */
    OsiChooseStrong strong(babSolver) ;
    strong.setNumberBeforeTrusted(babModel.numberBeforeTrust()) ;
    strong.setNumberStrong(babModel.numberStrong()) ;
    strong.setShadowPriceMode(ctlBlk->chooseStrong_.shadowPriceMode_) ;
    CbcBranchDefaultDecision decision ;
    decision.setChooseMethod(strong) ;
    babModel.setBranchingMethod(decision) ;
    /*
      Here I've deleted a huge block of code that deals with external priorities,
      branch direction, pseudocosts, and solution. (PRIORITYIN) Also a block of
      code that generates C++ code.
    */
    /*
      Set up strategy for branch-and-cut. Note that the integer code supplied to
      setupPreProcessing is *not* compatible with the IPPAction enum. But at least
      it's documented. See desiredPreProcess_ in CbcStrategyDefault. `1' is
      accidentally equivalent to IPPOn.
    */

    if (ippAction == CbcGenCtlBlk::IPPStrategy) {
        CbcStrategyDefault strategy(true, 5, 5) ;
        strategy.setupPreProcessing(1) ;
        babModel.setStrategy(strategy) ;
    }
    /*
      Yes! At long last, we're ready for the big call. Do branch and cut. In
      general, the solver used to return the solution will not be the solver we
      passed in, so reset babSolver here.
    */
    int statistics = (ctlBlk->printOpt_ > 0) ? ctlBlk->printOpt_ : 0 ;
# if CBC_TRACK_SOLVERS > 0
    std::cout
        << "doBaCParam: solver at call to branchAndBound is "
        << std::hex << babModel.solver() << std::dec
        << ", log level " << babModel.solver()->messageHandler()->logLevel()
        << "." << std::endl ;
# endif
    babModel.branchAndBound(statistics) ;
    babSolver = babModel.solver() ;
# if CBC_TRACK_SOLVERS > 0
    std::cout
        << "doBaCParam: solver at return from branchAndBound is "
        << std::hex << babModel.solver() << std::dec
        << ", log level " << babModel.solver()->messageHandler()->logLevel()
        << "." << std::endl ;
# endif
    /*
      Write out solution to preprocessed model.
    */
    if (ctlBlk->debugCreate_ == "createAfterPre" &&
            babModel.bestSolution()) {
        CbcGenParamUtils::saveSolution(babSolver, "debug.file") ;
    }
    /*
      Print some information about branch-and-cut.
    */
# if COIN_CBC_VERBOSITY > 0
    std::cout
        << "Cuts at root node changed objective from "
        << babModel.getContinuousObjective()
        << " to " << babModel.rootObjectiveAfterCuts() << std::endl ;

    for (int iGen = 0 ; iGen < babModel.numberCutGenerators() ; iGen++) {
        CbcCutGenerator *generator = babModel.cutGenerator(iGen) ;
        std::cout
            << generator->cutGeneratorName() << " was tried "
            << generator->numberTimesEntered() << " times and created "
            << generator->numberCutsInTotal() << " cuts of which "
            << generator->numberCutsActive()
            << " were active after adding rounds of cuts" ;
        if (generator->timing()) {
            std::cout << " ( " << generator->timeInCutGenerator() << " seconds)" ;
        }
        std::cout << std::endl ;
    }
# endif

    time2 = CoinCpuTime();
    ctlBlk->totalTime_ += time2 - time1;
    /*
      If we performed integer preprocessing, time to back it out.
    */
    if (ippAction != CbcGenCtlBlk::IPPOff) {
#   if CBC_TRACK_SOLVERS > 0
        std::cout
            << "doBaCParam: solver passed to IPP postprocess is "
            << std::hex << babSolver << std::dec << "." << std::endl ;
#   endif
        ippObj.postProcess(*babSolver);
        babModel.assignSolver(preIppSolver) ;
        babSolver = babModel.solver() ;
#   if CBC_TRACK_SOLVERS > 0
        std::cout
            << "doBaCParam: solver in babModel after IPP postprocess is "
            << std::hex << babSolver << std::dec << "." << std::endl ;
#   endif
    }
    /*
      Write out postprocessed solution to debug file, if requested.
    */
    if (ctlBlk->debugCreate_ == "create" && babModel.bestSolution()) {
        CbcGenParamUtils::saveSolution(babSolver, "debug.file") ;
    }
    /*
      If we have a good solution, detach the solver with the answer. Fill in the
      rest of the status information for the benefit of the wider world.
    */
    bool keepAnswerSolver = false ;
    OsiSolverInterface *answerSolver = 0 ;
    if (babModel.bestSolution()) {
        babModel.setModelOwnsSolver(false) ;
        keepAnswerSolver = true ;
        answerSolver = babSolver ;
    }
    ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwBAC,
                         keepAnswerSolver, answerSolver) ;
    /*
      And one last bit of information & statistics.
    */
    ctlBlk->printBaBStatus() ;
    std::cout << "    " ;
    if (keepAnswerSolver) {
        std::cout
            << "objective " << babModel.getObjValue() << "; " ;
    }
    std::cout
        << babModel.getNodeCount() << " nodes and "
        << babModel.getIterationCount() << " iterations - took "
        << time2 - time1 << " seconds" << std::endl ;

    return (0) ;
}