source: trunk/Cbc/src/CbcThread.cpp @ 2097

Last change on this file since 2097 was 2097, checked in by forrest, 4 years ago

try and improve memory leaks (and clean up Clp pthread build problem)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 70.4 KB
Line 
1/* $Id: CbcThread.cpp 2097 2014-11-21 10:57:22Z forrest $ */
2// Copyright (C) 2002, International Business Machines
3// Corporation and others.  All Rights Reserved.
4// This code is licensed under the terms of the Eclipse Public License (EPL).
5
6#if defined(_MSC_VER)
7// Turn off compiler warning about long names
8#  pragma warning(disable:4786)
9#endif
10
11#include "CbcConfig.h"
12
13//#define THREAD_DEBUG
14#include <string>
15#include <cassert>
16#include <cmath>
17#include <cfloat>
18
19#include "CbcEventHandler.hpp"
20
21#include "OsiSolverInterface.hpp"
22#include "OsiRowCutDebugger.hpp"
23#include "CbcThread.hpp"
24#include "CbcTree.hpp"
25#include "CbcHeuristic.hpp"
26#include "CbcCutGenerator.hpp"
27#include "CbcModel.hpp"
28#include "CbcFathom.hpp"
29#include "CbcSimpleIntegerDynamicPseudoCost.hpp"
30#include "ClpDualRowDantzig.hpp"
31#include "OsiAuxInfo.hpp"
32
33#include "CoinTime.hpp"
34#ifdef CBC_THREAD
35/// Thread functions
36static void * doNodesThread(void * voidInfo);
37static void * doCutsThread(void * voidInfo);
38static void * doHeurThread(void * voidInfo);
39// Default Constructor
40CbcSpecificThread::CbcSpecificThread ()
41        : basePointer_(NULL),
42        masterMutex_(NULL),
43        locked_(false)
44{
45#ifdef CBC_PTHREAD
46    pthread_mutex_init(&mutex2_, NULL);
47    pthread_cond_init(&condition2_, NULL);
48    threadId_.status = 0;
49#else
50#endif
51}
52// Useful Constructor
53CbcSpecificThread::CbcSpecificThread (CbcSpecificThread * master, pthread_mutex_t * masterMutex)
54        : basePointer_(master),
55        masterMutex_(masterMutex),
56        locked_(false)
57
58{
59#ifdef CBC_PTHREAD
60    pthread_mutex_init(&mutex2_, NULL);
61    pthread_cond_init(&condition2_, NULL);
62    threadId_.status = 0;
63#else
64#endif
65
66}
67// Useful stuff
68void
69CbcSpecificThread::setUsefulStuff (CbcSpecificThread * master, void *& masterMutex)
70
71{
72#ifdef CBC_PTHREAD
73    basePointer_ = master;
74    if (masterMutex) {
75        masterMutex_ = reinterpret_cast<pthread_mutex_t *>(masterMutex);
76    } else {
77        // create master mutex
78        masterMutex_ = new pthread_mutex_t;
79        pthread_mutex_init(masterMutex_, NULL);
80        masterMutex = reinterpret_cast<void *>(masterMutex_);
81    }
82#else
83#endif
84}
85
86CbcSpecificThread::~CbcSpecificThread()
87{
88#ifdef CBC_PTHREAD
89    pthread_mutex_destroy (&mutex2_);
90    if (basePointer_ == this) {
91        pthread_mutex_destroy (masterMutex_);
92        delete masterMutex_;
93    }
94#else
95#endif
96}
97/*
98  Locks a thread if parallel so that stuff like cut pool
99  can be updated and/or used.
100*/
101void
102CbcSpecificThread::lockThread()
103{
104#ifdef CBC_PTHREAD
105    // Use master mutex
106    assert (basePointer_->masterMutex_ == masterMutex_);
107    pthread_mutex_lock (masterMutex_);
108#else
109#endif
110}
111/*
112  Unlocks a thread if parallel to say cut pool stuff not needed
113*/
114void
115CbcSpecificThread::unlockThread()
116{
117#ifdef CBC_PTHREAD
118    // Use master mutex
119    pthread_mutex_unlock (masterMutex_);
120#else
121#endif
122}
123//  Locks a thread for testing whether to start etc
124void
125CbcSpecificThread::lockThread2(bool doAnyway)
126{
127    if (!locked_ || doAnyway) {
128#ifdef CBC_PTHREAD
129        pthread_mutex_lock (&mutex2_);
130#else
131#endif
132        locked_ = true;
133    }
134}
135//  Unlocks a thread for testing whether to start etc
136void
137CbcSpecificThread::unlockThread2(bool doAnyway)
138{
139    if (locked_ || doAnyway) {
140#ifdef CBC_PTHREAD
141        pthread_mutex_unlock (&mutex2_);
142#else
143#endif
144        locked_ = false;
145    }
146}
147#ifdef HAVE_CLOCK_GETTIME
148inline int my_gettime(struct timespec* tp)
149{
150    return clock_gettime(CLOCK_REALTIME, tp);
151}
152#else
153#ifndef _MSC_VER
154inline int my_gettime(struct timespec* tp)
155{
156    struct timeval tv;
157    int ret = gettimeofday(&tv, NULL);
158    tp->tv_sec = tv.tv_sec;
159    tp->tv_nsec = tv.tv_usec * 1000;
160    return ret;
161}
162#else
163inline int my_gettime(struct timespec* tp)
164{
165    double t = CoinGetTimeOfDay();
166    tp->tv_sec = (int)floor(t);
167    tp->tv_nsec = (int)((tp->tv_sec - floor(t)) / 1000000.0);
168    return 0;
169}
170#endif
171#endif
172// Get time
173static double getTime()
174{
175    struct timespec absTime2;
176    my_gettime(&absTime2);
177    double time2 = absTime2.tv_sec + 1.0e-9 * 
178      static_cast<double>(absTime2.tv_nsec);
179    return time2;
180}
181// Timed wait in nanoseconds - if negative then seconds
182void
183CbcSpecificThread::timedWait(int time)
184{
185
186#ifdef CBC_PTHREAD
187    struct timespec absTime;
188    my_gettime(&absTime);
189    if (time > 0) {
190        absTime.tv_nsec += time;
191        if (absTime.tv_nsec >= 1000000000) {
192            absTime.tv_nsec -= 1000000000;
193            absTime.tv_sec++;
194        }
195    } else {
196        absTime.tv_sec -= time;
197    }
198    pthread_cond_timedwait(&condition2_, &mutex2_, &absTime);
199#else
200#endif
201}
202// Signal
203void
204CbcSpecificThread::signal()
205{
206#ifdef CBC_PTHREAD
207    pthread_cond_signal(&condition2_);
208#else
209#endif
210}
211// Actually starts a thread
212void
213CbcSpecificThread::startThread(void * (*routine ) (void *), CbcThread * thread)
214{
215#ifdef CBC_PTHREAD
216    pthread_create(&(threadId_.thr), NULL, routine, thread);
217    threadId_.status = 1;
218#else
219#endif
220}
221// Exits thread (from master)
222int
223CbcSpecificThread::exit()
224{
225#ifdef CBC_PTHREAD
226    pthread_cond_signal(&condition2_); // unlock
227    return pthread_join(threadId_.thr, NULL);
228#else
229#endif
230}
231// Exits thread
232void
233CbcSpecificThread::exitThread()
234{
235#ifdef CBC_PTHREAD
236    pthread_mutex_unlock(&mutex2_);
237    pthread_exit(NULL);
238#else
239#endif
240
241}
242// Get status
243int
244CbcSpecificThread::status() const
245{
246#ifdef CBC_PTHREAD
247    return static_cast<int>(threadId_.status);
248#else
249#endif
250}
251// Set status
252void
253CbcSpecificThread::setStatus(int value)
254{
255#ifdef CBC_PTHREAD
256    threadId_.status = value;
257#else
258#endif
259}
260// Parallel heuristics
261void
262parallelHeuristics (int numberThreads,
263                    int sizeOfData,
264                    void * argBundle)
265{
266    Coin_pthread_t * threadId = new Coin_pthread_t [numberThreads];
267    char * args = reinterpret_cast<char *>(argBundle);
268    for (int i = 0; i < numberThreads; i++) {
269        pthread_create(&(threadId[i].thr), NULL, doHeurThread,
270                       args + i*sizeOfData);
271    }
272    // now wait
273    for (int i = 0; i < numberThreads; i++) {
274        pthread_join(threadId[i].thr, NULL);
275    }
276    delete [] threadId;
277}
278// End of specific thread stuff
279
280/// Default constructor
281CbcThread::CbcThread()
282        :
283        baseModel_(NULL),
284        thisModel_(NULL),
285        node_(NULL), // filled in every time
286        createdNode_(NULL), // filled in every time on return
287        returnCode_(-1), // -1 available, 0 busy, 1 finished , 2??
288        timeLocked_(0.0),
289        timeWaitingToLock_(0.0),
290        timeWaitingToStart_(0.0),
291        timeInThread_(0.0),
292        numberTimesLocked_(0),
293        numberTimesUnlocked_(0),
294        numberTimesWaitingToStart_(0),
295        dantzigState_(0), // 0 unset, -1 waiting to be set, 1 set
296        locked_(false),
297        nDeleteNode_(0),
298        delNode_(NULL),
299        maxDeleteNode_(0),
300        nodesThisTime_(0),
301        iterationsThisTime_(0),
302        deterministic_(0)
303{
304}
305void
306CbcThread::gutsOfDelete()
307{
308    baseModel_ = NULL;
309    thisModel_ = NULL;
310    node_ = NULL;
311    createdNode_ = NULL;
312    delNode_ = NULL;
313}
314// Destructor
315CbcThread::~CbcThread()
316{
317}
318// Fills in useful stuff
319void
320CbcThread::setUsefulStuff (CbcModel * model, int deterministic, CbcModel * baseModel,
321                           CbcThread * master,
322                           void *& masterMutex)
323{
324    baseModel_ = baseModel;
325    thisModel_ = model;
326    deterministic_ = deterministic;
327    threadStuff_.setUsefulStuff(&master->threadStuff_, masterMutex);
328    node_ = NULL;
329    createdNode_ = NULL;
330    master_ = master;
331    returnCode_ = -1;
332    timeLocked_ = 0.0;
333    timeWaitingToLock_ = 0.0;
334    timeWaitingToStart_ = 0.0;
335    timeInThread_ = 0.0;
336    numberTimesLocked_ = 0;
337    numberTimesUnlocked_ = 0;
338    numberTimesWaitingToStart_ = 0;
339    dantzigState_ = 0; // 0 unset, -1 waiting to be set, 1 set
340    locked_ = false;
341    delNode_ = NULL;
342    maxDeleteNode_ = 0;
343    nDeleteNode_ = 0;
344    nodesThisTime_ = 0;
345    iterationsThisTime_ = 0;
346    if (model != baseModel) {
347        // thread
348        thisModel_->setInfoInChild(-3, this);
349        if (deterministic_ >= 0)
350            thisModel_->moveToModel(baseModel, -1);
351        if (deterministic == -1)
352            threadStuff_.startThread( doCutsThread, this);
353        else
354            threadStuff_.startThread( doNodesThread, this);
355    }
356}
357/*
358  Locks a thread if parallel so that stuff like cut pool
359  can be updated and/or used.
360*/
361void
362CbcThread::lockThread()
363{
364    if (!locked_) {
365        double time2 = getTime();
366        threadStuff_.lockThread();
367        locked_ = true;
368        timeWhenLocked_ = getTime();
369        timeWaitingToLock_ += timeWhenLocked_ - time2;;
370        numberTimesLocked_++;
371#ifdef THREAD_DEBUG
372        lockCount_ ++;
373#if THREAD_DEBUG>1
374        if (threadNumber_ == -1)
375            printf("locking master %d\n", lockCount_);
376        else
377            printf("locking thread %d %d\n", threadNumber_, lockCount_);
378#endif
379    } else {
380        if (threadNumber_ == -1)
381            printf("master already locked %d\n", lockCount_);
382        else
383            printf("thread already locked %d %d\n", threadNumber_, lockCount_);
384#endif
385    }
386}
387/*
388  Unlocks a thread if parallel
389*/
390void
391CbcThread::unlockThread()
392{
393    if (locked_) {
394        locked_ = false;
395        threadStuff_.unlockThread();
396        double time2 = getTime();
397        timeLocked_ += time2 - timeWhenLocked_;
398        numberTimesUnlocked_++;
399#ifdef THREAD_DEBUG
400#if THREAD_DEBUG>1
401        if (threadNumber_ == -1)
402            printf("unlocking master %d\n", lockCount_);
403        else
404            printf("unlocking thread %d %d\n", threadNumber_, lockCount_);
405#endif
406    } else {
407        if (threadNumber_ == -1)
408            printf("master already unlocked %d\n", lockCount_);
409        else
410            printf("thread already unlocked %d %d\n", threadNumber_, lockCount_);
411#endif
412    }
413}
414/* Wait for child to have return code NOT == to currentCode
415   type - 0 timed wait
416   1 wait
417   returns true if return code changed */
418bool
419CbcThread::wait(int type, int currentCode)
420{
421    if (!type) {
422        // just timed wait
423        master_->threadStuff_.lockThread2();
424        master_->threadStuff_.timedWait(1000000);
425        master_->threadStuff_.unlockThread2();
426    } else {
427        // wait until return code changes
428        while (returnCode_ == currentCode) {
429            threadStuff_.signal();
430            master_->threadStuff_.lockThread2();
431            master_->threadStuff_.timedWait(1000000);
432            master_->threadStuff_.unlockThread2();
433        }
434    }
435    return (returnCode_ != currentCode);
436}
437#if 0
438pthread_cond_signal(&condition2_);
439-
440if (!locked_)
441{
442    pthread_mutex_lock (&mutex2_);
443    locked_ = true;
444}
445-
446pthread_cond_timedwait(&condition2_, &mutex2_, &absTime);
447-
448if (locked_)
449{
450    pthread_mutex_unlock (&mutex2_);
451    locked_ = false;
452}
453#endif
454// Waits until returnCode_ goes to zero
455void
456CbcThread::waitThread()
457{
458    double time = getTime();
459    threadStuff_.lockThread2();
460    while (returnCode_) {
461        threadStuff_.timedWait(-10); // 10 seconds
462    }
463    timeWaitingToStart_ += getTime() - time;
464    numberTimesWaitingToStart_++;
465}
466// Just wait for so many nanoseconds
467void
468CbcThread::waitNano(int time)
469{
470    threadStuff_.lockThread2();
471    threadStuff_.timedWait(time);
472    threadStuff_.unlockThread2();
473}
474// Signal child to carry on
475void
476CbcThread::signal()
477{
478    threadStuff_.signal();
479}
480// Lock from master with mutex2 and signal before lock
481void
482CbcThread::lockFromMaster()
483{
484    threadStuff_.signal();
485    master_->threadStuff_.lockThread2(true);
486}
487// Unlock from master with mutex2 and signal after unlock
488void
489CbcThread::unlockFromMaster()
490{
491    master_->threadStuff_.unlockThread2(true); // unlock anyway
492    threadStuff_.signal();
493}
494// Lock from thread with mutex2 and signal before lock
495void
496CbcThread::lockFromThread()
497{
498    master_->threadStuff_.signal();
499    threadStuff_.lockThread2();
500}
501// Unlock from thread with mutex2 and signal after unlock
502void
503CbcThread::unlockFromThread()
504{
505    master_->threadStuff_.signal();
506    threadStuff_.unlockThread2();
507}
508// Exits thread (from master)
509int
510CbcThread::exit()
511{
512    return threadStuff_.exit();
513}
514// Exits thread
515void
516CbcThread::exitThread()
517{
518    threadStuff_.exitThread();
519}
520// Default constructor
521CbcBaseModel::CbcBaseModel()
522        :
523        numberThreads_(0),
524        children_(NULL),
525        type_(0),
526        threadCount_(NULL),
527        threadModel_(NULL),
528        numberObjects_(0),
529        saveObjects_(NULL),
530        defaultParallelIterations_(400),
531        defaultParallelNodes_(2)
532{
533}
534// Constructor with model
535CbcBaseModel::CbcBaseModel (CbcModel & model,  int type)
536        :
537        children_(NULL),
538        type_(type),
539        threadCount_(NULL),
540        threadModel_(NULL),
541        numberObjects_(0),
542        saveObjects_(NULL),
543        defaultParallelIterations_(400),
544        defaultParallelNodes_(2)
545{
546    numberThreads_ = model.getNumberThreads();
547    if (numberThreads_) {
548        children_ = new CbcThread [numberThreads_+1];
549        // Do a partial one for base model
550        void * mutex_main = NULL;
551        children_[numberThreads_].setUsefulStuff(&model, type_, &model,
552                children_ + numberThreads_, mutex_main);
553#ifdef THREAD_DEBUG
554        children_[numberThreads_].threadNumber_ = -1;
555        children_[numberThreads_].lockCount_ = 0;
556#endif
557        threadCount_ = new int [numberThreads_];
558        CoinZeroN(threadCount_, numberThreads_);
559        threadModel_ = new CbcModel * [numberThreads_+1];
560        memset(threadStats_, 0, sizeof(threadStats_));
561        if (type_ > 0) {
562            // May need for deterministic
563            numberObjects_ = model.numberObjects();
564            saveObjects_ = new OsiObject * [numberObjects_];
565            for (int i = 0; i < numberObjects_; i++) {
566                saveObjects_[i] = model.object(i)->clone();
567            }
568        }
569        // we don't want a strategy object
570        CbcStrategy * saveStrategy = model.strategy();
571        model.setStrategy(NULL);
572        for (int i = 0; i < numberThreads_; i++) {
573            //threadModel_[i] = new CbcModel(model, true);
574            threadModel_[i] = model. clone (true);
575            threadModel_[i]->synchronizeHandlers(1);
576#ifdef COIN_HAS_CLP
577            // Solver may need to know about model
578            CbcModel * thisModel = threadModel_[i];
579            CbcOsiSolver * solver =
580                dynamic_cast<CbcOsiSolver *>(thisModel->solver()) ;
581            if (solver)
582                solver->setCbcModel(thisModel);
583#endif
584            children_[i].setUsefulStuff(threadModel_[i], type_, &model,
585                                        children_ + numberThreads_, mutex_main);
586#ifdef THREAD_DEBUG
587            children_[i].threadNumber_ = i;
588            children_[i].lockCount_ = 0;
589#endif
590        }
591        model.setStrategy(saveStrategy);
592    }
593}
594// Stop threads
595void
596CbcBaseModel::stopThreads(int type)
597{
598    CbcModel * baseModel = children_[0].baseModel();
599    if (type < 0) {
600        // max nodes ?
601        bool finished = false;
602        while (!finished) {
603          finished = true;
604          for (int i = 0; i < numberThreads_; i++) {
605            if (abs(children_[i].returnCode()) != 1) {
606              children_[i].wait(1, 0); 
607              finished=false;
608            }
609          }
610        }
611        for (int i = 0; i < numberThreads_; i++) {
612          baseModel->incrementExtra(threadModel_[i]->getExtraNodeCount(),
613                                    threadModel_[i]->numberExtraIterations(),
614                                    threadModel_[i]->getFathomCount());
615          threadModel_[i]->zeroExtra();
616        }
617        return;
618    }
619    for (int i = 0; i < numberThreads_; i++) {
620        children_[i].wait(1, 0);
621        assert (children_[i].returnCode() == -1);
622        baseModel->incrementExtra(threadModel_[i]->getExtraNodeCount(),
623                                  threadModel_[i]->numberExtraIterations(),
624                                  threadModel_[i]->getFathomCount());
625        threadModel_[i]->setInfoInChild(-2, NULL);
626        children_[i].setReturnCode( 0);
627        children_[i].exit();
628        children_[i].setStatus( 0);
629    }
630    // delete models and solvers
631    for (int i = 0; i < numberThreads_; i++) {
632        threadModel_[i]->setInfoInChild(type_, NULL);
633        delete threadModel_[i];
634    }
635    delete [] children_;
636    delete [] threadModel_;
637    for (int i = 0; i < numberObjects_; i++)
638        delete saveObjects_[i];
639    delete [] saveObjects_;
640    children_ = NULL;
641    threadModel_ = NULL;
642    saveObjects_ = NULL;
643    numberObjects_ = 0;
644    numberThreads_ = 0;
645}
646// Wait for threads in tree
647int
648CbcBaseModel::waitForThreadsInTree(int type)
649{
650    CbcModel * baseModel = children_[0].baseModel();
651    int anyLeft = 0;
652    // May be able to combine parts later
653    if (type == 0) {
654        bool locked = true;
655#ifdef COIN_DEVELOP
656        printf("empty\n");
657#endif
658        // may still be outstanding nodes
659        while (true) {
660            int iThread;
661            for (iThread = 0; iThread < numberThreads_; iThread++) {
662                if (children_[iThread].status()) {
663                  if (children_[iThread].returnCode() == 0) {
664                        break;
665                  }
666                }
667            }
668            if (iThread < numberThreads_) {
669#ifdef COIN_DEVELOP
670                printf("waiting for thread %d code 0\n", iThread);
671#endif
672                unlockThread();
673                locked = false;
674                children_[iThread].wait(1, 0);
675                assert(children_[iThread].returnCode() == 1);
676                threadModel_[iThread]->moveToModel(baseModel, 1);
677#ifdef THREAD_PRINT
678                printf("off thread2 %d node %x\n", iThread, children_[iThread].node());
679#endif
680                children_[iThread].setNode(NULL);
681                anyLeft = 1;
682                assert (children_[iThread].returnCode() == 1);
683                if (children_[iThread].dantzigState() == -1) {
684                    // 0 unset, -1 waiting to be set, 1 set
685                    children_[iThread].setDantzigState(1);
686                    CbcModel * model = children_[iThread].thisModel();
687                    OsiClpSolverInterface * clpSolver2
688                    = dynamic_cast<OsiClpSolverInterface *> (model->solver());
689                    assert (clpSolver2);
690                    ClpSimplex * simplex2 = clpSolver2->getModelPtr();
691                    ClpDualRowDantzig dantzig;
692                    simplex2->setDualRowPivotAlgorithm(dantzig);
693                }
694                // say available
695                children_[iThread].setReturnCode( -1);
696                threadStats_[4]++;
697#ifdef COIN_DEVELOP
698                printf("thread %d code now -1\n", iThread);
699#endif
700                break;
701            } else {
702#ifdef COIN_DEVELOP
703                printf("no threads at code 0 \n");
704#endif
705                // now check if any have just finished
706                for (iThread = 0; iThread < numberThreads_; iThread++) {
707                    if (children_[iThread].status()) {
708                        if (children_[iThread].returnCode() == 1)
709                            break;
710                    }
711                }
712                if (iThread < numberThreads_) {
713                    unlockThread();
714                    locked = false;
715                    threadModel_[iThread]->moveToModel(baseModel, 1);
716#ifdef THREAD_PRINT
717                    printf("off thread3 %d node %x\n", iThread, children_[iThread].node());
718#endif
719                    children_[iThread].setNode(NULL);
720                    anyLeft = 1;
721                    assert (children_[iThread].returnCode() == 1);
722                    // say available
723                    children_[iThread].setReturnCode( -1);
724                    threadStats_[4]++;
725#ifdef COIN_DEVELOP
726                    printf("thread %d code now -1\n", iThread);
727#endif
728                    break;
729                }
730            }
731            if (!baseModel->tree()->empty()) {
732#ifdef COIN_DEVELOP
733                printf("tree not empty!!!!!!\n");
734#endif
735                if (locked)
736                    unlockThread();
737                return 1;
738                break;
739            }
740            for (iThread = 0; iThread < numberThreads_; iThread++) {
741                if (children_[iThread].status()) {
742                    if (children_[iThread].returnCode() != -1) {
743                        printf("bad end of tree\n");
744                        abort();
745                    }
746                }
747            }
748            break;
749        }
750#ifdef COIN_DEVELOP
751        printf("finished ************\n");
752#endif
753        if (locked)
754            unlockThread();
755        return anyLeft;
756    } else if (type == 1) {
757        // normal
758        double cutoff = baseModel->getCutoff();
759        CbcNode * node = baseModel->tree()->bestNode(cutoff) ;
760        // Possible one on tree worse than cutoff
761        if (!node || node->objectiveValue() > cutoff)
762            return 1;
763        threadStats_[0]++;
764        //need to think
765        int iThread;
766        // Start one off if any available
767        for (iThread = 0; iThread < numberThreads_; iThread++) {
768          if (children_[iThread].returnCode() == -1) {
769                break;
770          }
771        }
772        if (iThread < numberThreads_) {
773            children_[iThread].setNode(node);
774#ifdef THREAD_PRINT
775            printf("empty thread %d node %x\n", iThread, children_[iThread].node());
776#endif
777            assert (children_[iThread].returnCode() == -1);
778            // say in use
779            threadModel_[iThread]->moveToModel(baseModel, 0);
780            // This has to be AFTER moveToModel
781            children_[iThread].setReturnCode( 0);
782            children_[iThread].signal();
783            threadCount_[iThread]++;
784        }
785        lockThread();
786        // see if any finished
787        for (iThread = 0; iThread < numberThreads_; iThread++) {
788            if (children_[iThread].returnCode() > 0)
789                break;
790        }
791        unlockThread();
792        if (iThread < numberThreads_) {
793            threadModel_[iThread]->moveToModel(baseModel, 1);
794#ifdef THREAD_PRINT
795            printf("off thread4 %d node %x\n", iThread, children_[iThread].node());
796#endif
797            children_[iThread].setNode(NULL);
798            anyLeft = 1;
799            assert (children_[iThread].returnCode() == 1);
800            // say available
801            children_[iThread].setReturnCode( -1);
802            // carry on
803            threadStats_[3]++;
804        } else {
805            // Start one off if any available
806            for (iThread = 0; iThread < numberThreads_; iThread++) {
807                if (children_[iThread].returnCode() == -1)
808                    break;
809            }
810            if (iThread < numberThreads_) {
811                // If any on tree get
812                if (!baseModel->tree()->empty()) {
813                    //node = baseModel->tree()->bestNode(cutoff) ;
814                    //assert (node);
815                    threadStats_[1]++;
816                    return 1; // ** get another node
817                }
818            }
819            // wait (for debug could sleep and use test)
820            bool finished = false;
821            while (!finished) {
822                double time = getTime();
823                children_[numberThreads_].wait(0, 0);
824                children_[numberThreads_].incrementTimeInThread(getTime() - time);
825                for (iThread = 0; iThread < numberThreads_; iThread++) {
826                    if (children_[iThread].returnCode() > 0) {
827                        finished = true;
828                        break;
829                    } else if (children_[iThread].returnCode() == 0) {
830                        children_[iThread].signal(); // unlock
831                    }
832                }
833            }
834            assert (iThread < numberThreads_);
835            // move information to model
836            threadModel_[iThread]->moveToModel(baseModel, 1);
837            anyLeft = 1;
838#ifdef THREAD_PRINT
839            printf("off thread %d node %x\n", iThread, children_[iThread].node());
840#endif
841            children_[iThread].setNode(NULL);
842            assert (children_[iThread].returnCode() == 1);
843            // say available
844            children_[iThread].setReturnCode( -1);
845        }
846        // carry on
847        threadStats_[2]++;
848        for (int iThread = 0; iThread < numberThreads_; iThread++) {
849            if (children_[iThread].status()) {
850                if (children_[iThread].returnCode() != -1) {
851                    anyLeft = 1;
852                    break;
853                }
854            }
855        }
856        return anyLeft;
857    } else if (type == 2) {
858        if (!baseModel->tree()->empty()) {
859          // max nodes ?
860          bool finished = false;
861          while (!finished) {
862            finished = true;
863            for (int iThread = 0; iThread < numberThreads_; iThread++) {
864              if (children_[iThread].returnCode() == 0) { 
865                double time = getTime();
866                children_[numberThreads_].wait(0, 0);
867                children_[numberThreads_].incrementTimeInThread(getTime() - time);
868                finished = false;
869                children_[iThread].signal(); // unlock
870              }
871            }
872          }
873        }
874        int i;
875        // do statistics
876        // Seems to be bug in CoinCpu on Linux - does threads as well despite documentation
877        double time = 0.0;
878        for (i = 0; i < numberThreads_; i++)
879            time += children_[i].timeInThread();
880        bool goodTimer = time < (baseModel->getCurrentSeconds());
881        for (i = 0; i < numberThreads_; i++) {
882            while (children_[i].returnCode() == 0) {
883                children_[i].signal();
884                double time = getTime();
885                children_[numberThreads_].wait(0, 0);
886                children_[numberThreads_].incrementTimeInThread(getTime() - time);
887            }
888            children_[i].lockFromMaster();
889            threadModel_[i]->setNumberThreads(0); // say exit
890            if (children_[i].deterministic() > 0)
891                delete [] children_[i].delNode();
892            if (children_[i].node()) {
893              delete children_[i].node();
894              children_[i].setNode(NULL);
895            }
896            children_[i].setReturnCode( 0);
897            children_[i].unlockFromMaster();
898#ifndef NDEBUG
899            int returnCode = children_[i].exit();
900            assert (!returnCode);
901#else
902            children_[i].exit();
903#endif
904            children_[i].setStatus( 0);
905            //else
906            threadModel_[i]->moveToModel(baseModel, 2);
907            assert (children_[i].numberTimesLocked() == children_[i].numberTimesUnlocked());
908            baseModel->messageHandler()->message(CBC_THREAD_STATS, baseModel->messages())
909            << "Thread";
910            baseModel->messageHandler()->printing(true)
911            << i << threadCount_[i] << children_[i].timeWaitingToStart();
912            baseModel->messageHandler()->printing(goodTimer) << children_[i].timeInThread();
913            baseModel->messageHandler()->printing(false) << 0.0;
914            baseModel->messageHandler()->printing(true) << children_[i].numberTimesLocked()
915            << children_[i].timeLocked() << children_[i].timeWaitingToLock()
916            << CoinMessageEol;
917        }
918        assert (children_[numberThreads_].numberTimesLocked() == children_[numberThreads_].numberTimesUnlocked());
919        baseModel->messageHandler()->message(CBC_THREAD_STATS, baseModel->messages())
920        << "Main thread";
921        baseModel->messageHandler()->printing(false) << 0 << 0 << 0.0;
922        baseModel->messageHandler()->printing(false) << 0.0;
923        baseModel->messageHandler()->printing(true) << children_[numberThreads_].timeInThread();
924        baseModel->messageHandler()->printing(true) << children_[numberThreads_].numberTimesLocked()
925        << children_[numberThreads_].timeLocked() << children_[numberThreads_].timeWaitingToLock()
926        << CoinMessageEol;
927        // delete models (here in case some point to others)
928        for (i = 0; i < numberThreads_; i++) {
929            // make sure handler will be deleted
930            threadModel_[i]->setDefaultHandler(true);
931            //delete threadModel_[i];
932        }
933    } else {
934        abort();
935    }
936    return 0;
937}
938void
939CbcBaseModel::waitForThreadsInCuts(int type, OsiCuts * eachCuts,
940                                   int whichGenerator)
941{
942    if (type == 0) {
943        // cuts while doing
944        bool finished = false;
945        int iThread = -1;
946        // see if any available
947        for (iThread = 0; iThread < numberThreads_; iThread++) {
948            if (children_[iThread].returnCode()) {
949                finished = true;
950                break;
951            } else if (children_[iThread].returnCode() == 0) {
952                children_[iThread].signal();
953            }
954        }
955        while (!finished) {
956            children_[numberThreads_].waitNano(1000000);
957            for (iThread = 0; iThread < numberThreads_; iThread++) {
958                if (children_[iThread].returnCode() > 0) {
959                    finished = true;
960                    break;
961                } else if (children_[iThread].returnCode() == 0) {
962                    children_[iThread].signal();
963                }
964            }
965        }
966        assert (iThread < numberThreads_);
967        assert (children_[iThread].returnCode());
968        // Use dantzigState to signal which generator
969        children_[iThread].setDantzigState(whichGenerator);
970        // and delNode for eachCuts
971        children_[iThread].fakeDelNode(reinterpret_cast<CbcNode **> (eachCuts));
972        // allow to start
973        children_[iThread].setReturnCode( 0);
974        children_[iThread].signal();
975    } else if (type == 1) {
976        // cuts - finish up
977        for (int iThread = 0; iThread < numberThreads_; iThread++) {
978            if (children_[iThread].returnCode() == 0) {
979                bool finished = false;
980                while (!finished) {
981                    children_[numberThreads_].wait(0, 0);
982                    if (children_[iThread].returnCode() > 0) {
983                        finished = true;
984                        break;
985                        //#ifndef NEW_STYLE_PTHREAD
986                        //} else if (children_[iThread].returnCode_ == 0) {
987                        //pthread_cond_signal(&children_[iThread].threadStuff_.condition2_); // unlock
988                        //#endif
989                    }
990                }
991            }
992            assert (children_[iThread].returnCode());
993            // say available
994            children_[iThread].setReturnCode( -1);
995            //delete threadModel_[iThread]->solver();
996            //threadModel_[iThread]->setSolver(NULL);
997        }
998    } else {
999        abort();
1000    }
1001}
1002// Returns pointer to master thread
1003CbcThread *
1004CbcBaseModel::masterThread() const
1005{
1006    return children_ + numberThreads_;
1007}
1008
1009// Split model and do work in deterministic parallel
1010void
1011CbcBaseModel::deterministicParallel()
1012{
1013    CbcModel * baseModel = children_[0].baseModel();
1014    for (int i = 0; i < numberThreads_; i++)
1015        threadCount_[i]++;
1016    int saveTreeSize = baseModel->tree()->size();
1017    // For now create threadModel - later modify splitModel
1018    CbcModel ** threadModel = new CbcModel * [numberThreads_];
1019    int iThread;
1020    for (iThread = 0; iThread < numberThreads_; iThread++)
1021        threadModel[iThread] = children_[iThread].thisModel();
1022
1023    int nAffected = baseModel->splitModel(numberThreads_, threadModel, defaultParallelNodes_);
1024    // do all until finished
1025    for (iThread = 0; iThread < numberThreads_; iThread++) {
1026        // obviously tune
1027        children_[iThread].setNDeleteNode(defaultParallelIterations_);
1028    }
1029    // Save current state
1030    int iObject;
1031    OsiObject ** object = baseModel->objects();
1032    for (iObject = 0; iObject < numberObjects_; iObject++) {
1033        saveObjects_[iObject]->updateBefore(object[iObject]);
1034    }
1035    //#define FAKE_PARALLEL
1036#ifndef FAKE_PARALLEL
1037    for (iThread = 0; iThread < numberThreads_; iThread++) {
1038        children_[iThread].setReturnCode( 0);
1039        children_[iThread].signal();
1040    }
1041    // wait
1042    bool finished = false;
1043    double time = getTime();
1044    while (!finished) {
1045        children_[numberThreads_].waitNano( 1000000); // millisecond
1046        finished = true;
1047        for (iThread = 0; iThread < numberThreads_; iThread++) {
1048            if (children_[iThread].returnCode() <= 0) {
1049                finished = false;
1050            }
1051        }
1052    }
1053    for (iThread = 0; iThread < numberThreads_; iThread++)
1054        children_[iThread].setReturnCode(-1);
1055#else
1056    // wait
1057    bool finished = false;
1058    double time = getTime();
1059    for (iThread = 0; iThread < numberThreads_; iThread++) {
1060        children_[iThread].setReturnCode( 0);
1061        children_[iThread].signal();
1062        while (!finished) {
1063          children_[numberThreads_].waitNano( 1000000); // millisecond
1064          finished = (children_[iThread].returnCode() >0);
1065        }
1066        children_[iThread].setReturnCode(-1);
1067        finished=false;
1068    }
1069#endif
1070    children_[numberThreads_].incrementTimeInThread(getTime() - time);
1071    // Unmark marked
1072    for (int i = 0; i < nAffected; i++) {
1073        baseModel->walkback()[i]->unmark();
1074    }
1075    int iModel;
1076    double scaleFactor = 1.0;
1077    for (iModel = 0; iModel < numberThreads_; iModel++) {
1078        //printf("model %d tree size %d\n",iModel,threadModel[iModel]->baseModel->tree()->size());
1079        if (saveTreeSize > 4*numberThreads_*defaultParallelNodes_) {
1080            if (!threadModel[iModel]->tree()->size()) {
1081                scaleFactor *= 1.05;
1082            }
1083        }
1084        threadModel[iModel]->moveToModel(baseModel, 11);
1085        // Update base model
1086        OsiObject ** threadObject = threadModel[iModel]->objects();
1087        for (iObject = 0; iObject < numberObjects_; iObject++) {
1088            object[iObject]->updateAfter(threadObject[iObject], saveObjects_[iObject]);
1089        }
1090    }
1091    if (scaleFactor != 1.0) {
1092        int newNumber = static_cast<int> (defaultParallelNodes_ * scaleFactor + 0.5001);
1093        if (newNumber*2 < defaultParallelIterations_) {
1094            if (defaultParallelNodes_ == 1)
1095                newNumber = 2;
1096            if (newNumber != defaultParallelNodes_) {
1097                char general[200];
1098                sprintf(general, "Changing tree size from %d to %d",
1099                        defaultParallelNodes_, newNumber);
1100                baseModel->messageHandler()->message(CBC_GENERAL,
1101                                                     baseModel->messages())
1102                << general << CoinMessageEol ;
1103                defaultParallelNodes_ = newNumber;
1104            }
1105        }
1106    }
1107    delete [] threadModel;
1108}
1109// Destructor
1110CbcBaseModel::~CbcBaseModel()
1111{
1112    delete [] threadCount_;
1113#if 1
1114    for (int i = 0; i < numberThreads_; i++)
1115        delete threadModel_[i];
1116    delete [] threadModel_;
1117    delete [] children_;
1118#endif
1119    for (int i = 0; i < numberObjects_; i++)
1120        delete saveObjects_[i];
1121    delete [] saveObjects_;
1122}
1123// Sets Dantzig state in children
1124void
1125CbcBaseModel::setDantzigState()
1126{
1127    for (int i = 0; i < numberThreads_; i++) {
1128        children_[i].setDantzigState(-1);
1129    }
1130}
1131static void * doNodesThread(void * voidInfo)
1132{
1133    CbcThread * stuff = reinterpret_cast<CbcThread *> (voidInfo);
1134    CbcModel * thisModel = stuff->thisModel();
1135    CbcModel * baseModel = stuff->baseModel();
1136    while (true) {
1137        stuff->waitThread();
1138        //printf("start node %x\n",stuff->node);
1139        int mode = thisModel->getNumberThreads();
1140        if (mode) {
1141            // normal
1142            double time2 = CoinCpuTime();
1143            assert (stuff->returnCode() == 0);
1144            if (thisModel->parallelMode() >= 0) {
1145                CbcNode * node = stuff->node();
1146                //assert (node->nodeInfo());
1147                CbcNode * createdNode = stuff->createdNode();
1148                // try and see if this has slipped through
1149                if (node) {
1150                  thisModel->doOneNode(baseModel, node, createdNode);
1151                } else {
1152                  //printf("null node\n");
1153                  createdNode=NULL;
1154                }
1155                stuff->setNode(node);
1156                stuff->setCreatedNode(createdNode);
1157                stuff->setReturnCode( 1);
1158            } else {
1159                assert (!stuff->node());
1160                assert (!stuff->createdNode());
1161                int numberIterations = stuff->nDeleteNode();
1162                int nDeleteNode = 0;
1163                int maxDeleteNode = stuff->maxDeleteNode();
1164                CbcNode ** delNode = stuff->delNode();
1165                int returnCode = 1;
1166                // this should be updated by heuristics strong branching etc etc
1167                assert (numberIterations > 0);
1168                thisModel->setNumberThreads(0);
1169                int nodesThisTime = thisModel->getNodeCount();
1170                int iterationsThisTime = thisModel->getIterationCount();
1171                int strongThisTime = thisModel->numberStrongIterations();
1172                thisModel->setStopNumberIterations(thisModel->getIterationCount() + numberIterations);
1173                int numberColumns = thisModel->getNumCols();
1174                int * used = CoinCopyOfArray(thisModel->usedInSolution(), numberColumns);
1175                int numberSolutions = thisModel->getSolutionCount();
1176                while (true) {
1177                    if (thisModel->tree()->empty()) {
1178                        returnCode = 1 + 1;
1179#ifdef CLP_INVESTIGATE_2
1180                        printf("%x tree empty - time %18.6f\n", thisModel, CoinGetTimeOfDay() - 1.2348e9);
1181#endif
1182                        break;
1183                    }
1184#define NODE_ITERATIONS 2
1185                    int nodesNow = thisModel->getNodeCount();
1186                    int iterationsNow = thisModel->getIterationCount();
1187                    int strongNow = thisModel->numberStrongIterations();
1188                    bool exit1 = (NODE_ITERATIONS * ((nodesNow - nodesThisTime) +
1189                                                     ((strongNow - strongThisTime) >> 1)) +
1190                                  (iterationsNow - iterationsThisTime) > numberIterations);
1191                    //bool exit2 =(thisModel->getIterationCount()>thisModel->getStopNumberIterations()) ;
1192                    //assert (exit1==exit2);
1193                    if (exit1 && nodesNow - nodesThisTime >= 10) {
1194                        // out of loop
1195                        //printf("out of loop\n");
1196#ifdef CLP_INVESTIGATE3
1197                        printf("%x tree %d nodes left, done %d and %d its - time %18.6f\n", thisModel,
1198                               thisModel->tree()->size(), nodesNow - nodesThisTime,
1199                               iterationsNow - iterationsThisTime, CoinGetTimeOfDay() - 1.2348e9);
1200#endif
1201                        break;
1202                    }
1203                    double cutoff = thisModel->getCutoff() ;
1204                    CbcNode *node = thisModel->tree()->bestNode(cutoff) ;
1205                    // Possible one on tree worse than cutoff
1206                    if (!node)
1207                        continue;
1208                    CbcNode * createdNode = NULL;
1209                    // Do real work of node
1210                    thisModel->doOneNode(NULL, node, createdNode);
1211                    assert (createdNode);
1212                    if (!createdNode->active()) {
1213                        delete createdNode;
1214                    } else {
1215                        // Say one more pointing to this **** postpone if marked
1216                        node->nodeInfo()->increment() ;
1217                        thisModel->tree()->push(createdNode) ;
1218                    }
1219                    if (node->active()) {
1220                        assert (node->nodeInfo());
1221                        if (node->nodeInfo()->numberBranchesLeft()) {
1222                            thisModel->tree()->push(node) ;
1223                        } else {
1224                            node->setActive(false);
1225                        }
1226                    } else {
1227                        if (node->nodeInfo()) {
1228                            if (!node->nodeInfo()->numberBranchesLeft())
1229                                node->nodeInfo()->allBranchesGone(); // can clean up
1230                            // So will delete underlying stuff
1231                            node->setActive(true);
1232                        }
1233                        if (nDeleteNode == maxDeleteNode) {
1234                            maxDeleteNode = (3 * maxDeleteNode) / 2 + 10;
1235                            stuff->setMaxDeleteNode(maxDeleteNode);
1236                            stuff->setDelNode(new CbcNode * [maxDeleteNode]);
1237                            for (int i = 0; i < nDeleteNode; i++)
1238                                stuff->delNode()[i] = delNode[i];
1239                            delete [] delNode;
1240                            delNode = stuff->delNode();
1241                        }
1242                        delNode[nDeleteNode++] = node;
1243                    }
1244                }
1245                // end of this sub-tree
1246                int * usedA = thisModel->usedInSolution();
1247                for (int i = 0; i < numberColumns; i++) {
1248                    usedA[i] -= used[i];
1249                }
1250                delete [] used;
1251                thisModel->setSolutionCount(thisModel->getSolutionCount() - numberSolutions);
1252                stuff->setNodesThisTime(thisModel->getNodeCount() - nodesThisTime);
1253                stuff->setIterationsThisTime(thisModel->getIterationCount() - iterationsThisTime);
1254                stuff->setNDeleteNode(nDeleteNode);
1255                stuff->setReturnCode( returnCode);
1256                thisModel->setNumberThreads(mode);
1257            }
1258            //printf("end node %x\n",stuff->node);
1259            stuff->unlockFromThread();
1260            stuff->incrementTimeInThread(CoinCpuTime() - time2);
1261        } else {
1262            // exit
1263            break;
1264        }
1265    }
1266    //printf("THREAD exiting\n");
1267    stuff->exitThread();
1268    return NULL;
1269}
1270static void * doHeurThread(void * voidInfo)
1271{
1272    typedef struct {
1273        double solutionValue;
1274        CbcModel * model;
1275        double * solution;
1276        int foundSol;
1277    } argBundle;
1278    argBundle * stuff = reinterpret_cast<argBundle *> (voidInfo);
1279    stuff->foundSol =
1280        stuff->model->heuristic(0)->solution(stuff->solutionValue,
1281                                             stuff->solution);
1282    return NULL;
1283}
1284static void * doCutsThread(void * voidInfo)
1285{
1286    CbcThread * stuff = reinterpret_cast<CbcThread *> (voidInfo);
1287    CbcModel * thisModel =  stuff->thisModel();
1288    while (true) {
1289        stuff->waitThread();
1290        //printf("start node %x\n",stuff->node);
1291        int mode = thisModel->getNumberThreads();
1292        if (mode) {
1293            // normal
1294            assert (stuff->returnCode() == 0);
1295            int fullScan = thisModel->getNodeCount() == 0 ? 1 : 0; //? was >0
1296            CbcCutGenerator * generator = thisModel->cutGenerator(stuff->dantzigState());
1297            generator->refreshModel(thisModel);
1298            OsiCuts * cuts = reinterpret_cast<OsiCuts *> (stuff->delNode());
1299            OsiSolverInterface * thisSolver = thisModel->solver();
1300            generator->generateCuts(*cuts, fullScan, thisSolver, NULL);
1301            stuff->setReturnCode( 1);
1302            stuff->unlockFromThread();
1303        } else {
1304            // exit
1305            break;
1306        }
1307    }
1308    stuff->exitThread();
1309    return NULL;
1310}
1311// Split up nodes - returns number of CbcNodeInfo's affected
1312int
1313CbcModel::splitModel(int numberModels, CbcModel ** model,
1314                     int numberNodes)
1315{
1316    int iModel;
1317    int i;
1318    for (iModel = 0; iModel < numberModels; iModel++) {
1319        CbcModel * otherModel = model[iModel];
1320        otherModel->moveToModel(this, 10);
1321        assert (!otherModel->tree()->size());
1322        otherModel->tree()->resetNodeNumbers();
1323        otherModel->bestPossibleObjective_ = bestPossibleObjective_;
1324        otherModel->sumChangeObjective1_ = sumChangeObjective1_;
1325        otherModel->sumChangeObjective2_ = sumChangeObjective2_;
1326        int numberColumns = solver_->getNumCols();
1327        if (otherModel->bestSolution_) {
1328            assert (bestSolution_);
1329            memcpy(otherModel->bestSolution_, bestSolution_, numberColumns*sizeof(double));
1330        } else if (bestSolution_) {
1331            otherModel->bestSolution_ = CoinCopyOfArray(bestSolution_, numberColumns);
1332        }
1333        otherModel->globalCuts_ = globalCuts_;
1334        otherModel->numberSolutions_ = numberSolutions_;
1335        otherModel->numberHeuristicSolutions_ = numberHeuristicSolutions_;
1336        otherModel->numberNodes_ = numberNodes_;
1337        otherModel->numberIterations_ = numberIterations_;
1338#ifdef JJF_ZERO
1339        if (maximumNumberCuts_ > otherModel->maximumNumberCuts_) {
1340            otherModel->maximumNumberCuts_ = maximumNumberCuts_;
1341            delete [] otherModel->addedCuts_;
1342            otherModel->addedCuts_ = new CbcCountRowCut * [maximumNumberCuts_];
1343        }
1344        if (maximumDepth_ > otherModel->maximumDepth_) {
1345            otherModel->maximumDepth_ = maximumDepth_;
1346            delete [] otherModel->walkback_;
1347            otherModel->walkback_ = new CbcNodeInfo * [maximumDepth_];
1348        }
1349#endif
1350        otherModel->currentNumberCuts_ = currentNumberCuts_;
1351        if (otherModel->usedInSolution_) {
1352            assert (usedInSolution_);
1353            memcpy(otherModel->usedInSolution_, usedInSolution_, numberColumns*sizeof(int));
1354        } else if (usedInSolution_) {
1355            otherModel->usedInSolution_ = CoinCopyOfArray(usedInSolution_, numberColumns);
1356        }
1357        /// ??? tree_;
1358        // Need flag (stopNumberIterations_>0?) which says don't update cut etc counts
1359        for (i = 0; i < numberObjects_; i++) {
1360            otherModel->object_[i]->updateBefore(object_[i]);
1361        }
1362        otherModel->maximumDepthActual_ = maximumDepthActual_;
1363        // Real cuts are in node info
1364        otherModel->numberOldActiveCuts_ = numberOldActiveCuts_;
1365        otherModel->numberNewCuts_ = numberNewCuts_;
1366        otherModel->numberStrongIterations_ = numberStrongIterations_;
1367    }
1368    double cutoff = getCutoff();
1369    int nAffected = 0;
1370    while (!tree_->empty()) {
1371        for (iModel = 0; iModel < numberModels; iModel++) {
1372            if (tree_->empty())
1373                break;
1374            CbcModel * otherModel = model[iModel];
1375            CbcNode * node = tree_->bestNode(cutoff) ;
1376            CbcNodeInfo * nodeInfo = node->nodeInfo();
1377            assert (nodeInfo);
1378            if (!nodeInfo->marked()) {
1379                //while (nodeInfo&&!nodeInfo->marked()) {
1380                if (nAffected == maximumDepth_) {
1381                    redoWalkBack();
1382                }
1383                nodeInfo->mark();
1384                //nodeInfo->incrementCuts(1000000);
1385                walkback_[nAffected++] = nodeInfo;
1386                //nodeInfo = nodeInfo->parent() ;
1387                //}
1388            }
1389            // Make node join otherModel
1390            OsiBranchingObject * bobj = node->modifiableBranchingObject();
1391            CbcBranchingObject * cbcobj = dynamic_cast<CbcBranchingObject *> (bobj);
1392            //assert (cbcobj);
1393            if (cbcobj) {
1394                CbcObject * object = cbcobj->object();
1395                assert (object);
1396                int position = object->position();
1397                assert (position >= 0);
1398                assert (object_[position] == object);
1399                CbcObject * objectNew =
1400                    dynamic_cast<CbcObject *> (otherModel->object_[position]);
1401                cbcobj->setOriginalObject(objectNew);
1402            }
1403            otherModel->tree_->push(node);
1404        }
1405        numberNodes--;
1406        if (!numberNodes)
1407            break;
1408    }
1409    return nAffected;
1410}
1411// Start threads
1412void
1413CbcModel::startSplitModel(int /*numberIterations*/)
1414{
1415    abort();
1416}
1417// Merge models
1418void
1419CbcModel::mergeModels(int /*numberModel*/, CbcModel ** /*model*/,
1420                      int /*numberNodes*/)
1421{
1422    abort();
1423}
1424/* Move/copy information from one model to another
1425   -1 - initial setup
1426   0 - from base model
1427   1 - to base model (and reset)
1428   2 - add in final statistics etc (and reset so can do clean destruction)
1429   10 - from base model (deterministic)
1430   11 - to base model (deterministic)
1431*/
1432void
1433CbcModel::moveToModel(CbcModel * baseModel, int mode)
1434{
1435#ifdef THREAD_DEBUG
1436    {
1437      CbcThread * stuff = reinterpret_cast<CbcThread *> (masterThread_);
1438      if (stuff) 
1439        printf("mode %d node_ %p createdNode_ %p - stuff %p\n",
1440               mode,stuff->node(),stuff->createdNode(),stuff);
1441      else
1442        printf("mode %d null stuff\n",mode);
1443    }
1444#endif
1445    if (mode == 0) {
1446        setCutoff(baseModel->getCutoff());
1447        bestObjective_ = baseModel->bestObjective_;
1448        //assert (!baseModel->globalCuts_.sizeRowCuts());
1449        if (numberSolutions_ < baseModel->numberSolutions_&& baseModel->bestSolution_) {
1450          int numberColumns = solver_->getNumCols();
1451          if (!bestSolution_)
1452            bestSolution_ = new double [numberColumns];
1453          memcpy(bestSolution_,baseModel->bestSolution_,
1454                 numberColumns*sizeof(double));
1455          numberSolutions_ = baseModel->numberSolutions_;
1456        }
1457        stateOfSearch_ = baseModel->stateOfSearch_;
1458        numberNodes_ = baseModel->numberNodes_;
1459        numberIterations_ = baseModel->numberIterations_;
1460        numberFixedAtRoot_ = numberIterations_; // for statistics
1461        numberSolves_ = 0;
1462        phase_ = baseModel->phase_;
1463        assert (!nextRowCut_);
1464        nodeCompare_ = baseModel->nodeCompare_;
1465        tree_ = baseModel->tree_;
1466        assert (!subTreeModel_);
1467        //branchingMethod_ = NULL; // need something but what
1468        numberOldActiveCuts_ = baseModel->numberOldActiveCuts_;
1469        cutModifier_ = NULL;
1470        assert (!analyzeResults_);
1471        CbcThread * stuff = reinterpret_cast<CbcThread *> (masterThread_);
1472        assert (stuff);
1473        //if (stuff)
1474        stuff->setCreatedNode(NULL);
1475        // ?? searchStrategy_;
1476        searchStrategy_ = baseModel->searchStrategy_;
1477        stuff->saveStuff()[0] = searchStrategy_;
1478        stateOfSearch_ = baseModel->stateOfSearch_;
1479        stuff->saveStuff()[1] = stateOfSearch_;
1480        for (int iObject = 0 ; iObject < numberObjects_ ; iObject++) {
1481            CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
1482                dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object_[iObject]) ;
1483            if (dynamicObject) {
1484                CbcSimpleIntegerDynamicPseudoCost * baseObject =
1485                    dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(baseModel->object_[iObject]) ;
1486                assert (baseObject);
1487                dynamicObject->copySome(baseObject);
1488            }
1489        }
1490        // add new global cuts
1491        CbcRowCuts * baseGlobal = baseModel->globalCuts();
1492        CbcRowCuts * thisGlobal = globalCuts();
1493        int baseNumberCuts = baseGlobal->sizeRowCuts();
1494        int thisNumberCuts = thisGlobal->sizeRowCuts();
1495        for (int i=thisNumberCuts;i<baseNumberCuts;i++) {
1496          thisGlobal->addCutIfNotDuplicate(*baseGlobal->cut(i));
1497        }
1498        numberGlobalCutsIn_ = baseNumberCuts; 
1499    } else if (mode == 1) {
1500        lockThread();
1501        CbcThread * stuff = reinterpret_cast<CbcThread *> (masterThread_);
1502        assert (stuff);
1503        //stateOfSearch_
1504        if (stuff->saveStuff()[0] != searchStrategy_) {
1505#ifdef COIN_DEVELOP
1506            printf("changing searchStrategy from %d to %d\n",
1507                   baseModel->searchStrategy_, searchStrategy_);
1508#endif
1509            baseModel->searchStrategy_ = searchStrategy_;
1510        }
1511        if (stuff->saveStuff()[1] != stateOfSearch_) {
1512#ifdef COIN_DEVELOP
1513            printf("changing stateOfSearch from %d to %d\n",
1514                   baseModel->stateOfSearch_, stateOfSearch_);
1515#endif
1516            baseModel->stateOfSearch_ = stateOfSearch_;
1517        }
1518        if (numberUpdateItems_) {
1519            for (int i = 0; i < numberUpdateItems_; i++) {
1520                CbcObjectUpdateData * update = updateItems_ + i;
1521                int objectNumber = update->objectNumber_;
1522                CbcObject * object = dynamic_cast<CbcObject *> (baseModel->object_[objectNumber]);
1523                if (object)
1524                    object->updateInformation(*update);
1525            }
1526            numberUpdateItems_ = 0;
1527        }
1528        if (eventHappened_)
1529            baseModel->eventHappened_ = true;
1530        baseModel->numberNodes_++;
1531        baseModel->numberIterations_ +=
1532            numberIterations_ - numberFixedAtRoot_;
1533        baseModel->numberSolves_ += numberSolves_;
1534        if (stuff->node())
1535            baseModel->tree_->push(stuff->node());
1536        if (stuff->createdNode())
1537            baseModel->tree_->push(stuff->createdNode());
1538        // add new global cuts to base and take off
1539        CbcRowCuts * baseGlobal = baseModel->globalCuts();
1540        CbcRowCuts * thisGlobal = globalCuts();
1541        int thisNumberCuts = thisGlobal->sizeRowCuts();
1542        for (int i=thisNumberCuts-1;i>=numberGlobalCutsIn_;i--) {
1543          baseGlobal->addCutIfNotDuplicate(*thisGlobal->cut(i),thisGlobal->cut(i)->whichRow());
1544          thisGlobal->eraseRowCut(i);
1545        }
1546        //thisGlobal->truncate(numberGlobalCutsIn_);
1547        numberGlobalCutsIn_ = 999999; 
1548        unlockThread();
1549    } else if (mode == 2) {
1550        baseModel->sumChangeObjective1_ += sumChangeObjective1_;
1551        baseModel->sumChangeObjective2_ += sumChangeObjective2_;
1552        //baseModel->numberIterations_ += numberIterations_;
1553        for (int iGenerator = 0; iGenerator < numberCutGenerators_; iGenerator++) {
1554            CbcCutGenerator * generator = baseModel->generator_[iGenerator];
1555            CbcCutGenerator * generator2 = generator_[iGenerator];
1556            generator->incrementNumberTimesEntered(generator2->numberTimesEntered());
1557            generator->incrementNumberCutsInTotal(generator2->numberCutsInTotal());
1558            generator->incrementNumberCutsActive(generator2->numberCutsActive());
1559            generator->incrementTimeInCutGenerator(generator2->timeInCutGenerator());
1560        }
1561        if (parallelMode() >= 0)
1562            nodeCompare_ = NULL;
1563        baseModel->maximumDepthActual_ = CoinMax(baseModel->maximumDepthActual_, maximumDepthActual_);
1564        baseModel->numberDJFixed_ += numberDJFixed_;
1565        baseModel->numberStrongIterations_ += numberStrongIterations_;
1566        int i;
1567        for (i = 0; i < 3; i++)
1568            baseModel->strongInfo_[i] += strongInfo_[i];
1569        if (parallelMode() >= 0) {
1570            walkback_ = NULL;
1571            lastNodeInfo_ = NULL;
1572            lastNumberCuts_ = NULL;
1573            lastCut_ = NULL;
1574            //addedCuts_ = NULL;
1575            tree_ = NULL;
1576        }
1577        if ((moreSpecialOptions2_&32)!=0)
1578          delete eventHandler_;
1579        eventHandler_ = NULL;
1580        delete solverCharacteristics_;
1581        solverCharacteristics_ = NULL;
1582        bool newMethod = (baseModel->branchingMethod_ && baseModel->branchingMethod_->chooseMethod());
1583        if (newMethod) {
1584            // new method - we were using base models
1585            numberObjects_ = 0;
1586            object_ = NULL;
1587        }
1588    } else if (mode == -1) {
1589        delete eventHandler_;
1590        if ((moreSpecialOptions2_&32)==0||!baseModel->eventHandler_) {
1591          eventHandler_ = baseModel->eventHandler_;
1592        } else {
1593          eventHandler_ = baseModel->eventHandler_->clone();
1594          eventHandler_->setModel(this);
1595        }
1596        assert (!statistics_);
1597        assert(baseModel->solverCharacteristics_);
1598        solverCharacteristics_ = new OsiBabSolver (*baseModel->solverCharacteristics_);
1599        solverCharacteristics_->setSolver(solver_);
1600        setMaximumNodes(COIN_INT_MAX);
1601        if (parallelMode() >= 0) {
1602            delete [] walkback_;
1603            //delete [] addedCuts_;
1604            walkback_ = NULL;
1605            //addedCuts_ = NULL;
1606            delete [] lastNodeInfo_ ;
1607            lastNodeInfo_ = NULL;
1608            delete [] lastNumberCuts_ ;
1609            lastNumberCuts_ = NULL;
1610            delete [] lastCut_ ;
1611            lastCut_ = NULL;
1612            delete tree_;
1613            tree_ = NULL;
1614            delete nodeCompare_;
1615            nodeCompare_ = NULL;
1616        } else {
1617            delete tree_;
1618            tree_ = new CbcTree();
1619            tree_->setComparison(*nodeCompare_) ;
1620        }
1621        delete continuousSolver_;
1622        continuousSolver_ = baseModel->continuousSolver_->clone();
1623        // make sure solvers have correct message handler
1624        solver_->passInMessageHandler(handler_);
1625        continuousSolver_->passInMessageHandler(handler_);
1626        bool newMethod = (baseModel->branchingMethod_ && baseModel->branchingMethod_->chooseMethod());
1627        if (newMethod) {
1628            // new method uses solver - but point to base model
1629            // We may update an object in wrong order - shouldn't matter?
1630            numberObjects_ = baseModel->numberObjects_;
1631            if (parallelMode() >= 0) {
1632                object_ = baseModel->object_;
1633            } else {
1634                printf("*****WARNING - fix testosi option\n");
1635                object_ = baseModel->object_;
1636            }
1637        }
1638        int i;
1639        for (i = 0; i < numberHeuristics_; i++) {
1640            delete heuristic_[i];
1641            heuristic_[i] = baseModel->heuristic_[i]->clone();
1642            heuristic_[i]->setModelOnly(this);
1643        }
1644        for (i = 0; i < numberCutGenerators_; i++) {
1645            delete generator_[i];
1646            generator_[i] = new CbcCutGenerator(*baseModel->generator_[i]);
1647            // refreshModel was overkill as thought too many rows
1648            if (generator_[i]->needsRefresh())
1649              generator_[i]->refreshModel(this);
1650            else
1651              generator_[i]->setModel(this);
1652        }
1653    } else if (mode == 10) {
1654        setCutoff(baseModel->getCutoff());
1655        bestObjective_ = baseModel->bestObjective_;
1656        //assert (!baseModel->globalCuts_.sizeRowCuts());
1657        numberSolutions_ = baseModel->numberSolutions_;
1658        assert (usedInSolution_);
1659        assert (baseModel->usedInSolution_);
1660        memcpy(usedInSolution_, baseModel->usedInSolution_, solver_->getNumCols()*sizeof(int));
1661        stateOfSearch_ = baseModel->stateOfSearch_;
1662        //numberNodes_ = baseModel->numberNodes_;
1663        //numberIterations_ = baseModel->numberIterations_;
1664        //numberFixedAtRoot_ = numberIterations_; // for statistics
1665        phase_ = baseModel->phase_;
1666        assert (!nextRowCut_);
1667        delete nodeCompare_;
1668        nodeCompare_ = baseModel->nodeCompare_->clone();
1669        tree_->setComparison(*nodeCompare_) ;
1670        assert (!subTreeModel_);
1671        //branchingMethod_ = NULL; // need something but what
1672        numberOldActiveCuts_ = baseModel->numberOldActiveCuts_;
1673        cutModifier_ = NULL;
1674        assert (!analyzeResults_);
1675        CbcThread * stuff = reinterpret_cast<CbcThread *> (masterThread_);
1676        assert (stuff);
1677        //if (stuff)
1678        stuff->setCreatedNode(NULL);
1679        // ?? searchStrategy_;
1680        searchStrategy_ = baseModel->searchStrategy_;
1681        stuff->saveStuff()[0] = searchStrategy_;
1682        stateOfSearch_ = baseModel->stateOfSearch_;
1683        stuff->saveStuff()[1] = stateOfSearch_;
1684        OsiObject ** baseObject = baseModel->object_;
1685        for (int iObject = 0 ; iObject < numberObjects_ ; iObject++) {
1686            object_[iObject]->updateBefore(baseObject[iObject]);
1687        }
1688        //delete [] stuff->nodeCount;
1689        //stuff->nodeCount = new int [baseModel->maximumDepth_+1];
1690    } else if (mode == 11) {
1691        if (parallelMode() < 0) {
1692            // from deterministic
1693            CbcThread * stuff = reinterpret_cast<CbcThread *> (masterThread_);
1694            assert (stuff);
1695            // Move solution etc
1696            // might as well mark all including continuous
1697            int numberColumns = solver_->getNumCols();
1698            for (int i = 0; i < numberColumns; i++) {
1699                baseModel->usedInSolution_[i] += usedInSolution_[i];
1700                //usedInSolution_[i]=0;
1701            }
1702            baseModel->numberSolutions_ += numberSolutions_;
1703            if (bestObjective_ < baseModel->bestObjective_ && bestObjective_ < baseModel->getCutoff()) {
1704                baseModel->bestObjective_ = bestObjective_ ;
1705                int numberColumns = solver_->getNumCols();
1706                if (!baseModel->bestSolution_)
1707                    baseModel->bestSolution_ = new double[numberColumns];
1708                CoinCopyN(bestSolution_, numberColumns, baseModel->bestSolution_);
1709                baseModel->setCutoff(getCutoff());
1710                baseModel->handler_->message(CBC_ROUNDING, messages_)
1711                << bestObjective_
1712                << "heuristic"
1713                << baseModel->numberIterations_
1714                << baseModel->numberNodes_ << getCurrentSeconds()
1715                << CoinMessageEol;
1716            }
1717            //stateOfSearch_
1718            if (stuff->saveStuff()[0] != searchStrategy_) {
1719#ifdef COIN_DEVELOP
1720                printf("changing searchStrategy from %d to %d\n",
1721                       baseModel->searchStrategy_, searchStrategy_);
1722#endif
1723                baseModel->searchStrategy_ = searchStrategy_;
1724            }
1725            if (stuff->saveStuff()[1] != stateOfSearch_) {
1726#ifdef COIN_DEVELOP
1727                printf("changing stateOfSearch from %d to %d\n",
1728                       baseModel->stateOfSearch_, stateOfSearch_);
1729#endif
1730                baseModel->stateOfSearch_ = stateOfSearch_;
1731            }
1732            int i;
1733            if (eventHappened_)
1734                baseModel->eventHappened_ = true;
1735            baseModel->numberNodes_ += stuff->nodesThisTime();
1736            baseModel->numberIterations_ += stuff->iterationsThisTime();
1737            double cutoff = baseModel->getCutoff();
1738            while (!tree_->empty()) {
1739                CbcNode * node = tree_->bestNode(COIN_DBL_MAX) ;
1740                if (node->objectiveValue() < cutoff) {
1741                    assert(node->nodeInfo());
1742                    // Make node join correctly
1743                    OsiBranchingObject * bobj = node->modifiableBranchingObject();
1744                    CbcBranchingObject * cbcobj = dynamic_cast<CbcBranchingObject *> (bobj);
1745                    if (cbcobj) {
1746                        CbcObject * object = cbcobj->object();
1747                        assert (object);
1748                        int position = object->position();
1749                        assert (position >= 0);
1750                        assert (object_[position] == object);
1751                        CbcObject * objectNew =
1752                            dynamic_cast<CbcObject *> (baseModel->object_[position]);
1753                        cbcobj->setOriginalObject(objectNew);
1754                    }
1755                    baseModel->tree_->push(node);
1756                } else {
1757                    delete node;
1758                }
1759            }
1760            for (i = 0; i < stuff->nDeleteNode(); i++) {
1761                //printf("CbcNode %x stuff delete\n",stuff->delNode[i]);
1762                delete stuff->delNode()[i];
1763            }
1764        }
1765    } else {
1766        abort();
1767    }
1768}
1769// Generate one round of cuts - parallel mode
1770int
1771CbcModel::parallelCuts(CbcBaseModel * master, OsiCuts & theseCuts,
1772                       CbcNode * /*node*/, OsiCuts & slackCuts, int lastNumberCuts)
1773{
1774    /*
1775      Is it time to scan the cuts in order to remove redundant cuts? If so, set
1776      up to do it.
1777    */
1778    int fullScan = 0 ;
1779    if ((numberNodes_ % SCANCUTS) == 0 || (specialOptions_&256) != 0) {
1780        fullScan = 1 ;
1781        if (!numberNodes_ || (specialOptions_&256) != 0)
1782            fullScan = 2;
1783        specialOptions_ &= ~256; // mark as full scan done
1784    }
1785    // do cuts independently
1786    OsiCuts * eachCuts = new OsiCuts [numberCutGenerators_];;
1787    int i;
1788    assert (master);
1789    for (i = 0; i < numberThreads_; i++) {
1790        // set solver here after cloning
1791        master->model(i)->solver_ = solver_->clone();
1792        master->model(i)->numberNodes_ = (fullScan) ? 1 : 0;
1793    }
1794    // generate cuts
1795    int status = 0;
1796    const OsiRowCutDebugger * debugger = NULL;
1797    bool onOptimalPath = false;
1798    for (i = 0; i < numberCutGenerators_; i++) {
1799        bool generate = generator_[i]->normal();
1800        // skip if not optimal and should be (maybe a cut generator has fixed variables)
1801        if (generator_[i]->needsOptimalBasis() && !solver_->basisIsAvailable())
1802            generate = false;
1803        if (generator_[i]->switchedOff())
1804            generate = false;;
1805        if (generate) {
1806            master->waitForThreadsInCuts(0, eachCuts + i, i);
1807        }
1808    }
1809    // wait
1810    master->waitForThreadsInCuts(1, eachCuts, 0);
1811    // Now put together
1812    for (i = 0; i < numberCutGenerators_; i++) {
1813        // add column cuts
1814        int numberColumnCutsBefore = theseCuts.sizeColCuts() ;
1815        int numberColumnCuts = eachCuts[i].sizeColCuts();
1816        int numberColumnCutsAfter = numberColumnCutsBefore
1817                                    + numberColumnCuts;
1818        int j;
1819        for (j = 0; j < numberColumnCuts; j++) {
1820            theseCuts.insert(eachCuts[i].colCut(j));
1821        }
1822        int numberRowCutsBefore = theseCuts.sizeRowCuts() ;
1823        int numberRowCuts = eachCuts[i].sizeRowCuts();
1824        // insert good cuts
1825        if (numberRowCuts) {
1826            int n = numberRowCuts;
1827            numberRowCuts = 0;
1828            for (j = 0; j < n; j++) {
1829                const OsiRowCut * thisCut = eachCuts[i].rowCutPtr(j) ;
1830                if (thisCut->lb() <= 1.0e10 && thisCut->ub() >= -1.0e10) {
1831                    theseCuts.insert(eachCuts[i].rowCut(j));
1832                    numberRowCuts++;
1833                }
1834            }
1835            if (generator_[i]->mustCallAgain() && status >= 0)
1836                status = 1; // say must go round
1837        }
1838        int numberRowCutsAfter = numberRowCutsBefore
1839                                 + numberRowCuts;
1840        if (numberRowCuts) {
1841            // Check last cut to see if infeasible
1842            const OsiRowCut * thisCut = theseCuts.rowCutPtr(numberRowCutsAfter - 1) ;
1843            if (thisCut->lb() > thisCut->ub()) {
1844                status = -1; // sub-problem is infeasible
1845                break;
1846            }
1847        }
1848#ifdef CBC_DEBUG
1849        {
1850            int k ;
1851            for (k = numberRowCutsBefore; k < numberRowCutsAfter; k++) {
1852                OsiRowCut thisCut = theseCuts.rowCut(k) ;
1853                /* check size of elements.
1854                   We can allow smaller but this helps debug generators as it
1855                   is unsafe to have small elements */
1856                int n = thisCut.row().getNumElements();
1857                const int * column = thisCut.row().getIndices();
1858                const double * element = thisCut.row().getElements();
1859                //assert (n);
1860                for (int i = 0; i < n; i++) {
1861                    double value = element[i];
1862                    assert(fabs(value) > 1.0e-12 && fabs(value) < 1.0e20);
1863                }
1864            }
1865        }
1866#endif
1867        if ((specialOptions_&1) != 0) {
1868            if (onOptimalPath) {
1869                int k ;
1870                for (k = numberRowCutsBefore; k < numberRowCutsAfter; k++) {
1871                    OsiRowCut thisCut = theseCuts.rowCut(k) ;
1872                    if (debugger->invalidCut(thisCut)) {
1873                        solver_->getRowCutDebuggerAlways()->printOptimalSolution(*solver_);
1874                        solver_->writeMpsNative("badCut.mps", NULL, NULL, 2);
1875#ifdef NDEBUG
1876                        printf("Cut generator %d (%s) produced invalid cut (%dth in this go)\n",
1877                               i, generator_[i]->cutGeneratorName(), k - numberRowCutsBefore);
1878                        const double *lower = getColLower() ;
1879                        const double *upper = getColUpper() ;
1880                        int numberColumns = solver_->getNumCols();
1881                        for (int i = 0; i < numberColumns; i++)
1882                            printf("%d bounds %g,%g\n", i, lower[i], upper[i]);
1883                        abort();
1884#endif
1885                    }
1886                    assert(!debugger->invalidCut(thisCut)) ;
1887                }
1888            }
1889        }
1890        /*
1891          The cut generator has done its thing, and maybe it generated some
1892          cuts.  Do a bit of bookkeeping: load
1893          whichGenerator[i] with the index of the generator responsible for a cut,
1894          and place cuts flagged as global in the global cut pool for the model.
1895
1896          lastNumberCuts is the sum of cuts added in previous iterations; it's the
1897          offset to the proper starting position in whichGenerator.
1898        */
1899        int numberBefore =
1900            numberRowCutsBefore + numberColumnCutsBefore + lastNumberCuts ;
1901        int numberAfter =
1902            numberRowCutsAfter + numberColumnCutsAfter + lastNumberCuts ;
1903        // possibly extend whichGenerator
1904        resizeWhichGenerator(numberBefore, numberAfter);
1905
1906        for (j = numberRowCutsBefore; j < numberRowCutsAfter; j++) {
1907            whichGenerator_[numberBefore++] = i  ;
1908            const OsiRowCut * thisCut = theseCuts.rowCutPtr(j) ;
1909            if (thisCut->lb() > thisCut->ub())
1910                status = -1; // sub-problem is infeasible
1911            if (thisCut->globallyValid()) {
1912                // add to global list
1913                OsiRowCut newCut(*thisCut);
1914                newCut.setGloballyValid(true);
1915                newCut.mutableRow().setTestForDuplicateIndex(false);
1916                globalCuts_.addCutIfNotDuplicate(newCut) ;
1917            }
1918        }
1919        for (j = numberColumnCutsBefore; j < numberColumnCutsAfter; j++) {
1920            //whichGenerator_[numberBefore++] = i ;
1921            const OsiColCut * thisCut = theseCuts.colCutPtr(j) ;
1922            if (thisCut->globallyValid()) {
1923                // add to global list
1924                makeGlobalCut(thisCut);
1925            }
1926        }
1927    }
1928    // Add in any violated saved cuts
1929    if (!theseCuts.sizeRowCuts() && !theseCuts.sizeColCuts()) {
1930        int numberOld = theseCuts.sizeRowCuts() + lastNumberCuts;
1931        int numberCuts = slackCuts.sizeRowCuts() ;
1932        int i;
1933        // possibly extend whichGenerator
1934        resizeWhichGenerator(numberOld, numberOld + numberCuts);
1935        double primalTolerance;
1936        solver_->getDblParam(OsiPrimalTolerance, primalTolerance) ;
1937        for ( i = 0; i < numberCuts; i++) {
1938            const OsiRowCut * thisCut = slackCuts.rowCutPtr(i) ;
1939            if (thisCut->violated(cbcColSolution_) > 100.0*primalTolerance) {
1940                if (messageHandler()->logLevel() > 2)
1941                    printf("Old cut added - violation %g\n",
1942                           thisCut->violated(cbcColSolution_)) ;
1943                whichGenerator_[numberOld++] = 999;
1944                theseCuts.insert(*thisCut) ;
1945            }
1946        }
1947    }
1948    delete [] eachCuts;
1949    return status;
1950}
1951/*
1952  Locks a thread if parallel so that stuff like cut pool
1953  can be updated and/or used.
1954*/
1955void
1956CbcModel::lockThread()
1957{
1958    if (masterThread_ && (threadMode_&1) == 0)
1959        masterThread_->lockThread();
1960}
1961/*
1962  Unlocks a thread if parallel
1963*/
1964void
1965CbcModel::unlockThread()
1966{
1967    if (masterThread_ && (threadMode_&1) == 0)
1968        masterThread_->unlockThread();
1969}
1970// Returns true if locked
1971bool
1972CbcModel::isLocked() const
1973{
1974    if (masterThread_) {
1975        return (masterThread_->locked());
1976    } else {
1977        return true;
1978    }
1979}
1980// Stop a child
1981void
1982CbcModel::setInfoInChild(int type, CbcThread * info)
1983{
1984    if (type == -3) {
1985        // set up
1986        masterThread_ = info;
1987    } else if (type == -2) {
1988        numberThreads_ = 0; // signal to stop
1989    } else {
1990        // make sure message handler will be deleted
1991        defaultHandler_ = true;
1992        ownObjects_ = false;
1993        delete solverCharacteristics_;
1994        solverCharacteristics_ = NULL;
1995        if (type >= 0) {
1996            delete [] object_; // may be able to when all over to CbcThread
1997            for (int i = 0; i < numberCutGenerators_; i++) {
1998                delete generator_[i];
1999                generator_[i] = NULL;
2000                //delete virginGenerator_[i];
2001                //virginGenerator_[i]=NULL;
2002            }
2003            //generator_[0] = NULL;
2004            //delete [] generator_;
2005            //generator_ = NULL;
2006            numberCutGenerators_ = 0;
2007        } else {
2008            for (int i = 0; i < numberCutGenerators_; i++) {
2009                generator_[i] = NULL;
2010            }
2011        }
2012        object_ = NULL;
2013    }
2014}
2015
2016/// Indicates whether Cbc library has been compiled with multithreading support
2017bool CbcModel::haveMultiThreadSupport() { return true; }
2018
2019#else
2020// Default constructor
2021CbcBaseModel::CbcBaseModel() {}
2022
2023bool CbcModel::haveMultiThreadSupport() { return false; }
2024#endif
2025
Note: See TracBrowser for help on using the repository browser.