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

NREL / SolTrace / 21046664913

15 Jan 2026 09:17PM UTC coverage: 87.999% (+0.2%) from 87.815%
21046664913

Pull #96

github

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

605 of 797 new or added lines in 17 files covered. (75.91%)

14 existing lines in 7 files now uncovered.

6255 of 7108 relevant lines covered (88.0%)

7221404.67 hits per line

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

88.1
/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
        std::lock_guard<std::mutex> lk(this->progress_mutex);
31✔
30
        this->progress[id] = 0.0;
31✔
31
        return id;
31✔
32
    }
31✔
33

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

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

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

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

94
        return sts;
28✔
95
    }
96

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

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

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

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

139
        return sts;
4✔
140
    }
141

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

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

165
} // 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