• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

NREL / SolTrace / 21012157876

14 Jan 2026 10:28PM UTC coverage: 87.988% (+0.2%) from 87.815%
21012157876

Pull #96

github

web-flow
Merge e4465f26c into e78d2bfb0
Pull Request #96: 95 implement embree runner

590 of 781 new or added lines in 17 files covered. (75.54%)

14 existing lines in 7 files now uncovered.

6248 of 7101 relevant lines covered (87.99%)

7196132.48 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.8
/coretrace/simulation_runner/native_runner/thread_manager.cpp
1
#include "thread_manager.hpp"
2

3
#include <chrono>
4
#include <future>
5
#include <sstream>
6
#include <thread>
7

8
namespace SolTrace::NativeRunner
9
{
10

11
    ThreadManager::ThreadManager(trace_logger_ptr log) : logger(log)
29✔
12
    {
13
        this->initialize();
29✔
14
        return;
29✔
15
    }
×
16

17
    ThreadManager::~ThreadManager()
29✔
18
    {
19
        this->threads.clear();
29✔
20
        this->progress.clear();
29✔
21
        return;
29✔
22
    }
29✔
23

24
    unsigned int ThreadManager::manage(unsigned int id, future f)
31✔
25
    {
26
        assert(this->threads.find(id) == this->threads.end());
31✔
27

28
        this->threads[id] = std::move(f);
31✔
29
        this->progress[id] = 0.0;
31✔
30
        return id;
31✔
31
    }
32

33
    ThreadManager::ThreadStatus ThreadManager::monitor_until_completion()
28✔
34
    {
35
        ThreadStatus sts = ThreadStatus::SUCCESS;
28✔
36
        bool canceled = false;
28✔
37

38
        while (!this->threads.empty())
7,223✔
39
        {
40
            auto iter = this->threads.begin();
7,195✔
41
            while (iter != this->threads.end())
14,434✔
42
            {
43
                if (iter->second.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
7,239✔
44
                {
45
                    ThreadStatus thread_status = iter->second.get();
31✔
46
                    if (thread_status == ThreadStatus::SUCCESS)
31✔
47
                    {
48
                        ; // Intentional no-op
49
                    }
50
                    else if (thread_status == ThreadStatus::ERROR)
5✔
51
                    {
52
                        // Something went wrong -- shut everything down
53
                        this->cancel();
1✔
54
                        // Return ERROR status
55
                        sts = ThreadStatus::ERROR;
1✔
56
                        canceled = true;
1✔
57
                    }
58
                    else if (thread_status == ThreadStatus::CANCEL)
4✔
59
                    {
60
                        // Return CANCEL if threads were canceled
61
                        // by an external call to cancel()
62
                        sts = canceled ? sts : thread_status;
4✔
63
                    }
64
                    else
65
                    {
66
                        // Thread terminated with something other than
67
                        // SUCCESS, ERROR, or CANCEL. This is unexpected.
68
                        std::stringstream ss;
×
69
                        ss << "Thread " << iter->first
×
70
                           << " returned status "
71
                           << status_string(thread_status)
×
72
                           << ". This is an error.";
×
NEW
73
                        this->logger->error_log(ss.str());
×
74

75
                        // Unexpected behavior so we terminate
76
                        this->cancel();
×
77
                        sts = ThreadStatus::ERROR;
×
78
                        canceled = true;
×
79
                    }
×
80
                    // Task is complete so we stop tracking it.
81
                    // Also increments to the next spot
82
                    iter = this->threads.erase(iter);
31✔
83
                }
84
                else
85
                {
86
                    ++iter;
7,208✔
87
                }
88
            }
89

90
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
7,195✔
91
        }
92

93
        return sts;
28✔
94
    }
95

96
    void ThreadManager::progress_update(unsigned int id, double prog)
11,775✔
97
    {
98
        // std::cout << "Update from thread " << id << " reporting "
99
        //           << prog << " complete." << std::endl;
100
        std::lock_guard<std::mutex> lk(this->progress_mutex);
11,775✔
101
        this->progress[id] = prog;
11,775✔
102
        return;
23,550✔
103
    }
11,775✔
104

105
    bool ThreadManager::terminate(unsigned int id)
11,775✔
106
    {
107
        std::lock_guard<std::mutex> lk(this->state_mutex);
11,775✔
108
        return this->state != ThreadStatus::RUNNING;
11,775✔
109
    }
11,775✔
110

111
    ThreadManager::ThreadStatus ThreadManager::status(double *progress) const
4✔
112
    {
113
        ThreadStatus sts = ThreadStatus::ERROR;
4✔
114
        // Create isolated scope for lock guard
115
        {
116
            std::lock_guard<std::mutex> lk(this->state_mutex);
4✔
117
            sts = this->state;
4✔
118
        }
4✔
119

120
        if (progress != nullptr)
4✔
121
        {
122
            int k = 0;
2✔
123
            double avg = 0.0;
2✔
124
            std::lock_guard<std::mutex> lk(this->progress_mutex);
2✔
125
            for (auto it = this->progress.cbegin();
2✔
126
                 it != this->progress.cend();
5✔
127
                 ++it)
3✔
128
            {
129
                // std::cout << "Thread " << k
130
                //           << " progress " << it->second
131
                //           << std::endl;
132
                ++k;
3✔
133
                avg += (it->second - avg) / k;
3✔
134
            }
135
            *progress = avg;
2✔
136
        }
2✔
137

138
        return sts;
4✔
139
    }
140

141
    void ThreadManager::cancel() const
3✔
142
    {
143
        std::lock_guard<std::mutex> lk(this->state_mutex);
3✔
144
        this->state = ThreadStatus::CANCEL;
3✔
145
        return;
6✔
146
    }
3✔
147

148
    void ThreadManager::initialize()
32✔
149
    {
150
        // Must call prior to manage and not while running!!
151
        // this->next_id = 0;
152
        {
153
            std::lock_guard<std::mutex> lk(this->state_mutex);
32✔
154
            this->state = ThreadStatus::RUNNING;
32✔
155
        }
32✔
156
        {
157
            std::lock_guard<std::mutex> lk(this->progress_mutex);
32✔
158
            this->progress.clear();
32✔
159
            this->threads.clear();
32✔
160
        }
32✔
161
        return;
32✔
162
    }
163

164
} // namespace SolTrace::NativeRunner
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc