Changeset 1412


Ignore:
Timestamp:
Jan 5, 2010 11:20:52 AM (9 years ago)
Author:
forrest
Message:

try and modularize threads

Location:
branches/sandbox/Cbc/src
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • branches/sandbox/Cbc/src/CbcModel.cpp

    r1409 r1412  
    1212//#define CBC_DEBUG 1
    1313//#define CHECK_CUT_COUNTS
     14//#define CHECK_NODE
    1415//#define CHECK_NODE_FULL
    1516//#define NODE_LOG
     
    12061207                *feasible = false; // stop search
    12071208            }
     1209#if 0 // probably not needed def CBC_THREAD
     1210            if (master_) {
     1211                lockThread();
     1212                if (parallelMode() > 0) {
     1213                    while (master_->waitForThreadsInTree(0)) {
     1214                        lockThread();
     1215                        double dummyBest;
     1216                        tree_->cleanTree(this, -COIN_DBL_MAX, dummyBest) ;
     1217                        //unlockThread();
     1218                    }
     1219                }
     1220                master_->waitForThreadsInTree(2);
     1221                delete master_;
     1222                master_ = NULL;
     1223                masterThread_ = NULL;
     1224            }
     1225#endif
    12081226        }
    12091227    }
     
    33283346        if (tree_->empty()) {
    33293347#ifdef CBC_THREAD
    3330             if (parallelMode() > 0) {
     3348            if (parallelMode() > 0 && master_) {
    33313349                int anyLeft = master_->waitForThreadsInTree(0);
    3332                 if (!anyLeft)
     3350                if (!anyLeft) {
     3351                    master_->stopThreads(-1);
    33333352                    break;
     3353                }
    33343354            } else {
    33353355                break;
     
    35043524                        }
    35053525                        delete [] newSolution;
     3526#ifdef CBC_THREAD
     3527                        if (master_) {
     3528                            lockThread();
     3529                            if (parallelMode() > 0) {
     3530                                while (master_->waitForThreadsInTree(0)) {
     3531                                    lockThread();
     3532                                    double dummyBest;
     3533                                    tree_->cleanTree(this, -COIN_DBL_MAX, dummyBest) ;
     3534                                    //unlockThread();
     3535                                }
     3536                            } else {
     3537                                double dummyBest;
     3538                                tree_->cleanTree(this, -COIN_DBL_MAX, dummyBest) ;
     3539                            }
     3540                            master_->waitForThreadsInTree(2);
     3541                            delete master_;
     3542                            master_ = NULL;
     3543                            masterThread_ = NULL;
     3544                        }
     3545#endif
    35063546                        if (tree_->size()) {
    35073547                            double dummyBest;
     
    37313771#ifdef CBC_THREAD
    37323772        } else if (parallelMode() > 0) {
    3733             int anyLeft = master_->waitForThreadsInTree(1);
    3734             // may need to go round again
    3735             if (anyLeft)
    3736                 continue;
     3773            //lockThread();
     3774            //node = tree_->bestNode(cutoff) ;
     3775            // Possible one on tree worse than cutoff
     3776            if (true || !node || node->objectiveValue() > cutoff) {
     3777                assert (master_);
     3778                if (master_) {
     3779                    int anyLeft = master_->waitForThreadsInTree(1);
     3780                    // may need to go round again
     3781                    if (anyLeft) {
     3782                        continue;
     3783                    } else {
     3784                        master_->stopThreads(-1);
     3785                    }
     3786                }
     3787            }
     3788            //unlockThread();
    37373789        } else {
    37383790            // Deterministic parallel
     
    37933845    }
    37943846#ifdef CBC_THREAD
    3795     if (numberThreads_) {
     3847    if (master_) {
     3848        master_->stopThreads(-1);
    37963849        master_->waitForThreadsInTree(2);
    37973850        delete master_;
     
    53665419    delete eventHandler_ ;
    53675420    eventHandler_ = NULL ;
     5421#ifdef CBC_THREAD
     5422    // Get rid of all threaded stuff
     5423    delete master_;
     5424#endif
    53685425}
    53695426// Clears out as much as possible (except solver)
     
    74357492                    }
    74367493                }
     7494                unlockThread();
    74377495            }
    74387496            numberTries = 0 ;
     
    82208278    // Get rid of all threaded stuff
    82218279    if (master) {
    8222         master->stopThreads();
     8280        master->stopThreads(0);
    82238281        delete master;
    82248282    }
     
    1270712765                            continue;
    1270812766                        parameters[i-iChunk].solutionValue = heuristicValue;
     12767                        // Don't want a strategy object
     12768                        CbcStrategy * saveStrategy = strategy_;
     12769                        strategy_ = NULL;
    1270912770                        CbcModel * newModel = new CbcModel(*this);
     12771                        strategy_ = saveStrategy;
    1271012772                        assert (!newModel->continuousSolver_);
    1271112773                        if (continuousSolver_)
     
    1272512787                        newModel->numberHeuristics_ = 1;
    1272612788                    }
    12727                     CbcSimpleThread(nThisTime, 0, static_cast<int>(sizeof(argBundle)), parameters);
     12789                    void
     12790                    parallelHeuristics (int numberThreads,
     12791                                        int sizeOfData,
     12792                                        void * argBundle);
     12793                    parallelHeuristics(nThisTime,
     12794                                       static_cast<int>(sizeof(argBundle)),
     12795                                       parameters);
    1272812796                    double cutoff = heuristicValue;
    1272912797                    for (int i = 0; i < chunk; i++) {
     
    1308613154           node->nodeInfo()->numberBranchesLeft(),
    1308713155           node->nodeInfo()->numberPointingToThis()) ;
    13088     printf("\tdepth = %d, z =  %g, unsat = %d, var = %d.\n",
     13156    printf("\tdepth = %d, z =  %g, unsat = %d\n", //var = %d.\n",
    1308913157           node->depth(), node->objectiveValue(),
    13090            node->numberUnsatisfied(),
    13091            node->columnNumber()) ;
     13158           node->numberUnsatisfied());
     13159    //node->columnNumber()) ;
    1309213160#   endif
    1309313161
     
    1391013978        }
    1391113979        lockThread();
     13980        bool locked = true;
    1391213981        if (parallelMode() <= 0) {
    1391313982            if (numberUpdateItems_) {
     
    1398714056                    }
    1398814057                    unlockThread();
    13989 
     14058                    locked = false;
    1399014059                    double estValue = newNode->guessedObjectiveValue() ;
    1399114060                    int found = -1 ;
     
    1403414103                    delete [] newSolution ;
    1403514104                    newNode->setGuessedObjectiveValue(estValue) ;
    14036                     lockThread();
    1403714105                    if (parallelMode() >= 0) {
    1403814106                        if (!masterThread_) // only if serial
     
    1414714215            }
    1414814216        }
    14149         unlockThread();
     14217        if (locked)
     14218            unlockThread();
    1415014219    } else {
    1415114220        // add cuts found to be infeasible (on bound)!
  • branches/sandbox/Cbc/src/CbcSolver.cpp

    r1404 r1412  
    637637{
    638638    OsiSolverInterface * solver = model_.solver();
    639     OsiClpSolverInterface * clpSolver = 
    640                 dynamic_cast< OsiClpSolverInterface*> (solver);
     639    OsiClpSolverInterface * clpSolver =
     640        dynamic_cast< OsiClpSolverInterface*> (solver);
    641641    assert (clpSolver);
    642         ClpSimplex * lpSolver = clpSolver->getModelPtr();
     642    ClpSimplex * lpSolver = clpSolver->getModelPtr();
    643643
    644644    /*
     
    657657    generalMessageHandler->setPrefix(true);
    658658
    659         lpSolver->setPerturbation(50);
     659    lpSolver->setPerturbation(50);
    660660    lpSolver->messageHandler()->setPrefix(false);
    661661
     
    10141014
    10151015int callCbc1(const std::string input2, CbcModel & babSolver,
    1016              int callBack(CbcModel * currentSolver, int whereFrom))
     1016             int callBack(CbcModel * currentSolver, int whereFrom))
    10171017{
    10181018    char * input3 = CoinStrdup(input2.c_str());
     
    10231023
    10241024int callCbc1(const char * input2, CbcModel & model,
    1025              int callBack(CbcModel * currentSolver, int whereFrom))
     1025             int callBack(CbcModel * currentSolver, int whereFrom))
    10261026{
    10271027    char * input = CoinStrdup(input2);
     
    10751075    noPrinting = false;
    10761076    int returnCode = CbcMain1(n + 2, const_cast<const char **>(argv),
    1077                               model, callBack);
     1077                              model, callBack);
    10781078    for (int k = 0; k < n + 2; k++)
    10791079        free(argv[k]);
     
    24632463                            }
    24642464                            solveOptions.setPresolveType(presolveType, preSolve);
    2465                             if (type == CLP_PARAM_ACTION_DUALSIMPLEX || 
    2466                                                                 type == CLP_PARAM_ACTION_SOLVECONTINUOUS) {
     2465                            if (type == CLP_PARAM_ACTION_DUALSIMPLEX ||
     2466                                    type == CLP_PARAM_ACTION_SOLVECONTINUOUS) {
    24672467                                method = ClpSolve::useDual;
    24682468                            } else if (type == CLP_PARAM_ACTION_PRIMALSIMPLEX) {
     
    28922892                            }
    28932893                            // Actually do heuristics
    2894                             doHeuristics(&model_,2,parameters_,
    2895                                 numberParameters_,noPrinting_,initialPumpTune);
     2894                            doHeuristics(&model_, 2, parameters_,
     2895                                         numberParameters_, noPrinting_, initialPumpTune);
    28962896                            if (model_.bestSolution()) {
    28972897                                model_.setProblemStatus(1);
     
    39043904                            }
    39053905                            // Set up heuristics
    3906                             doHeuristics(babModel_,((!miplib)?1:10),parameters_,
    3907                                 numberParameters_,noPrinting_,initialPumpTune);
     3906                            doHeuristics(babModel_, ((!miplib) ? 1 : 10), parameters_,
     3907                                         numberParameters_, noPrinting_, initialPumpTune);
    39083908                            if (!miplib) {
    39093909                                if (parameters_[whichParam(CBC_PARAM_STR_LOCALTREE, numberParameters_, parameters_)].currentOptionAsInteger()) {
     
    42284228                            currentBranchModel = babModel_;
    42294229                            //OsiSolverInterface * strengthenedModel=NULL;
    4230                             if (type == CBC_PARAM_ACTION_BAB || 
    4231                                                                 type == CBC_PARAM_ACTION_MIPLIB) {
     4230                            if (type == CBC_PARAM_ACTION_BAB ||
     4231                                    type == CBC_PARAM_ACTION_MIPLIB) {
    42324232                                if (strategyFlag == 1) {
    42334233                                    // try reduced model
     
    74277427                                fp = stderr;
    74287428                            } else {
    7429                                 if (field[0] == '/' || field[0] == '\\') {
     7429                                bool absolutePath;
     7430                                if (dirsep == '/') {
     7431                                    // non Windows (or cygwin)
     7432                                    absolutePath = (field[0] == '/');
     7433                                } else {
     7434                                    //Windows (non cycgwin)
     7435                                    absolutePath = (field[0] == '\\');
     7436                                    // but allow for :
     7437                                    if (strchr(field.c_str(), ':'))
     7438                                        absolutePath = true;
     7439                                }
     7440                                if (absolutePath) {
    74307441                                    fileName = field;
    74317442                                } else if (field[0] == '~') {
     
    74607471                                        // unbounded
    74617472                                        fprintf(fp, "Unbounded" );
    7462                                     } else if (iStat >= 3&&iStat <= 5) {
    7463                                         if (iStat==3)
    7464                                             fprintf(fp, "Stopped on iterations or time" );
    7465                                       else if (iStat == 4)
    7466                                         fprintf(fp, "Stopped on difficulties" );
    7467                                       else 
    7468                                         fprintf(fp, "Stopped on ctrl-c" );
    7469                                       if (babModel_&&!babModel_->bestSolution())
    7470                                         fprintf(fp," (no integer solution - continuous used)");
     7473                                    } else if (iStat >= 3 && iStat <= 5) {
     7474                                        if (iStat == 3)
     7475                                            fprintf(fp, "Stopped on iterations or time" );
     7476                                        else if (iStat == 4)
     7477                                            fprintf(fp, "Stopped on difficulties" );
     7478                                        else
     7479                                            fprintf(fp, "Stopped on ctrl-c" );
     7480                                        if (babModel_ && !babModel_->bestSolution())
     7481                                            fprintf(fp, " (no integer solution - continuous used)");
    74717482                                    } else if (iStat == 6) {
    74727483                                        // bab infeasible
  • branches/sandbox/Cbc/src/CbcThread.cpp

    r1409 r1412  
    99#include "CbcConfig.h"
    1010
     11//#define THREAD_DEBUG
    1112#include <string>
    1213#include <cassert>
     
    3031#include "CoinTime.hpp"
    3132#ifdef CBC_THREAD
     33/// Thread functions
     34static void * doNodesThread(void * voidInfo);
     35static void * doCutsThread(void * voidInfo);
     36static void * doHeurThread(void * voidInfo);
     37// Default Constructor
     38CbcSpecificThread::CbcSpecificThread ()
     39        : basePointer_(NULL),
     40        masterMutex_(NULL),
     41        locked_(false)
     42{
     43#ifdef CBC_PTHREAD
     44    pthread_mutex_init(&mutex2_, NULL);
     45    pthread_cond_init(&condition2_, NULL);
     46    threadId_.status = 0;
     47#else
     48#endif
     49}
     50// Useful Constructor
     51CbcSpecificThread::CbcSpecificThread (CbcSpecificThread * master, pthread_mutex_t * masterMutex)
     52        : basePointer_(master),
     53        masterMutex_(masterMutex),
     54        locked_(false)
     55
     56{
     57#ifdef CBC_PTHREAD
     58    pthread_mutex_init(&mutex2_, NULL);
     59    pthread_cond_init(&condition2_, NULL);
     60    threadId_.status = 0;
     61#else
     62#endif
     63
     64}
     65// Useful stuff
     66void
     67CbcSpecificThread::setUsefulStuff (CbcSpecificThread * master, void *& masterMutex)
     68
     69{
     70#ifdef CBC_PTHREAD
     71    basePointer_ = master;
     72    if (masterMutex) {
     73        masterMutex_ = reinterpret_cast<pthread_mutex_t *>(masterMutex);
     74    } else {
     75        // create master mutex
     76        masterMutex_ = new pthread_mutex_t;
     77        pthread_mutex_init(masterMutex_, NULL);
     78        masterMutex = reinterpret_cast<void *>(masterMutex_);
     79    }
     80#else
     81#endif
     82}
     83
     84CbcSpecificThread::~CbcSpecificThread()
     85{
     86#ifdef CBC_PTHREAD
     87    pthread_mutex_destroy (&mutex2_);
     88    if (basePointer_ == this) {
     89        pthread_mutex_destroy (masterMutex_);
     90        delete masterMutex_;
     91    }
     92#else
     93#endif
     94}
     95/*
     96  Locks a thread if parallel so that stuff like cut pool
     97  can be updated and/or used.
     98*/
     99void
     100CbcSpecificThread::lockThread()
     101{
     102#ifdef CBC_PTHREAD
     103    // Use master mutex
     104    assert (basePointer_->masterMutex_ == masterMutex_);
     105    pthread_mutex_lock (masterMutex_);
     106#else
     107#endif
     108}
     109/*
     110  Unlocks a thread if parallel to say cut pool stuff not needed
     111*/
     112void
     113CbcSpecificThread::unlockThread()
     114{
     115#ifdef CBC_PTHREAD
     116    // Use master mutex
     117    pthread_mutex_unlock (masterMutex_);
     118#else
     119#endif
     120}
     121//  Locks a thread for testing whether to start etc
     122void
     123CbcSpecificThread::lockThread2(bool doAnyway)
     124{
     125    if (!locked_ || doAnyway) {
     126#ifdef CBC_PTHREAD
     127        pthread_mutex_lock (&mutex2_);
     128#else
     129#endif
     130        locked_ = true;
     131    }
     132}
     133//  Unlocks a thread for testing whether to start etc
     134void
     135CbcSpecificThread::unlockThread2(bool doAnyway)
     136{
     137    if (locked_ || doAnyway) {
     138#ifdef CBC_PTHREAD
     139        pthread_mutex_unlock (&mutex2_);
     140#else
     141#endif
     142        locked_ = false;
     143    }
     144}
     145#ifdef HAVE_CLOCK_GETTIME
     146inline int my_gettime(struct timespec* tp)
     147{
     148    return clock_gettime(CLOCK_REALTIME, tp);
     149}
     150#else
     151#ifndef _MSC_VER
     152inline int my_gettime(struct timespec* tp)
     153{
     154    struct timeval tv;
     155    int ret = gettimeofday(&tv, NULL);
     156    tp->tv_sec = tv.tv_sec;
     157    tp->tv_nsec = tv.tv_usec * 1000;
     158    return ret;
     159}
     160#else
     161inline int my_gettime(struct timespec* tp)
     162{
     163    double t = CoinGetTimeOfDay();
     164    tp->tv_sec = (int)floor(t);
     165    tp->tv_nsec = (int)((tp->tv_sec - floor(t)) / 1000000.0);
     166    return 0;
     167}
     168#endif
     169#endif
     170// Get time
     171static double getTime()
     172{
     173    struct timespec absTime2;
     174    my_gettime(&absTime2);
     175    double time2 = absTime2.tv_sec + 1.0e-9 * absTime2.tv_nsec;
     176    return time2;
     177}
     178// Timed wait in nanoseconds - if negative then seconds
     179void
     180CbcSpecificThread::timedWait(int time)
     181{
     182
     183#ifdef CBC_PTHREAD
     184    struct timespec absTime;
     185    my_gettime(&absTime);
     186    if (time > 0) {
     187        absTime.tv_nsec += time;
     188        if (absTime.tv_nsec >= 1000000000) {
     189            absTime.tv_nsec -= 1000000000;
     190            absTime.tv_sec++;
     191        }
     192    } else {
     193        absTime.tv_sec -= time;
     194    }
     195    pthread_cond_timedwait(&condition2_, &mutex2_, &absTime);
     196#else
     197#endif
     198}
     199// Signal
     200void
     201CbcSpecificThread::signal()
     202{
     203#ifdef CBC_PTHREAD
     204    pthread_cond_signal(&condition2_);
     205#else
     206#endif
     207}
     208// Actually starts a thread
     209void
     210CbcSpecificThread::startThread(void * (*routine ) (void *), CbcThread * thread)
     211{
     212#ifdef CBC_PTHREAD
     213    pthread_create(&(threadId_.thr), NULL, routine, thread);
     214    threadId_.status = 1;
     215#else
     216#endif
     217}
     218// Exits thread (from master)
     219int
     220CbcSpecificThread::exit()
     221{
     222#ifdef CBC_PTHREAD
     223    pthread_cond_signal(&condition2_); // unlock
     224    return pthread_join(threadId_.thr, NULL);
     225#else
     226#endif
     227}
     228// Exits thread
     229void
     230CbcSpecificThread::exitThread()
     231{
     232#ifdef CBC_PTHREAD
     233    pthread_mutex_unlock(&mutex2_);
     234    pthread_exit(NULL);
     235#else
     236#endif
     237
     238}
     239// Get status
     240int
     241CbcSpecificThread::status() const
     242{
     243#ifdef CBC_PTHREAD
     244    return threadId_.status;
     245#else
     246#endif
     247}
     248// Set status
     249void
     250CbcSpecificThread::setStatus(int value)
     251{
     252#ifdef CBC_PTHREAD
     253    threadId_.status = value;
     254#else
     255#endif
     256}
     257// Parallel heuristics
     258void
     259parallelHeuristics (int numberThreads,
     260                    int sizeOfData,
     261                    void * argBundle)
     262{
     263    Coin_pthread_t * threadId = new Coin_pthread_t [numberThreads];
     264    char * args = reinterpret_cast<char *>(argBundle);
     265    for (int i = 0; i < numberThreads; i++) {
     266        pthread_create(&(threadId[i].thr), NULL, doHeurThread,
     267                       args + i*sizeOfData);
     268    }
     269    // now wait
     270    for (int i = 0; i < numberThreads; i++) {
     271        pthread_join(threadId[i].thr, NULL);
     272    }
     273    delete [] threadId;
     274}
     275// End of specific thread stuff
     276
    32277/// Default constructor
    33278CbcThread::CbcThread()
     
    37282        node_(NULL), // filled in every time
    38283        createdNode_(NULL), // filled in every time on return
    39         mutex2_(NULL), // for waking up threads
    40         condition2_(NULL), // for waking up thread
    41284        returnCode_(-1), // -1 available, 0 busy, 1 finished , 2??
    42285        timeLocked_(0.0),
     
    57300{
    58301}
    59 // Constructor with base model
    60 CbcThread::CbcThread (CbcModel & model, int deterministic, CbcModel * baseModel)
    61         :
    62         baseModel_(baseModel),
    63         thisModel_(&model),
    64         node_(NULL), // filled in every time
    65         createdNode_(NULL), // filled in every time on return
    66         mutex2_(NULL), // for waking up threads
    67         condition2_(NULL), // for waking up thread
    68         returnCode_(-1), // -1 available, 0 busy, 1 finished , 2??
    69         timeLocked_(0.0),
    70         timeWaitingToLock_(0.0),
    71         timeWaitingToStart_(0.0),
    72         timeInThread_(0.0),
    73         numberTimesLocked_(0),
    74         numberTimesUnlocked_(0),
    75         numberTimesWaitingToStart_(0),
    76         dantzigState_(0), // 0 unset, -1 waiting to be set, 1 set
    77         locked_(false),
    78         nDeleteNode_(0),
    79         delNode_(NULL),
    80         maxDeleteNode_(0),
    81         nodesThisTime_(0),
    82         iterationsThisTime_(0),
    83         deterministic_(deterministic)
    84 {
    85 }
    86302void
    87303CbcThread::gutsOfDelete()
     
    91307    node_ = NULL;
    92308    createdNode_ = NULL;
    93     mutex2_ = NULL;
    94     condition2_ = NULL;
    95309    delNode_ = NULL;
    96 }
    97 void CbcThread::gutsOfCopy(const CbcThread & rhs)
    98 {
    99     baseModel_ = rhs.baseModel_;
    100     thisModel_ = rhs.thisModel_;
    101     node_ = rhs.node_;
    102     createdNode_ = rhs.createdNode_;
    103     mutex2_ = rhs.mutex2_;
    104     condition2_ = rhs.condition2_;
    105     returnCode_ = rhs.returnCode_;
    106     timeLocked_ = rhs.timeLocked_;
    107     timeWaitingToLock_ = rhs.timeWaitingToLock_;
    108     timeWaitingToStart_ = rhs.timeWaitingToStart_;
    109     timeInThread_ = rhs.timeInThread_;
    110     numberTimesLocked_ = rhs.numberTimesLocked_;
    111     numberTimesUnlocked_ = rhs.numberTimesUnlocked_;
    112     numberTimesWaitingToStart_ = rhs.numberTimesWaitingToStart_;
    113     dantzigState_ = rhs.dantzigState_;
    114     locked_ = rhs.locked_;
    115     nDeleteNode_ = rhs.nDeleteNode_;
    116     delNode_ = rhs.delNode_;
    117     maxDeleteNode_ = rhs.maxDeleteNode_;
    118     nodesThisTime_ = rhs.nodesThisTime_;
    119     iterationsThisTime_ = rhs.iterationsThisTime_;
    120     deterministic_ = rhs.deterministic_;
    121310}
    122311// Destructor
     
    124313{
    125314}
    126 // Assignment operator
    127 CbcThread &
    128 CbcThread::operator=(const CbcThread & rhs)
    129 {
    130     if (this != &rhs) {
    131         gutsOfDelete();
    132         gutsOfCopy(rhs);
    133     }
    134     return *this;
     315// Fills in useful stuff
     316void
     317CbcThread::setUsefulStuff (CbcModel * model, int deterministic, CbcModel * baseModel,
     318                           CbcThread * master,
     319                           void *& masterMutex)
     320{
     321    baseModel_ = baseModel;
     322    thisModel_ = model;
     323    deterministic_ = deterministic;
     324    threadStuff_.setUsefulStuff(&master->threadStuff_, masterMutex);
     325    node_ = NULL;
     326    createdNode_ = NULL;
     327    master_ = master;
     328    returnCode_ = -1;
     329    timeLocked_ = 0.0;
     330    timeWaitingToLock_ = 0.0;
     331    timeWaitingToStart_ = 0.0;
     332    timeInThread_ = 0.0;
     333    numberTimesLocked_ = 0;
     334    numberTimesUnlocked_ = 0;
     335    numberTimesWaitingToStart_ = 0;
     336    dantzigState_ = 0; // 0 unset, -1 waiting to be set, 1 set
     337    locked_ = false;
     338    delNode_ = NULL;
     339    maxDeleteNode_ = 0;
     340    nDeleteNode_ = 0;
     341    nodesThisTime_ = 0;
     342    iterationsThisTime_ = 0;
     343    if (model != baseModel) {
     344        // thread
     345        thisModel_->setInfoInChild(-3, this);
     346        if (deterministic_ >= 0)
     347            thisModel_->moveToModel(baseModel, -1);
     348        if (deterministic == -1)
     349            threadStuff_.startThread( doCutsThread, this);
     350        else
     351            threadStuff_.startThread( doNodesThread, this);
     352    }
    135353}
    136354/*
     
    142360{
    143361    if (!locked_) {
    144         struct timespec absTime2;
    145         my_gettime(&absTime2);
    146         double time2 = absTime2.tv_sec + 1.0e-9 * absTime2.tv_nsec;
    147         pthread_mutex_lock (mutex_);
     362        double time2 = getTime();
     363        threadStuff_.lockThread();
    148364        locked_ = true;
    149         my_gettime(&absTime_);
    150         double time = absTime_.tv_sec + 1.0e-9 * absTime_.tv_nsec;
    151         timeWaitingToLock_ += time - time2;;
     365        timeWhenLocked_ = getTime();
     366        timeWaitingToLock_ += timeWhenLocked_ - time2;;
    152367        numberTimesLocked_++;
     368#ifdef THREAD_DEBUG
     369        lockCount_ ++;
     370#if THREAD_DEBUG>1
     371        if (threadNumber_ == -1)
     372            printf("locking master %d\n", lockCount_);
     373        else
     374            printf("locking thread %d %d\n", threadNumber_, lockCount_);
     375#endif
     376    } else {
     377        if (threadNumber_ == -1)
     378            printf("master already locked %d\n", lockCount_);
     379        else
     380            printf("thread already locked %d %d\n", threadNumber_, lockCount_);
     381#endif
    153382    }
    154383}
     
    161390    if (locked_) {
    162391        locked_ = false;
    163         pthread_mutex_unlock (mutex_);
    164         struct timespec absTime2;
    165         my_gettime(&absTime2);
    166         double time2 = absTime2.tv_sec + 1.0e-9 * absTime2.tv_nsec;
    167         double time = absTime_.tv_sec + 1.0e-9 * absTime_.tv_nsec;
    168         timeLocked_ += time2 - time;
     392        threadStuff_.unlockThread();
     393        double time2 = getTime();
     394        timeLocked_ += time2 - timeWhenLocked_;
    169395        numberTimesUnlocked_++;
     396#ifdef THREAD_DEBUG
     397#if THREAD_DEBUG>1
     398        if (threadNumber_ == -1)
     399            printf("unlocking master %d\n", lockCount_);
     400        else
     401            printf("unlocking thread %d %d\n", threadNumber_, lockCount_);
     402#endif
    170403    } else {
    171         printf("already unlocked\n");
    172     }
     404        if (threadNumber_ == -1)
     405            printf("master already unlocked %d\n", lockCount_);
     406        else
     407            printf("thread already unlocked %d %d\n", threadNumber_, lockCount_);
     408#endif
     409    }
     410}
     411/* Wait for child to have return code NOT == to currentCode
     412   type - 0 timed wait
     413   1 wait
     414   returns true if return code changed */
     415bool
     416CbcThread::wait(int type, int currentCode)
     417{
     418    if (!type) {
     419        // just timed wait
     420        master_->threadStuff_.lockThread2();
     421        master_->threadStuff_.timedWait(1000000);
     422        master_->threadStuff_.unlockThread2();
     423    } else {
     424        // wait until return code changes
     425        while (returnCode_ == currentCode) {
     426            threadStuff_.signal();
     427            master_->threadStuff_.lockThread2();
     428            master_->threadStuff_.timedWait(1000000);
     429            master_->threadStuff_.unlockThread2();
     430        }
     431    }
     432    return (returnCode_ != currentCode);
     433}
     434#if 0
     435pthread_cond_signal(&condition2_);
     436-
     437if (!locked_)
     438{
     439    pthread_mutex_lock (&mutex2_);
     440    locked_ = true;
     441}
     442-
     443pthread_cond_timedwait(&condition2_, &mutex2_, &absTime);
     444-
     445if (locked_)
     446{
     447    pthread_mutex_unlock (&mutex2_);
     448    locked_ = false;
     449}
     450#endif
     451// Waits until returnCode_ goes to zero
     452void
     453CbcThread::waitThread()
     454{
     455    double time = getTime();
     456    threadStuff_.lockThread2();
     457    while (returnCode_) {
     458        threadStuff_.timedWait(-10); // 10 seconds
     459    }
     460    timeWaitingToStart_ += getTime() - time;
     461    numberTimesWaitingToStart_++;
     462}
     463// Just wait for so many nanoseconds
     464void
     465CbcThread::waitNano(int time)
     466{
     467    threadStuff_.lockThread2();
     468    threadStuff_.timedWait(time);
     469    threadStuff_.unlockThread2();
     470}
     471// Signal child to carry on
     472void
     473CbcThread::signal()
     474{
     475    threadStuff_.signal();
     476}
     477// Lock from master with mutex2 and signal before lock
     478void
     479CbcThread::lockFromMaster()
     480{
     481    threadStuff_.signal();
     482    master_->threadStuff_.lockThread2(true);
     483}
     484// Unlock from master with mutex2 and signal after unlock
     485void
     486CbcThread::unlockFromMaster()
     487{
     488    master_->threadStuff_.unlockThread2(true); // unlock anyway
     489    threadStuff_.signal();
     490}
     491// Lock from thread with mutex2 and signal before lock
     492void
     493CbcThread::lockFromThread()
     494{
     495    master_->threadStuff_.signal();
     496    threadStuff_.lockThread2();
     497}
     498// Unlock from thread with mutex2 and signal after unlock
     499void
     500CbcThread::unlockFromThread()
     501{
     502    master_->threadStuff_.signal();
     503    threadStuff_.unlockThread2();
     504}
     505// Exits thread (from master)
     506int
     507CbcThread::exit()
     508{
     509    return threadStuff_.exit();
     510}
     511// Exits thread
     512void
     513CbcThread::exitThread()
     514{
     515    threadStuff_.exitThread();
    173516}
    174517// Default constructor
     
    178521        children_(NULL),
    179522        type_(0),
    180         threadId_(NULL),
    181523        threadCount_(NULL),
    182524        threadModel_(NULL),
    183         mutex2_(NULL),
    184         condition2_(NULL),
    185525        numberObjects_(0),
    186526        saveObjects_(NULL),
     
    189529{
    190530}
    191 /// Thread functions
    192 static void * doNodesThread(void * voidInfo);
    193 static void * doCutsThread(void * voidInfo);
    194 static void * doHeurThread(void * voidInfo);
    195531// Constructor with model
    196532CbcBaseModel::CbcBaseModel (CbcModel & model,  int type)
     
    198534        children_(NULL),
    199535        type_(type),
    200         threadId_(NULL),
    201536        threadCount_(NULL),
    202537        threadModel_(NULL),
    203         mutex2_(NULL),
    204         condition2_(NULL),
    205538        numberObjects_(0),
    206539        saveObjects_(NULL),
     
    210543    numberThreads_ = model.getNumberThreads();
    211544    if (numberThreads_) {
    212         threadId_ = new Coin_pthread_t [numberThreads_];
     545        children_ = new CbcThread [numberThreads_+1];
     546        // Do a partial one for base model
     547        void * mutex_main = NULL;
     548        children_[numberThreads_].setUsefulStuff(&model, type_, &model,
     549                children_ + numberThreads_, mutex_main);
     550#ifdef THREAD_DEBUG
     551        children_[numberThreads_].threadNumber_ = -1;
     552        children_[numberThreads_].lockCount_ = 0;
     553#endif
    213554        threadCount_ = new int [numberThreads_];
    214555        CoinZeroN(threadCount_, numberThreads_);
    215         children_ = new CbcThread [numberThreads_+1];
    216         pthread_mutex_init(&mutex_main_, NULL);
    217         pthread_cond_init(&condition_main_, NULL);
    218         pthread_mutex_init(&condition_mutex_, NULL);
    219556        threadModel_ = new CbcModel * [numberThreads_+1];
    220         mutex2_ = new pthread_mutex_t [numberThreads_];
    221         condition2_ = new pthread_cond_t [numberThreads_];
    222557        memset(threadStats_, 0, sizeof(threadStats_));
    223558        if (type_ > 0) {
     
    233568        model.setStrategy(NULL);
    234569        for (int i = 0; i < numberThreads_; i++) {
    235             pthread_mutex_init(mutex2_ + i, NULL);
    236             pthread_cond_init(condition2_ + i, NULL);
    237             threadId_[i].status = 0;
    238570            threadModel_[i] = new CbcModel(model, true);
    239             //threadModel_[i]->setMasterThread(children_+i);
    240             children_[i] = CbcThread(*threadModel_[i], type_, &model);
    241571            threadModel_[i]->synchronizeHandlers(1);
    242572#ifdef COIN_HAS_CLP
     
    248578                solver->setCbcModel(thisModel);
    249579#endif
    250             threadModel_[i]->setInfoInChild(-3, children_ + i);
    251             if (type_ >= 0)
    252                 threadModel_[i]->moveToModel(&model, -1);
    253             children_[i].thisModel_ = threadModel_[i];
    254             children_[i].node_ = NULL;
    255             children_[i].createdNode_ = NULL;
    256             children_[i].threadIdOfBase_.thr = pthread_self();
    257             children_[i].mutex_ = &mutex_main_;
    258             children_[i].master_ = children_ + numberThreads_;
    259             children_[i].mutex2_ = mutex2_ + i;
    260             children_[i].condition2_ = condition2_ + i;
    261             children_[i].returnCode_ = -1;
    262             children_[i].timeLocked_ = 0.0;
    263             children_[i].timeWaitingToLock_ = 0.0;
    264             children_[i].timeWaitingToStart_ = 0.0;
    265             children_[i].timeInThread_ = 0.0;
    266             children_[i].numberTimesLocked_ = 0;
    267             children_[i].numberTimesUnlocked_ = 0;
    268             children_[i].numberTimesWaitingToStart_ = 0;
    269             children_[i].dantzigState_ = 0; // 0 unset, -1 waiting to be set, 1 set
    270             children_[i].locked_ = false;
    271             children_[i].delNode_ = NULL;
    272             children_[i].maxDeleteNode_ = 0;
    273             children_[i].nDeleteNode_ = 0;
    274             children_[i].nodesThisTime_ = 0;
    275             children_[i].iterationsThisTime_ = 0;
    276             if (type == -1)
    277                 pthread_create(&(threadId_[i].thr), NULL, doCutsThread, children_ + i);
    278             else
    279                 pthread_create(&(threadId_[i].thr), NULL, doNodesThread, children_ + i);
    280             threadId_[i].status = 1;
     580            children_[i].setUsefulStuff(threadModel_[i], type_, &model,
     581                                        children_ + numberThreads_, mutex_main);
     582#ifdef THREAD_DEBUG
     583            children_[i].threadNumber_ = i;
     584            children_[i].lockCount_ = 0;
     585#endif
    281586        }
    282587        model.setStrategy(saveStrategy);
    283         // Do a partial one for base model
    284         children_[numberThreads_].baseModel_ = &model;
    285         //model.setMasterThread(children_+numberThreads_);
    286         threadModel_[numberThreads_] = &model;
    287         children_[numberThreads_].node_ = NULL;
    288         children_[numberThreads_].mutex_ = &mutex_main_;
    289         children_[numberThreads_].condition2_ = &condition_main_;
    290         children_[numberThreads_].mutex2_ = &condition_mutex_;
    291         children_[numberThreads_].timeLocked_ = 0.0;
    292         children_[numberThreads_].timeWaitingToLock_ = 0.0;
    293         children_[numberThreads_].numberTimesLocked_ = 0;
    294         children_[numberThreads_].numberTimesUnlocked_ = 0;
    295         children_[numberThreads_].locked_ = false;
    296588    }
    297589}
    298590// Stop threads
    299591void
    300 CbcBaseModel::stopThreads()
    301 {
     592CbcBaseModel::stopThreads(int type)
     593{
     594    if (type < 0) {
     595        for (int i = 0; i < numberThreads_; i++) {
     596            assert (children_[i].returnCode() == -1);
     597        }
     598        return;
     599    }
    302600    for (int i = 0; i < numberThreads_; i++) {
    303         while (children_[i].returnCode_ == 0) {
    304             pthread_cond_signal(children_[i].condition2_); // unlock
    305             pthread_mutex_lock(children_[numberThreads_].mutex2_);
    306             struct timespec absTime;
    307             my_gettime(&absTime);
    308             absTime.tv_nsec += 1000000; // millisecond
    309             if (absTime.tv_nsec >= 1000000000) {
    310                 absTime.tv_nsec -= 1000000000;
    311                 absTime.tv_sec++;
    312             }
    313             pthread_cond_timedwait(children_[numberThreads_].condition2_, children_[numberThreads_].mutex2_, &absTime);
    314             my_gettime(&absTime);
    315             pthread_mutex_unlock(children_[numberThreads_].mutex2_);
    316         }
     601        children_[i].wait(1, 0);
     602        assert (children_[i].returnCode() == -1);
    317603        threadModel_[i]->setInfoInChild(-2, NULL);
    318         children_[i].returnCode_ = 0;
    319         pthread_cond_signal(children_[i].condition2_); // unlock
    320         pthread_join(threadId_[i].thr, NULL);
    321         threadId_[i].status = 0;
    322         pthread_mutex_destroy (children_[i].mutex2_);
    323         pthread_cond_destroy (children_[i].condition2_);
    324     }
    325     pthread_cond_destroy (children_[numberThreads_].condition2_);
    326     pthread_mutex_destroy (children_[numberThreads_].mutex2_);
     604        children_[i].setReturnCode( 0);
     605        children_[i].exit();
     606        children_[i].setStatus( 0);
     607    }
    327608    // delete models and solvers
    328609    for (int i = 0; i < numberThreads_; i++) {
     
    330611        delete threadModel_[i];
    331612    }
    332     delete [] mutex2_;
    333     delete [] condition2_;
    334     delete [] threadId_;
    335613    delete [] children_;
    336614    delete [] threadModel_;
     
    338616        delete saveObjects_[i];
    339617    delete [] saveObjects_;
    340     mutex2_ = NULL;
    341     condition2_ = NULL;
    342     threadId_ = NULL;
    343618    children_ = NULL;
    344619    threadModel_ = NULL;
     
    351626CbcBaseModel::waitForThreadsInTree(int type)
    352627{
    353     CbcModel * baseModel = children_[0].baseModel_;
     628    CbcModel * baseModel = children_[0].baseModel();
    354629    int anyLeft = 0;
    355630    // May be able to combine parts later
    356631
    357632    if (type == 0) {
     633        bool locked = true;
    358634#ifdef COIN_DEVELOP
    359635        printf("empty\n");
     
    363639            int iThread;
    364640            for (iThread = 0; iThread < numberThreads_; iThread++) {
    365                 if (threadId_[iThread].status) {
    366                     if (children_[iThread].returnCode_ == 0)
     641                if (children_[iThread].status()) {
     642                    if (children_[iThread].returnCode() == 0)
    367643                        break;
    368644                }
     
    373649#endif
    374650                unlockThread();
    375                 pthread_cond_signal(children_[iThread].condition2_); // unlock in case
    376                 while (true) {
    377                     pthread_mutex_lock(children_[numberThreads_].mutex2_);
    378                     struct timespec absTime;
    379                     my_gettime(&absTime);
    380                     double time = absTime.tv_sec + 1.0e-9 * absTime.tv_nsec;
    381                     absTime.tv_nsec += 1000000; // millisecond
    382                     if (absTime.tv_nsec >= 1000000000) {
    383                         absTime.tv_nsec -= 1000000000;
    384                         absTime.tv_sec++;
    385                     }
    386                     pthread_cond_timedwait(children_[numberThreads_].condition2_, children_[numberThreads_].mutex2_, &absTime);
    387                     my_gettime(&absTime);
    388                     double time2 = absTime.tv_sec + 1.0e-9 * absTime.tv_nsec;
    389                     children_[numberThreads_].timeInThread_ += time2 - time;
    390                     pthread_mutex_unlock(children_[numberThreads_].mutex2_);
    391                     if (children_[iThread].returnCode_ != 0)
    392                         break;
    393                     pthread_cond_signal(children_[iThread].condition2_); // unlock
    394                 }
     651                locked = false;
     652                children_[iThread].wait(1, 0);
     653                assert(children_[iThread].returnCode() == 1);
    395654                threadModel_[iThread]->moveToModel(baseModel, 1);
     655#ifdef THREAD_PRINT
     656                printf("off thread2 %d node %x\n", iThread, children_[iThread].node());
     657#endif
     658                children_[iThread].setNode(NULL);
    396659                anyLeft = 1;
    397                 assert (children_[iThread].returnCode_ == 1);
    398                 if (children_[iThread].dantzigState_ == -1) {
     660                assert (children_[iThread].returnCode() == 1);
     661                if (children_[iThread].dantzigState() == -1) {
    399662                    // 0 unset, -1 waiting to be set, 1 set
    400                     children_[iThread].dantzigState_ = 1;
    401                     CbcModel * model = children_[iThread].thisModel_;
     663                    children_[iThread].setDantzigState(1);
     664                    CbcModel * model = children_[iThread].thisModel();
    402665                    OsiClpSolverInterface * clpSolver2
    403666                    = dynamic_cast<OsiClpSolverInterface *> (model->solver());
     
    408671                }
    409672                // say available
    410                 children_[iThread].returnCode_ = -1;
     673                children_[iThread].setReturnCode( -1);
    411674                threadStats_[4]++;
    412675#ifdef COIN_DEVELOP
     
    420683                // now check if any have just finished
    421684                for (iThread = 0; iThread < numberThreads_; iThread++) {
    422                     if (threadId_[iThread].status) {
    423                         if (children_[iThread].returnCode_ == 1)
     685                    if (children_[iThread].status()) {
     686                        if (children_[iThread].returnCode() == 1)
    424687                            break;
    425688                    }
     
    427690                if (iThread < numberThreads_) {
    428691                    unlockThread();
     692                    locked = false;
    429693                    threadModel_[iThread]->moveToModel(baseModel, 1);
     694#ifdef THREAD_PRINT
     695                    printf("off thread3 %d node %x\n", iThread, children_[iThread].node());
     696#endif
     697                    children_[iThread].setNode(NULL);
    430698                    anyLeft = 1;
    431                     assert (children_[iThread].returnCode_ == 1);
     699                    assert (children_[iThread].returnCode() == 1);
    432700                    // say available
    433                     children_[iThread].returnCode_ = -1;
     701                    children_[iThread].setReturnCode( -1);
    434702                    threadStats_[4]++;
    435703#ifdef COIN_DEVELOP
     
    443711                printf("tree not empty!!!!!!\n");
    444712#endif
     713                if (locked)
     714                    unlockThread();
    445715                return 1;
    446716                break;
    447717            }
    448718            for (iThread = 0; iThread < numberThreads_; iThread++) {
    449                 if (threadId_[iThread].status) {
    450                     if (children_[iThread].returnCode_ != -1) {
     719                if (children_[iThread].status()) {
     720                    if (children_[iThread].returnCode() != -1) {
    451721                        printf("bad end of tree\n");
    452722                        abort();
     
    459729        printf("finished ************\n");
    460730#endif
    461         if (!anyLeft)
     731        if (locked)
    462732            unlockThread();
    463733        return anyLeft;
     
    474744        // Start one off if any available
    475745        for (iThread = 0; iThread < numberThreads_; iThread++) {
    476             if (children_[iThread].returnCode_ == -1)
     746            if (children_[iThread].returnCode() == -1)
    477747                break;
    478748        }
    479749        if (iThread < numberThreads_) {
    480             children_[iThread].node_ = node;
    481             //printf("empty thread %d node %x\n",iThread,children_[iThread].node_);
    482             assert (children_[iThread].returnCode_ == -1);
     750            children_[iThread].setNode(node);
     751#ifdef THREAD_PRINT
     752            printf("empty thread %d node %x\n", iThread, children_[iThread].node());
     753#endif
     754            assert (children_[iThread].returnCode() == -1);
    483755            // say in use
    484756            threadModel_[iThread]->moveToModel(baseModel, 0);
    485757            // This has to be AFTER moveToModel
    486             children_[iThread].returnCode_ = 0;
    487             pthread_cond_signal(children_[iThread].condition2_); // unlock
     758            children_[iThread].setReturnCode( 0);
     759            children_[iThread].signal();
    488760            threadCount_[iThread]++;
    489761        }
     
    491763        // see if any finished
    492764        for (iThread = 0; iThread < numberThreads_; iThread++) {
    493             if (children_[iThread].returnCode_ > 0)
     765            if (children_[iThread].returnCode() > 0)
    494766                break;
    495767        }
     
    497769        if (iThread < numberThreads_) {
    498770            threadModel_[iThread]->moveToModel(baseModel, 1);
     771#ifdef THREAD_PRINT
     772            printf("off thread4 %d node %x\n", iThread, children_[iThread].node());
     773#endif
     774            children_[iThread].setNode(NULL);
    499775            anyLeft = 1;
    500             assert (children_[iThread].returnCode_ == 1);
     776            assert (children_[iThread].returnCode() == 1);
    501777            // say available
    502             children_[iThread].returnCode_ = -1;
     778            children_[iThread].setReturnCode( -1);
    503779            // carry on
    504780            threadStats_[3]++;
     
    506782            // Start one off if any available
    507783            for (iThread = 0; iThread < numberThreads_; iThread++) {
    508                 if (children_[iThread].returnCode_ == -1)
     784                if (children_[iThread].returnCode() == -1)
    509785                    break;
    510786            }
     
    521797            bool finished = false;
    522798            while (!finished) {
    523                 pthread_mutex_lock(children_[numberThreads_].mutex2_);
    524                 struct timespec absTime;
    525                 my_gettime(&absTime);
    526                 double time = absTime.tv_sec + 1.0e-9 * absTime.tv_nsec;
    527                 absTime.tv_nsec += 1000000; // millisecond
    528                 if (absTime.tv_nsec >= 1000000000) {
    529                     absTime.tv_nsec -= 1000000000;
    530                     absTime.tv_sec++;
    531                 }
    532                 pthread_cond_timedwait(children_[numberThreads_].condition2_, children_[numberThreads_].mutex2_, &absTime);
    533                 my_gettime(&absTime);
    534                 double time2 = absTime.tv_sec + 1.0e-9 * absTime.tv_nsec;
    535                 children_[numberThreads_].timeInThread_ += time2 - time;
    536                 pthread_mutex_unlock(children_[numberThreads_].mutex2_);
     799                double time = getTime();
     800                children_[numberThreads_].wait(0, 0);
     801                children_[numberThreads_].incrementTimeInThread(getTime() - time);
    537802                for (iThread = 0; iThread < numberThreads_; iThread++) {
    538                     if (children_[iThread].returnCode_ > 0) {
     803                    if (children_[iThread].returnCode() > 0) {
    539804                        finished = true;
    540805                        break;
    541                     } else if (children_[iThread].returnCode_ == 0) {
    542                         pthread_cond_signal(children_[iThread].condition2_); // unlock
     806                    } else if (children_[iThread].returnCode() == 0) {
     807                        children_[iThread].signal(); // unlock
    543808                    }
    544809                }
     
    548813            threadModel_[iThread]->moveToModel(baseModel, 1);
    549814            anyLeft = 1;
    550             node = children_[iThread].node_;
    551             //printf("off thread %d node %x\n",iThread,children_[iThread].node_);
    552             children_[iThread].node_ = NULL;
    553             assert (children_[iThread].returnCode_ == 1);
     815#ifdef THREAD_PRINT
     816            printf("off thread %d node %x\n", iThread, children_[iThread].node());
     817#endif
     818            children_[iThread].setNode(NULL);
     819            assert (children_[iThread].returnCode() == 1);
    554820            // say available
    555             children_[iThread].returnCode_ = -1;
     821            children_[iThread].setReturnCode( -1);
    556822        }
    557823        // carry on
    558824        threadStats_[2]++;
    559825        for (int iThread = 0; iThread < numberThreads_; iThread++) {
    560             if (threadId_[iThread].status) {
    561                 if (children_[iThread].returnCode_ != -1) {
     826            if (children_[iThread].status()) {
     827                if (children_[iThread].returnCode() != -1) {
    562828                    anyLeft = 1;
    563829                    break;
     
    567833        return anyLeft;
    568834    } else if (type == 2) {
     835        assert (baseModel->tree()->empty());
     836        int i;
     837        for (i = 0; i < numberThreads_; i++)
     838            assert (children_[i].returnCode() == -1);
    569839        // do statistics
    570         int i;
    571840        // Seems to be bug in CoinCpu on Linux - does threads as well despite documentation
    572841        double time = 0.0;
    573842        for (i = 0; i < numberThreads_; i++)
    574             time += children_[i].timeInThread_;
     843            time += children_[i].timeInThread();
    575844        bool goodTimer = time < (baseModel->getCurrentSeconds());
    576845        for (i = 0; i < numberThreads_; i++) {
    577             while (children_[i].returnCode_ == 0) {
    578                 pthread_cond_signal(children_[i].condition2_); // unlock
    579                 pthread_mutex_lock(children_[numberThreads_].mutex2_);
    580                 struct timespec absTime;
    581                 my_gettime(&absTime);
    582                 absTime.tv_nsec += 1000000; // millisecond
    583                 if (absTime.tv_nsec >= 1000000000) {
    584                     absTime.tv_nsec -= 1000000000;
    585                     absTime.tv_sec++;
    586                 }
    587                 pthread_cond_timedwait(children_[numberThreads_].condition2_, children_[numberThreads_].mutex2_, &absTime);
    588                 my_gettime(&absTime);
    589                 pthread_mutex_unlock(children_[numberThreads_].mutex2_);
    590             }
    591             pthread_cond_signal(children_[i].condition2_); // unlock
    592             pthread_mutex_lock(children_[numberThreads_].mutex2_); // not sure necessary but have had one hang on interrupt
     846            while (children_[i].returnCode() == 0) {
     847                children_[i].signal();
     848                double time = getTime();
     849                children_[numberThreads_].wait(0, 0);
     850                children_[numberThreads_].incrementTimeInThread(getTime() - time);
     851            }
     852            children_[i].lockFromMaster();
    593853            threadModel_[i]->setNumberThreads(0); // say exit
    594             if (children_[i].deterministic_ > 0)
    595                 delete [] children_[i].delNode_;
    596             children_[i].returnCode_ = 0;
    597             pthread_mutex_unlock(children_[numberThreads_].mutex2_);
    598             pthread_cond_signal(children_[i].condition2_); // unlock
    599             //if (!stopped)
    600             //pthread_join(threadId[i],NULL);
     854            if (children_[i].deterministic() > 0)
     855                delete [] children_[i].delNode();
     856            children_[i].setReturnCode( 0);
     857            children_[i].unlockFromMaster();
    601858            int returnCode;
    602             returnCode = pthread_join(threadId_[i].thr, NULL);
    603             threadId_[i].status = 0;
     859            returnCode = children_[i].exit();
     860            children_[i].setStatus( 0);
    604861            assert (!returnCode);
    605862            //else
    606             //pthread_kill(threadId[i]); // kill rather than try and synchronize
    607863            threadModel_[i]->moveToModel(baseModel, 2);
    608             pthread_mutex_destroy (children_[i].mutex2_);
    609             pthread_cond_destroy (children_[i].condition2_);
    610             assert (children_[i].numberTimesLocked_ == children_[i].numberTimesUnlocked_);
     864            assert (children_[i].numberTimesLocked() == children_[i].numberTimesUnlocked());
    611865            baseModel->messageHandler()->message(CBC_THREAD_STATS, baseModel->messages())
    612866            << "Thread";
    613867            baseModel->messageHandler()->printing(true)
    614             << i << threadCount_[i] << children_[i].timeWaitingToStart_;
    615             baseModel->messageHandler()->printing(goodTimer) << children_[i].timeInThread_;
     868            << i << threadCount_[i] << children_[i].timeWaitingToStart();
     869            baseModel->messageHandler()->printing(goodTimer) << children_[i].timeInThread();
    616870            baseModel->messageHandler()->printing(false) << 0.0;
    617             baseModel->messageHandler()->printing(true) << children_[i].numberTimesLocked_
    618             << children_[i].timeLocked_ << children_[i].timeWaitingToLock_
     871            baseModel->messageHandler()->printing(true) << children_[i].numberTimesLocked()
     872            << children_[i].timeLocked() << children_[i].timeWaitingToLock()
    619873            << CoinMessageEol;
    620874        }
    621         assert (children_[numberThreads_].numberTimesLocked_ == children_[numberThreads_].numberTimesUnlocked_);
     875        assert (children_[numberThreads_].numberTimesLocked() == children_[numberThreads_].numberTimesUnlocked());
    622876        baseModel->messageHandler()->message(CBC_THREAD_STATS, baseModel->messages())
    623877        << "Main thread";
    624878        baseModel->messageHandler()->printing(false) << 0 << 0 << 0.0;
    625879        baseModel->messageHandler()->printing(false) << 0.0;
    626         baseModel->messageHandler()->printing(true) << children_[numberThreads_].timeInThread_;
    627         baseModel->messageHandler()->printing(true) << children_[numberThreads_].numberTimesLocked_
    628         << children_[numberThreads_].timeLocked_ << children_[numberThreads_].timeWaitingToLock_
     880        baseModel->messageHandler()->printing(true) << children_[numberThreads_].timeInThread();
     881        baseModel->messageHandler()->printing(true) << children_[numberThreads_].numberTimesLocked()
     882        << children_[numberThreads_].timeLocked() << children_[numberThreads_].timeWaitingToLock()
    629883        << CoinMessageEol;
    630         //pthread_mutex_destroy (&mutex_main_);
    631         //pthread_cond_destroy (children_[numberThreads_].condition2_);
    632         //pthread_mutex_destroy (children_[numberThreads_].mutex2_);
    633884        // delete models (here in case some point to others)
    634885        for (i = 0; i < numberThreads_; i++) {
     
    652903        // see if any available
    653904        for (iThread = 0; iThread < numberThreads_; iThread++) {
    654             if (children_[iThread].returnCode_) {
     905            if (children_[iThread].returnCode()) {
    655906                finished = true;
    656907                break;
    657             } else if (children_[iThread].returnCode_ == 0) {
    658                 pthread_cond_signal(children_[iThread].condition2_); // unlock
     908            } else if (children_[iThread].returnCode() == 0) {
     909                children_[iThread].signal();
    659910            }
    660911        }
    661912        while (!finished) {
    662             pthread_mutex_lock(children_[numberThreads_].mutex2_);
    663             struct timespec absTime;
    664             my_gettime(&absTime);
    665             absTime.tv_nsec += 1000000; // millisecond
    666             if (absTime.tv_nsec >= 1000000000) {
    667                 absTime.tv_nsec -= 1000000000;
    668                 absTime.tv_sec++;
    669             }
    670             pthread_cond_timedwait(children_[numberThreads_].condition2_, children_[numberThreads_].mutex2_, &absTime);
    671             pthread_mutex_unlock(children_[numberThreads_].mutex2_);
     913            children_[numberThreads_].waitNano(1000000);
    672914            for (iThread = 0; iThread < numberThreads_; iThread++) {
    673                 if (children_[iThread].returnCode_ > 0) {
     915                if (children_[iThread].returnCode() > 0) {
    674916                    finished = true;
    675917                    break;
    676                 } else if (children_[iThread].returnCode_ == 0) {
    677                     pthread_cond_signal(children_[iThread].condition2_); // unlock
     918                } else if (children_[iThread].returnCode() == 0) {
     919                    children_[iThread].signal();
    678920                }
    679921            }
    680922        }
    681923        assert (iThread < numberThreads_);
    682         assert (children_[iThread].returnCode_);
     924        assert (children_[iThread].returnCode());
    683925        // Use dantzigState to signal which generator
    684         children_[iThread].dantzigState_ = whichGenerator;
     926        children_[iThread].setDantzigState(whichGenerator);
    685927        // and delNode for eachCuts
    686         children_[iThread].delNode_ = reinterpret_cast<CbcNode **> (eachCuts);
     928        children_[iThread].fakeDelNode(reinterpret_cast<CbcNode **> (eachCuts));
    687929        // allow to start
    688         children_[iThread].returnCode_ = 0;
    689         pthread_cond_signal(children_[iThread].condition2_); // unlock
     930        children_[iThread].setReturnCode( 0);
     931        children_[iThread].signal();
    690932    } else if (type == 1) {
    691933        // cuts - finish up
    692934        for (int iThread = 0; iThread < numberThreads_; iThread++) {
    693             if (children_[iThread].returnCode_ == 0) {
     935            if (children_[iThread].returnCode() == 0) {
    694936                bool finished = false;
    695                 pthread_cond_signal(children_[iThread].condition2_); // unlock
    696937                while (!finished) {
    697                     pthread_mutex_lock(children_[numberThreads_].mutex2_);
    698                     struct timespec absTime;
    699                     my_gettime(&absTime);
    700                     absTime.tv_nsec += 1000000; // millisecond
    701                     if (absTime.tv_nsec >= 1000000000) {
    702                         absTime.tv_nsec -= 1000000000;
    703                         absTime.tv_sec++;
    704                     }
    705                     pthread_cond_timedwait(children_[numberThreads_].condition2_, children_[numberThreads_].mutex2_, &absTime);
    706                     pthread_mutex_unlock(children_[numberThreads_].mutex2_);
    707                     if (children_[iThread].returnCode_ > 0) {
     938                    children_[numberThreads_].wait(0, 0);
     939                    if (children_[iThread].returnCode() > 0) {
    708940                        finished = true;
    709941                        break;
    710                     } else if (children_[iThread].returnCode_ == 0) {
    711                         pthread_cond_signal(children_[iThread].condition2_); // unlock
     942                        //#ifndef NEW_STYLE_PTHREAD
     943                        //} else if (children_[iThread].returnCode_ == 0) {
     944                        //pthread_cond_signal(&children_[iThread].threadStuff_.condition2_); // unlock
     945                        //#endif
    712946                    }
    713947                }
    714948            }
    715             assert (children_[iThread].returnCode_);
     949            assert (children_[iThread].returnCode());
    716950            // say available
    717             children_[iThread].returnCode_ = -1;
     951            children_[iThread].setReturnCode( -1);
    718952            //delete threadModel_[iThread]->solver();
    719953            //threadModel_[iThread]->setSolver(NULL);
     
    723957    }
    724958}
     959// Returns pointer to master thread
     960CbcThread *
     961CbcBaseModel::masterThread() const
     962{
     963    return children_ + numberThreads_;
     964}
     965
    725966// Split model and do work in deterministic parallel
    726967void
    727968CbcBaseModel::deterministicParallel()
    728969{
    729     CbcModel * baseModel = children_[0].baseModel_;
     970    CbcModel * baseModel = children_[0].baseModel();
    730971    for (int i = 0; i < numberThreads_; i++)
    731972        threadCount_[i]++;
     
    735976    int iThread;
    736977    for (iThread = 0; iThread < numberThreads_; iThread++)
    737         threadModel[iThread] = children_[iThread].thisModel_;
     978        threadModel[iThread] = children_[iThread].thisModel();
    738979
    739980    int nAffected = baseModel->splitModel(numberThreads_, threadModel, defaultParallelNodes_);
     
    741982    for (iThread = 0; iThread < numberThreads_; iThread++) {
    742983        // obviously tune
    743         children_[iThread].nDeleteNode_ = defaultParallelIterations_;
     984        children_[iThread].setNDeleteNode(defaultParallelIterations_);
    744985    }
    745986    // Save current state
     
    750991    }
    751992    for (iThread = 0; iThread < numberThreads_; iThread++) {
    752         children_[iThread].returnCode_ = 0;
    753         pthread_cond_signal(children_[iThread].condition2_); // unlock
     993        children_[iThread].setReturnCode( 0);
     994        children_[iThread].signal();
    754995    }
    755996    // wait
    756997    bool finished = false;
     998    double time = getTime();
    757999    while (!finished) {
    758         pthread_mutex_lock(children_[numberThreads_].mutex2_);
    759         struct timespec absTime;
    760         my_gettime(&absTime);
    761         double time = absTime.tv_sec + 1.0e-9 * absTime.tv_nsec;
    762         absTime.tv_nsec += 1000000; // millisecond
    763         if (absTime.tv_nsec >= 1000000000) {
    764             absTime.tv_nsec -= 1000000000;
    765             absTime.tv_sec++;
    766         }
    767         pthread_cond_timedwait(children_[numberThreads_].condition2_,
    768                                children_[numberThreads_].mutex2_, &absTime);
    769         my_gettime(&absTime);
    770         double time2 = absTime.tv_sec + 1.0e-9 * absTime.tv_nsec;
    771         children_[numberThreads_].timeInThread_ += time2 - time;
    772         pthread_mutex_unlock(children_[numberThreads_].mutex2_);
     1000        children_[numberThreads_].waitNano( 1000000); // millisecond
    7731001        finished = true;
    7741002        for (iThread = 0; iThread < numberThreads_; iThread++) {
    775             if (children_[iThread].returnCode_ <= 0) {
     1003            if (children_[iThread].returnCode() <= 0) {
    7761004                finished = false;
    7771005            }
    7781006        }
    7791007    }
     1008    for (iThread = 0; iThread < numberThreads_; iThread++)
     1009        children_[iThread].setReturnCode(-1);
     1010    children_[numberThreads_].incrementTimeInThread(getTime() - time);
    7801011    // Unmark marked
    7811012    for (int i = 0; i < nAffected; i++) {
     
    8211052    delete [] threadCount_;
    8221053#if 1
    823     delete [] threadId_;
    8241054    for (int i = 0; i < numberThreads_; i++)
    8251055        delete threadModel_[i];
    8261056    delete [] threadModel_;
    8271057    delete [] children_;
    828     delete [] mutex2_;
    829     delete [] condition2_;
    8301058#endif
    8311059    for (int i = 0; i < numberObjects_; i++)
     
    8381066{
    8391067    for (int i = 0; i < numberThreads_; i++) {
    840         children_[i].dantzigState_ = -1;
    841     }
    842 }
    843 // Default constructor
    844 CbcSimpleThread::CbcSimpleThread()
    845         :
    846         numberThreads_(0),
    847         argBundle_(NULL)
    848 {
    849 }
    850 // Constructor with model
    851 CbcSimpleThread::CbcSimpleThread (int numberThreads,
    852                                   void *(* function) (void *),
    853                                   int sizeOfData,
    854                                   void * data)
    855         :
    856         numberThreads_(numberThreads),
    857         argBundle_(data)
    858 {
    859     Coin_pthread_t * threadId = new Coin_pthread_t [numberThreads_];
    860     char * args = reinterpret_cast<char *>(argBundle_);
    861     for (int i = 0; i < numberThreads_; i++) {
    862         pthread_create(&(threadId[i].thr), NULL, function,
    863                        args + i*sizeOfData);
    864     }
    865     // now wait
    866     for (int i = 0; i < numberThreads_; i++) {
    867         pthread_join(threadId[i].thr, NULL);
    868     }
    869     delete [] threadId;
    870 }
    871 // Constructor with stuff
    872 CbcSimpleThread::CbcSimpleThread (int numberThreads,
    873                                   int type,
    874                                   int sizeOfData,
    875                                   void * data)
    876         :
    877         numberThreads_(numberThreads),
    878         argBundle_(data)
    879 {
    880     assert (type == 0); // heuristics
    881     Coin_pthread_t * threadId = new Coin_pthread_t [numberThreads_];
    882     char * args = reinterpret_cast<char *>(argBundle_);
    883     for (int i = 0; i < numberThreads_; i++) {
    884         pthread_create(&(threadId[i].thr), NULL, doHeurThread,
    885                        args + i*sizeOfData);
    886     }
    887     // now wait
    888     for (int i = 0; i < numberThreads_; i++) {
    889         pthread_join(threadId[i].thr, NULL);
    890     }
    891     delete [] threadId;
    892 }
    893 // Destructor
    894 CbcSimpleThread::~CbcSimpleThread()
    895 {
     1068        children_[i].setDantzigState(-1);
     1069    }
    8961070}
    8971071static void * doNodesThread(void * voidInfo)
    8981072{
    8991073    CbcThread * stuff = reinterpret_cast<CbcThread *> (voidInfo);
    900     pthread_mutex_t * mutex = stuff->mutex2_;
    901     pthread_cond_t * condition = stuff->condition2_;
    902     CbcModel * thisModel = stuff->thisModel_;
    903     CbcModel * baseModel = stuff->baseModel_;
     1074    CbcModel * thisModel = stuff->thisModel();
     1075    CbcModel * baseModel = stuff->baseModel();
    9041076    while (true) {
    905         pthread_mutex_lock (mutex);
    906         while (stuff->returnCode_) {
    907             struct timespec absTime2;
    908             my_gettime(&absTime2);
    909             double time2 = absTime2.tv_sec + 1.0e-9 * absTime2.tv_nsec;
    910             // timed wait as seems to hang on max nodes at times
    911             absTime2.tv_sec += 10;
    912             pthread_cond_timedwait(condition, mutex, &absTime2);
    913             my_gettime(&stuff->absTime_);
    914             double time = stuff->absTime_.tv_sec + 1.0e-9 * stuff->absTime_.tv_nsec;
    915             stuff->timeWaitingToStart_ += time - time2;;
    916             stuff->numberTimesWaitingToStart_++;
    917         }
     1077        stuff->waitThread();
    9181078        //printf("start node %x\n",stuff->node);
    9191079        int mode = thisModel->getNumberThreads();
     
    9211081            // normal
    9221082            double time2 = CoinCpuTime();
    923             assert (stuff->returnCode_ == 0);
     1083            assert (stuff->returnCode() == 0);
    9241084            if (thisModel->parallelMode() >= 0) {
    925                 assert (stuff->node_->nodeInfo());
    926                 thisModel->doOneNode(baseModel, stuff->node_, stuff->createdNode_);
    927                 stuff->returnCode_ = 1;
     1085                CbcNode * node = stuff->node();
     1086                assert (node->nodeInfo());
     1087                CbcNode * createdNode = stuff->createdNode();
     1088                thisModel->doOneNode(baseModel, node, createdNode);
     1089                stuff->setNode(node);
     1090                stuff->setCreatedNode(createdNode);
     1091                stuff->setReturnCode( 1);
    9281092            } else {
    929                 assert (!stuff->node_);
    930                 assert (!stuff->createdNode_);
    931                 int numberIterations = stuff->nDeleteNode_;
     1093                assert (!stuff->node());
     1094                assert (!stuff->createdNode());
     1095                int numberIterations = stuff->nDeleteNode();
    9321096                int nDeleteNode = 0;
    933                 int maxDeleteNode = stuff->maxDeleteNode_;
    934                 CbcNode ** delNode = stuff->delNode_;
     1097                int maxDeleteNode = stuff->maxDeleteNode();
     1098                CbcNode ** delNode = stuff->delNode();
    9351099                int returnCode = 1;
    9361100                // this should be updated by heuristics strong branching etc etc
     
    10031167                        if (nDeleteNode == maxDeleteNode) {
    10041168                            maxDeleteNode = (3 * maxDeleteNode) / 2 + 10;
    1005                             stuff->maxDeleteNode_ = maxDeleteNode;
    1006                             stuff->delNode_ = new CbcNode * [maxDeleteNode];
     1169                            stuff->setMaxDeleteNode(maxDeleteNode);
     1170                            stuff->setDelNode(new CbcNode * [maxDeleteNode]);
    10071171                            for (int i = 0; i < nDeleteNode; i++)
    1008                                 stuff->delNode_[i] = delNode[i];
     1172                                stuff->delNode()[i] = delNode[i];
    10091173                            delete [] delNode;
    1010                             delNode = stuff->delNode_;
     1174                            delNode = stuff->delNode();
    10111175                        }
    10121176                        delNode[nDeleteNode++] = node;
     
    10201184                delete [] used;
    10211185                thisModel->setSolutionCount(thisModel->getSolutionCount() - numberSolutions);
    1022                 stuff->nodesThisTime_ = thisModel->getNodeCount() - nodesThisTime;
    1023                 stuff->iterationsThisTime_ = thisModel->getIterationCount() - iterationsThisTime;
    1024                 stuff->nDeleteNode_ = nDeleteNode;
    1025                 stuff->returnCode_ = returnCode;
     1186                stuff->setNodesThisTime(thisModel->getNodeCount() - nodesThisTime);
     1187                stuff->setIterationsThisTime(thisModel->getIterationCount() - iterationsThisTime);
     1188                stuff->setNDeleteNode(nDeleteNode);
     1189                stuff->setReturnCode( returnCode);
    10261190                thisModel->setNumberThreads(mode);
    10271191            }
    10281192            //printf("end node %x\n",stuff->node);
    1029             CbcThread * stuffMain = reinterpret_cast<CbcThread *> (baseModel->masterThread());
    1030             //pthread_mutex_t * condition_mutex = stuffMain->mutex2;
    1031             pthread_cond_t * condition_main = stuffMain->condition2_;
    1032             pthread_cond_signal(condition_main); // unlock
    1033             pthread_mutex_unlock(mutex);
    1034             stuff->timeInThread_ += CoinCpuTime() - time2;
     1193            stuff->unlockFromThread();
     1194            stuff->incrementTimeInThread(CoinCpuTime() - time2);
    10351195        } else {
    10361196            // exit
     
    10381198        }
    10391199    }
    1040     pthread_mutex_unlock(mutex);
    1041     pthread_exit(NULL);
     1200    //printf("THREAD exiting\n");
     1201    stuff->exitThread();
    10421202    return NULL;
    10431203}
     
    10541214        stuff->model->heuristic(0)->solution(stuff->solutionValue,
    10551215                                             stuff->solution);
    1056     pthread_exit(NULL);
    10571216    return NULL;
    10581217}
     
    10601219{
    10611220    CbcThread * stuff = reinterpret_cast<CbcThread *> (voidInfo);
    1062     pthread_mutex_t * mutex = stuff->mutex2_;
    1063     pthread_cond_t * condition = stuff->condition2_;
    1064     CbcModel * thisModel =  stuff->thisModel_;
     1221    CbcModel * thisModel =  stuff->thisModel();
    10651222    while (true) {
    1066         pthread_mutex_lock(mutex);
    1067         while (stuff->returnCode_) {
    1068             pthread_cond_wait(condition, mutex);
    1069         }
     1223        stuff->waitThread();
    10701224        //printf("start node %x\n",stuff->node);
    10711225        int mode = thisModel->getNumberThreads();
    10721226        if (mode) {
    10731227            // normal
    1074             assert (stuff->returnCode_ == 0);
     1228            assert (stuff->returnCode() == 0);
    10751229            int fullScan = thisModel->getNodeCount() == 0 ? 1 : 0; //? was >0
    1076             CbcCutGenerator * generator = thisModel->cutGenerator(stuff->dantzigState_);
     1230            CbcCutGenerator * generator = thisModel->cutGenerator(stuff->dantzigState());
    10771231            generator->refreshModel(thisModel);
    1078             OsiCuts * cuts = reinterpret_cast<OsiCuts *> (stuff->delNode_);
     1232            OsiCuts * cuts = reinterpret_cast<OsiCuts *> (stuff->delNode());
    10791233            OsiSolverInterface * thisSolver = thisModel->solver();
    10801234            generator->generateCuts(*cuts, fullScan, thisSolver, NULL);
    1081             stuff->returnCode_ = 1;
    1082             //printf("end node %x\n",stuff->node);
    1083             CbcThread * stuffMain = stuff->master_;
    1084             //pthread_mutex_t * condition_mutex = stuffMain->mutex2;
    1085             pthread_cond_t * condition_main = stuffMain->condition2_;
    1086             pthread_cond_signal(condition_main); // unlock
    1087             pthread_mutex_unlock(mutex);
     1235            stuff->setReturnCode( 1);
     1236            stuff->unlockFromThread();
    10881237        } else {
    10891238            // exit
     
    10911240        }
    10921241    }
    1093     pthread_mutex_unlock(mutex);
    1094     pthread_exit(NULL);
     1242    stuff->exitThread();
    10951243    return NULL;
    10961244}
     
    12411389        assert (stuff);
    12421390        //if (stuff)
    1243         stuff->createdNode_ = NULL;
     1391        stuff->setCreatedNode(NULL);
    12441392        // ?? searchStrategy_;
    12451393        searchStrategy_ = baseModel->searchStrategy_;
    1246         stuff->saveStuff_[0] = searchStrategy_;
     1394        stuff->saveStuff()[0] = searchStrategy_;
    12471395        stateOfSearch_ = baseModel->stateOfSearch_;
    1248         stuff->saveStuff_[1] = stateOfSearch_;
     1396        stuff->saveStuff()[1] = stateOfSearch_;
    12491397        for (int iObject = 0 ; iObject < numberObjects_ ; iObject++) {
    12501398            CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
     
    12621410        assert (stuff);
    12631411        //stateOfSearch_
    1264         if (stuff->saveStuff_[0] != searchStrategy_) {
     1412        if (stuff->saveStuff()[0] != searchStrategy_) {
    12651413#ifdef COIN_DEVELOP
    12661414            printf("changing searchStrategy from %d to %d\n",
     
    12691417            baseModel->searchStrategy_ = searchStrategy_;
    12701418        }
    1271         if (stuff->saveStuff_[1] != stateOfSearch_) {
     1419        if (stuff->saveStuff()[1] != stateOfSearch_) {
    12721420#ifdef COIN_DEVELOP
    12731421            printf("changing stateOfSearch from %d to %d\n",
     
    12921440            numberIterations_ - numberFixedAtRoot_;
    12931441        baseModel->numberSolves_ += numberSolves_;
    1294         if (stuff->node_)
    1295             baseModel->tree_->push(stuff->node_);
    1296         if (stuff->createdNode_)
    1297             baseModel->tree_->push(stuff->createdNode_);
     1442        if (stuff->node())
     1443            baseModel->tree_->push(stuff->node());
     1444        if (stuff->createdNode())
     1445            baseModel->tree_->push(stuff->createdNode());
    12981446        unlockThread();
    12991447    } else if (mode == 2) {
     
    14121560        assert (stuff);
    14131561        //if (stuff)
    1414         stuff->createdNode_ = NULL;
     1562        stuff->setCreatedNode(NULL);
    14151563        // ?? searchStrategy_;
    14161564        searchStrategy_ = baseModel->searchStrategy_;
    1417         stuff->saveStuff_[0] = searchStrategy_;
     1565        stuff->saveStuff()[0] = searchStrategy_;
    14181566        stateOfSearch_ = baseModel->stateOfSearch_;
    1419         stuff->saveStuff_[1] = stateOfSearch_;
     1567        stuff->saveStuff()[1] = stateOfSearch_;
    14201568        OsiObject ** baseObject = baseModel->object_;
    14211569        for (int iObject = 0 ; iObject < numberObjects_ ; iObject++) {
     
    14461594            }
    14471595            //stateOfSearch_
    1448             if (stuff->saveStuff_[0] != searchStrategy_) {
     1596            if (stuff->saveStuff()[0] != searchStrategy_) {
    14491597#ifdef COIN_DEVELOP
    14501598                printf("changing searchStrategy from %d to %d\n",
     
    14531601                baseModel->searchStrategy_ = searchStrategy_;
    14541602            }
    1455             if (stuff->saveStuff_[1] != stateOfSearch_) {
     1603            if (stuff->saveStuff()[1] != stateOfSearch_) {
    14561604#ifdef COIN_DEVELOP
    14571605                printf("changing stateOfSearch from %d to %d\n",
     
    14631611            if (eventHappened_)
    14641612                baseModel->eventHappened_ = true;
    1465             baseModel->numberNodes_ += stuff->nodesThisTime_;
    1466             baseModel->numberIterations_ += stuff->iterationsThisTime_;
     1613            baseModel->numberNodes_ += stuff->nodesThisTime();
     1614            baseModel->numberIterations_ += stuff->iterationsThisTime();
    14671615            double cutoff = baseModel->getCutoff();
    14681616            while (!tree_->empty()) {
     
    14881636                }
    14891637            }
    1490             for (i = 0; i < stuff->nDeleteNode_; i++) {
     1638            for (i = 0; i < stuff->nDeleteNode(); i++) {
    14911639                //printf("CbcNode %x stuff delete\n",stuff->delNode[i]);
    1492                 delete stuff->delNode_[i];
     1640                delete stuff->delNode()[i];
    14931641            }
    14941642        }
     
    15521700        int numberRowCutsBefore = theseCuts.sizeRowCuts() ;
    15531701        int numberRowCuts = eachCuts[i].sizeRowCuts();
     1702        // insert good cuts
     1703        if (numberRowCuts) {
     1704            int n = numberRowCuts;
     1705            numberRowCuts = 0;
     1706            for (j = 0; j < n; j++) {
     1707                const OsiRowCut * thisCut = eachCuts[i].rowCutPtr(j) ;
     1708                if (thisCut->lb() <= 1.0e10 && thisCut->ub() >= -1.0e10) {
     1709                    theseCuts.insert(eachCuts[i].rowCut(j));
     1710                    numberRowCuts++;
     1711                }
     1712            }
     1713            if (generator_[i]->mustCallAgain() && status >= 0)
     1714                status = 1; // say must go round
     1715        }
    15541716        int numberRowCutsAfter = numberRowCutsBefore
    15551717                                 + numberRowCuts;
    15561718        if (numberRowCuts) {
    1557             for (j = 0; j < numberRowCuts; j++) {
    1558                 const OsiRowCut * thisCut = eachCuts[i].rowCutPtr(j) ;
    1559                 if (thisCut->lb() <= 1.0e10 && thisCut->ub() >= -1.0e10)
    1560                     theseCuts.insert(eachCuts[i].rowCut(j));
    1561             }
    1562             if (generator_[i]->mustCallAgain() && status >= 0)
    1563                 status = 1; // say must go round
    15641719            // Check last cut to see if infeasible
    15651720            const OsiRowCut * thisCut = theseCuts.rowCutPtr(numberRowCutsAfter - 1) ;
     
    16981853{
    16991854    if (masterThread_) {
    1700         return (masterThread_->locked_);
     1855        return (masterThread_->locked());
    17011856    } else {
    17021857        return true;
  • branches/sandbox/Cbc/src/CbcThread.hpp

    r1409 r1412  
    1010class OsiCuts;
    1111#ifdef CBC_THREAD
    12 // Threads
     12class CbcThread;
     13// Use pthreads
     14#define CBC_PTHREAD
     15#ifdef CBC_PTHREAD
    1316#include <pthread.h>
    1417typedef struct {
     
    1619    long                status;
    1720} Coin_pthread_t;
    18 
    19 #ifdef HAVE_CLOCK_GETTIME
    20 inline int my_gettime(struct timespec* tp)
    21 {
    22     return clock_gettime(CLOCK_REALTIME, tp);
    23 }
    24 #else
    25 #ifndef _MSC_VER
    26 inline int my_gettime(struct timespec* tp)
    27 {
    28     struct timeval tv;
    29     int ret = gettimeofday(&tv, NULL);
    30     tp->tv_sec = tv.tv_sec;
    31     tp->tv_nsec = tv.tv_usec * 1000;
    32     return ret;
    33 }
    34 #else
    35 inline int my_gettime(struct timespec* tp)
    36 {
    37     double t = CoinGetTimeOfDay();
    38     tp->tv_sec = (int)floor(t);
    39     tp->tv_nsec = (int)((tp->tv_sec - floor(t)) / 1000000.0);
    40     return 0;
    41 }
    4221#endif
    43 #endif
    44 /** A class to encapsulate phread stuff */
    45 
    46 
    47 class CbcPthread {
     22//#define THREAD_DEBUG 1
     23/** A class to encapsulate specific thread stuff
     24    To use another api with same style - you just need to implement
     25    these methods.
     26
     27    At present just pthreads
     28 */
     29
     30
     31class CbcSpecificThread {
    4832public:
    4933    // Default Constructor
    50     CbcPthread ();
    51 
    52     // Constructor with base model
    53     CbcPthread (CbcModel & model, int deterministic, CbcModel * baseModel);
    54 
    55     // Copy constructor
    56     CbcPthread ( const CbcPthread &);
    57 
    58     virtual ~CbcPthread();
    59 
    60     /// Assignment operator
    61     CbcPthread & operator=(const CbcPthread& rhs);
     34    CbcSpecificThread ();
     35
     36    // Useful Constructor
     37    CbcSpecificThread (CbcSpecificThread * master, pthread_mutex_t * masterMutex);
     38
     39    virtual ~CbcSpecificThread();
     40
     41    // Useful stuff
     42    void setUsefulStuff (CbcSpecificThread * master,
     43                         void *& masterMutex);
    6244    /**
    6345       Locks a thread if parallel so that stuff like cut pool
     
    6951    */
    7052    void unlockThread();
    71 
    72     /// Returns true if locked
    73     inline bool isLocked() const {
    74         return locked_;
    75     }
    76 
    77 public:
    78     CbcPthread * basePointer_; // for getting main mutex and threadid of base
    79     pthread_mutex_t mutex_; // for waking up threads
    80     pthread_cond_t condition_; // for waking up thread
     53    ///  Locks a thread for testing whether to start etc
     54    void lockThread2(bool doAnyway = false);
     55    ///  Unlocks a thread for testing whether to start etc
     56    void unlockThread2(bool doAnyway = false);
     57    /// Signal
     58    void signal();
     59    /// Timed wait in nanoseconds - if negative then seconds
     60    void timedWait(int time);
     61    /// Actually starts a thread
     62    void startThread(void * (*routine ) (void *), CbcThread * thread);
     63    /// Exits thread (called from master) - return code should be zero
     64    int exit();
     65    /// Exits thread
     66    void exitThread();
     67    /// Get status
     68    int status() const;
     69    /// Set status
     70    void setStatus(int value);
     71    //}
     72
     73
     74public: // private:
     75    CbcSpecificThread * basePointer_; // for getting main mutex and threadid of base
     76#ifdef CBC_PTHREAD
     77    pthread_mutex_t *masterMutex_; // for synchronizing
     78    pthread_mutex_t mutex2_; // for waking up threads
     79    pthread_cond_t condition2_; // for waking up thread
    8180    Coin_pthread_t threadId_;
    82     bool locked_;
     81#endif
     82    bool locked_; // For mutex2
    8383};
    84 
    8584/** A class to encapsulate thread stuff */
    8685
     
    9594    CbcThread ();
    9695
    97     // Constructor with base model
    98     CbcThread (CbcModel & model, int deterministic, CbcModel * baseModel);
    99 
    100     // Copy constructor
    101     CbcThread ( const CbcThread &);
    102 
    10396    virtual ~CbcThread();
    10497
    105     /// Assignment operator
    106     CbcThread & operator=(const CbcThread& rhs);
     98    /// Fills in useful stuff
     99    void setUsefulStuff (CbcModel * model, int deterministic,
     100                         CbcModel * baseModel,
     101                         CbcThread * master,
     102                         void *& masterMutex);
    107103    /**
    108104       Locks a thread if parallel so that stuff like cut pool
     
    119115        return locked_;
    120116    }
    121 
    122 public:
     117    /** Wait for child to have return code NOT == to currentCode
     118        type - 0 timed wait
     119               1 wait
     120           returns true if return code changed */
     121    bool wait(int type, int currentCode);
     122    /// Just wait for so many nanoseconds
     123    void waitNano(int time);
     124    /// Signal child to carry on
     125    void signal();
     126    /// Lock from master with mutex2 and signal before lock
     127    void lockFromMaster();
     128    /// Unlock from master with mutex2 and signal after unlock
     129    void unlockFromMaster();
     130    /// Lock from thread with mutex2 and signal before lock
     131    void lockFromThread();
     132    /// Unlock from thread with mutex2 and signal after unlock
     133    void unlockFromThread();
     134    /// Exits thread (called from master) - return code should be zero
     135    int exit();
     136    /// Exits thread
     137    void exitThread();
     138    /// Waits until returnCode_ goes to zero
     139    void waitThread();
     140    /// Get status
     141    inline int status() const {
     142        return threadStuff_.status();
     143    }
     144    /// Set status
     145    inline void setStatus(int value) {
     146        threadStuff_.setStatus( value);
     147    }
     148    /// Get return code
     149    inline int returnCode() const {
     150        return returnCode_;
     151    }
     152    /// Set return code
     153    inline void setReturnCode(int value) {
     154        returnCode_ = value;
     155    }
     156    /// Get base model
     157    inline CbcModel * baseModel() const {
     158        return baseModel_;
     159    }
     160    /// Get this model
     161    inline CbcModel * thisModel() const {
     162        return thisModel_;
     163    }
     164    /// Get node
     165    inline CbcNode * node() const {
     166        return node_;
     167    }
     168    /// Set node
     169    inline void setNode(CbcNode * node) {
     170        node_ = node;
     171    }
     172    /// Get created node
     173    inline CbcNode * createdNode() const {
     174        return createdNode_;
     175    }
     176    /// Set created node
     177    inline void setCreatedNode(CbcNode * node) {
     178        createdNode_ = node;
     179    }
     180    /// Get dantzig state
     181    inline int dantzigState() const {
     182        return dantzigState_;
     183    }
     184    /// Set dantzig state
     185    inline void setDantzigState(int value) {
     186        dantzigState_ = value;
     187    }
     188    /// Get time in thread
     189    inline double timeInThread() const {
     190        return timeInThread_;
     191    }
     192    /// Increment time in thread
     193    inline void incrementTimeInThread(double value) {
     194        timeInThread_ += value;
     195    }
     196    /// Get time waiting to start
     197    inline double timeWaitingToStart() const {
     198        return timeWaitingToStart_;
     199    }
     200    /// Increment time waiting to start
     201    inline void incrementTimeWaitingToStart(double value) {
     202        timeWaitingToStart_ += value;
     203    }
     204    /// Get time locked
     205    inline double timeLocked() const {
     206        return timeLocked_;
     207    }
     208    /// Increment time locked
     209    inline void incrementTimeLocked(double value) {
     210        timeLocked_ += value;
     211    }
     212    /// Get time waiting to lock
     213    inline double timeWaitingToLock() const {
     214        return timeWaitingToLock_;
     215    }
     216    /// Increment time waiting to lock
     217    inline void incrementTimeWaitingToLock(double value) {
     218        timeWaitingToLock_ += value;
     219    }
     220    /// Get if deterministic
     221    inline int deterministic() const {
     222        return deterministic_;
     223    }
     224    /// Get maxDeleteNode
     225    inline int maxDeleteNode() const {
     226        return maxDeleteNode_;
     227    }
     228    /// Set maxDeleteNode
     229    inline void setMaxDeleteNode(int value) {
     230        maxDeleteNode_ = value;
     231    }
     232    /// Get nDeleteNode (may be fake i.e. defaultParallelIterations_)
     233    inline int nDeleteNode() const {
     234        return nDeleteNode_;
     235    }
     236    /// Set nDeleteNode (may be fake i.e. defaultParallelIterations_)
     237    inline void setNDeleteNode(int value) {
     238        nDeleteNode_ = value;
     239    }
     240    /// Clear delNode
     241    inline void clearDelNode() {
     242        delete delNode_;
     243        delNode_ = NULL;
     244    }
     245    /// Set fake delNode to pass across OsiCuts
     246    inline void fakeDelNode(CbcNode ** delNode) {
     247        delNode_ = delNode;
     248    }
     249    /// Get delNode
     250    inline CbcNode ** delNode() const {
     251        return delNode_;
     252    }
     253    /// Set delNode
     254    inline void setDelNode(CbcNode ** delNode) {
     255        delNode_ = delNode;
     256    }
     257    /// Get number times locked
     258    inline int numberTimesLocked() const {
     259        return numberTimesLocked_;
     260    }
     261    /// Get number times unlocked
     262    inline int numberTimesUnlocked() const {
     263        return numberTimesUnlocked_;
     264    }
     265    /// Get number of nodes this time
     266    inline int nodesThisTime() const {
     267        return nodesThisTime_;
     268    }
     269    /// Set number of nodes this time
     270    inline void setNodesThisTime(int value) {
     271        nodesThisTime_ = value;
     272    }
     273    /// Get number of iterations this time
     274    inline int iterationsThisTime() const {
     275        return iterationsThisTime_;
     276    }
     277    /// Set number of iterations this time
     278    inline void setIterationsThisTime(int value) {
     279        iterationsThisTime_ = value;
     280    }
     281    /// Get save stuff array
     282    inline int * saveStuff() {
     283        return saveStuff_;
     284    }
     285    /// Say if locked
     286    inline bool locked() const {
     287        return locked_;
     288    }
     289
     290public: // private:
     291    CbcSpecificThread threadStuff_;
    123292    CbcModel * baseModel_;
    124293    CbcModel * thisModel_;
    125294    CbcNode * node_; // filled in every time
    126295    CbcNode * createdNode_; // filled in every time on return
    127     Coin_pthread_t threadIdOfBase_;
    128     pthread_mutex_t * mutex_; // for locking data
    129     pthread_mutex_t * mutex2_; // for waking up threads
    130296    CbcThread * master_; // points back to master thread
    131     pthread_cond_t * condition2_; // for waking up thread
    132297    int returnCode_; // -1 available, 0 busy, 1 finished , 2??
    133298    double timeLocked_;
     
    135300    double timeWaitingToStart_;
    136301    double timeInThread_;
     302    double timeWhenLocked_; // time when thread got lock (in seconds)
    137303    int numberTimesLocked_;
    138304    int numberTimesUnlocked_;
     
    140306    int saveStuff_[2];
    141307    int dantzigState_; // 0 unset, -1 waiting to be set, 1 set
    142     struct timespec absTime_;
    143308    bool locked_;
    144309    int nDeleteNode_;
     
    148313    int iterationsThisTime_;
    149314    int deterministic_;
     315#ifdef THREAD_DEBUG
     316public:
     317    int threadNumber_;
     318    int lockCount_;
     319#endif
    150320};
    151321/** Base model */
     
    161331              0 opportunistic
    162332              1 deterministic */
    163     // CbcBaseModel (CbcModel & model, int numberThreads,
    164     //  void *(* function) (void *),
    165     //  int type);
    166333    /** Constructor with model
    167334        type -1 cuts
     
    170337    CbcBaseModel (CbcModel & model, int type);
    171338
    172     // Copy constructor
    173     CbcBaseModel ( const CbcBaseModel &);
    174 
    175339    virtual ~CbcBaseModel();
    176340
    177     /// Assignment operator
    178     CbcBaseModel & operator=(const CbcBaseModel& rhs);
    179 
    180     /// Stop all threads
    181     void stopThreads();
     341    /** Stop all threads
     342        -1 just check all in good state
     343        0 actually stop
     344    */
     345    void stopThreads(int type);
    182346
    183347    /** Wait for threads in tree
     
    213377    /// Returns true if locked
    214378    inline bool isLocked() const {
    215         return children_[numberThreads_].locked_;
     379        return children_[numberThreads_].locked();
    216380    }
    217381
    218382    /// Returns pointer to master thread
    219     inline CbcThread * masterThread() const {
    220         return children_ + numberThreads_;
    221     }
     383    CbcThread * masterThread() const;
    222384
    223385    /// Returns pointer to a thread model
     
    239401              1 deterministic */
    240402    int type_;
    241     pthread_mutex_t mutex_main_;
    242     pthread_cond_t condition_main_;
    243     pthread_mutex_t condition_mutex_;
    244     Coin_pthread_t * threadId_;
    245403    int * threadCount_;
    246404    CbcModel ** threadModel_;
    247     pthread_mutex_t * mutex2_;
    248     pthread_cond_t * condition2_;
    249405    int numberObjects_;
    250406    OsiObject ** saveObjects_;
     
    253409    int defaultParallelNodes_;
    254410};
    255 
    256 /** Simple general method - just passed n bundles of data and a function */
    257 
    258 
    259 class CbcSimpleThread {
    260 public:
    261     // Default Constructor
    262     CbcSimpleThread ();
    263 
    264     // Constructor with stuff
    265     CbcSimpleThread (int numberThreads,
    266                      void *(* function) (void *),
    267                      int sizeOfData,
    268                      void * data);
    269     // Constructor with stuff (type 0 -> doHeurThread)
    270     CbcSimpleThread (int numberThreads,
    271                      int type,
    272                      int sizeOfData,
    273                      void * data);
    274 
    275     virtual ~CbcSimpleThread();
    276 
    277 protected:
    278 
    279     /// Number of children
    280     int numberThreads_;
    281     /// data
    282     void * argBundle_;
    283 };
    284411#else
    285412// Dummy threads
Note: See TracChangeset for help on using the changeset viewer.