gcc seems to be getting smarter all the time. Sentience soon…?

/home/m/development/thedigitalage/AbetterTrader/server/src/TradingModel.cpp:2095:33: note: suggested alternative: ‘ba_’
ss << "WTF account " << pa_->strDesc_ << " sr " << db_id_ << " gain: " ^~~ ba_

After seeing this little gem on the xunitpatterns site:

(We are running all the tests before every check-in, aren’t we?)

I was glad that I baked my tests into the startup of A better Trader. As I build and run while coding, I’m constantly running my regression tests. Steady on.

Sometimes you just gotta stop and have a bump…

WOW major virtualbox shenanigans
i seem to have broken my good boxes with something from this list:
1) upgraded ubuntu to 18.04
2) kept compton but it is not needed now that we have wayland compositor
3) installed virtualbox* packages to try to fix clock
after I uninstalled virtualbox and compton, ONE of them came back to life (but not the other)
the other is having ssh problems of some kind that cause immediate systemd problems

while investigating, we got LOTS of good progress on setup_linux.sh KEEP GOING

MOVE ON

This is a sweet spot of thread functionality for me at the moment, mixing boost and c++11, so I’m throwing it down here.  It’s also in my Reusable code on git.

// --------------------------------------------------------------------
// CONCISE EXAMPLE OF THREAD WITH EXTERNALLY-ACCESSIBLE STATUS AND DATA
// --------------------------------------------------------------------
// We create a vector, and create a thread to start stuffing it.
// Externally, we can check the status of the job, and have mutex access to the data.
// The atomic job stage is SO CHEAP to change and check, do it all day long as needed.
// Initially, externally, we check the job stage.
// Meanwhile, we do a bunch of intense work inside the mutex.
// Then we do smaller work with frequent mutexing, allowing interruption.
// Great patterns, use them brother!
// Hells to the yeah.
// --------------------------------------------------------------------
std::atomic<int32_t> job_stage(0);
std::unordered_set<int> data;
boost::shared_mutex data_guard;
data.insert(-1);
std::thread t([&job_stage,&data,&data_guard] {
    // stage 1 = jam in data
    job_stage = 1;
    {
        boost::upgrade_lock<boost::shared_mutex> lock(data_guard);
        boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock);
        for (int loop = 0; loop < 2000; ++loop)
        {
            std::this_thread::sleep_for(1ms);
            data.insert(loop);
        }
    }
    // stage 2 = mutex-jam data, allowing intervention
    job_stage = 2;
    for (int loop = 3000000; loop < 4000000 && job_stage == 2; ++loop)
    {
        boost::upgrade_lock<boost::shared_mutex> lock(data_guard);
        boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock);
        data.insert(loop);
    }
    cout << "thread exiting..." << endl;
});

cout << "pre mutex job stage: " << job_stage << endl;

for (int check = 0; check < 5; ++check)
{
    std::this_thread::sleep_for(200ms);
    // not sure why i was getting std::hex output...
    cout << "check " << check << " job stage: ";
    {
        boost::upgrade_lock<boost::shared_mutex> lock(data_guard);
        cout  << dec << job_stage << " data size " << data.size();
    }
    cout << endl;
}

// We can trigger the thread to exit.
job_stage = 3;

// Let's see what happens if we don't join until after the thread is done.
std::this_thread::sleep_for(300ms);
cout << "done sleeping" << endl;

// NOW we will block to ensure the thread finishes.
cout << "joining" << endl;
t.join();
cout << "all done" << endl;
// --------------------------------------------------------------------

Output:

pre mutex job stage: 1
check 0 job stage: 2 data size 2031
check 1 job stage: 2 data size 225848
check 2 job stage: 2 data size 456199
check 3 job stage: 2 data size 726576
check 4 job stage: 2 data size 936429
thread exiting...
check 5 job stage: 2 data size 1002001
done sleeping
joining
all done