38#include "s57class_registrar.h"
44constexpr int kThreadWaitSeconds = 5;
50SENCJobTicket::SENCJobTicket() {
52 m_SENCResult = SENC_BUILD_INACTIVE;
53 m_status = THREAD_INACTIVE;
54 m_completion_posted =
false;
62OCPN_BUILDSENC_ThreadEvent::OCPN_BUILDSENC_ThreadEvent(wxEventType commandType,
64 : wxEvent(id, commandType) {
69OCPN_BUILDSENC_ThreadEvent::~OCPN_BUILDSENC_ThreadEvent() {}
71wxEvent *OCPN_BUILDSENC_ThreadEvent::Clone()
const {
73 newevent->stat = this->stat;
74 newevent->type = this->type;
75 newevent->m_ticket = this->m_ticket;
83SENCThreadManager::SENCThreadManager() : m_shutting_down(false) {
84 int nCPU = wxMax(1, wxThread::GetCPUCount());
85 if (g_nCPUCount > 0) nCPU = g_nCPUCount;
87 if (nCPU < 1) nCPU = 1;
89 m_max_jobs = wxMax(nCPU - 1, 1);
91 wxLogDebug(
"SENC: nCPU: %d m_max_jobs :%d\n", nCPU, m_max_jobs);
95 (wxObjectEventFunction)(wxEventFunction)&SENCThreadManager::OnEvtThread);
98SENCThreadManager::~SENCThreadManager() { ClearJobList(); }
100bool SENCThreadManager::IsShuttingDown()
const {
return m_shutting_down; }
102int SENCThreadManager::GetRunningJobCount() {
103 wxCriticalSectionLocker lock(m_list_mutex);
106 if (ticket->m_status == THREAD_STARTED) nRunning++;
111void SENCThreadManager::UpdateAlertString() {
115 wxCriticalSectionLocker lock(m_list_mutex);
116 jobCount = ticket_list.size();
118 if (ticket->m_status == THREAD_STARTED) nRunning++;
122 if (
auto tfPtr = top_frame::Get()) {
125 count.Printf(
" %ld",
static_cast<long>(jobCount));
126 tfPtr->SetAlertString(_(
"Preparing vector chart ") + count);
128 tfPtr->SetAlertString(
"");
133void SENCThreadManager::ClearJobList() {
134 m_shutting_down =
true;
136 wxDateTime end = wxDateTime::Now();
137 end.Add(wxTimeSpan::Seconds(kThreadWaitSeconds));
139 while (wxDateTime::Now() < end && GetRunningJobCount() > 0) {
144 std::vector<SENCJobTicket *> tickets_to_delete;
146 wxCriticalSectionLocker lock(m_list_mutex);
147 auto collect = [&](std::vector<SENCJobTicket *> &list) {
148 for (
SENCJobTicket *ticket : list) tickets_to_delete.push_back(ticket);
151 collect(ticket_list);
152 collect(completing_list);
155 for (
SENCJobTicket *ticket : tickets_to_delete) delete ticket;
158SENCThreadStatus SENCThreadManager::ScheduleJob(
SENCJobTicket *ticket) {
159 if (m_shutting_down)
return THREAD_INACTIVE;
162 wxCriticalSectionLocker lock(m_list_mutex);
165 if (queued->m_FullPath000 == ticket->m_FullPath000)
return THREAD_PENDING;
168 ticket->m_status = THREAD_PENDING;
169 ticket->m_completion_posted =
false;
170 ticket_list.push_back(ticket);
174 return THREAD_PENDING;
177void SENCThreadManager::StartTopJob() {
178 if (m_shutting_down)
return;
180 bool started_job =
false;
185 wxCriticalSectionLocker lock(m_list_mutex);
189 if (ticket->m_status == THREAD_STARTED) nRunning++;
192 if (nRunning >= m_max_jobs)
break;
196 if (ticket->m_status == THREAD_PENDING) {
197 startCandidate = ticket;
202 if (!startCandidate)
break;
205 startCandidate->m_status = THREAD_STARTED;
206 thread->SetPriority(20);
207 if (thread->Run() != wxTHREAD_NO_ERROR) {
208 startCandidate->m_status = THREAD_PENDING;
215 }
while (started_job);
222 wxCriticalSectionLocker lock(m_list_mutex);
224 for (
size_t i = 0; i < ticket_list.size(); i++) {
225 if (ticket_list[i] == ticket) {
226 ticket->m_status = THREAD_FINISHED;
227 completing_list.push_back(ticket);
228 ticket_list.erase(ticket_list.begin() + i);
237int SENCThreadManager::GetJobCount() {
238 wxCriticalSectionLocker lock(m_list_mutex);
239 return static_cast<int>(ticket_list.size());
242bool SENCThreadManager::IsChartInTicketlist(
s57chart *chart) {
243 wxCriticalSectionLocker lock(m_list_mutex);
245 if (ticket->m_chart == chart)
return true;
248 if (ticket->m_chart == chart)
return true;
253bool SENCThreadManager::SetChartPointer(
s57chart *chart,
void *new_ptr) {
254 wxCriticalSectionLocker lock(m_list_mutex);
255 auto update = [&](std::vector<SENCJobTicket *> &list) {
257 if (ticket->m_chart == chart) {
258 ticket->m_chart =
static_cast<s57chart *
>(new_ptr);
265 if (update(ticket_list))
return true;
266 return update(completing_list);
269void SENCThreadManager::InvalidateChartPointer(
s57chart *chart) {
270 SetChartPointer(chart,
nullptr);
273void SENCThreadManager::ReleaseCompletedTicket(
SENCJobTicket *ticket) {
274 wxCriticalSectionLocker lock(m_list_mutex);
275 for (
size_t i = 0; i < completing_list.size(); i++) {
276 if (completing_list[i] == ticket) {
277 completing_list.erase(completing_list.begin() + i);
284 if (!top_frame::Get())
return;
287 frame_event.stat =
event.stat;
288 frame_event.type =
event.type;
289 frame_event.m_ticket =
event.m_ticket;
290 top_frame::Get()->GetEventHandler()->AddPendingEvent(frame_event);
294 switch (event.type) {
295 case SENC_BUILD_DONE_NOERROR:
296 case SENC_BUILD_DONE_ERROR:
297 FinishJob(event.m_ticket);
312 : wxThread(wxTHREAD_DETACHED), m_manager(manager), m_ticket(ticket) {
313 m_FullPath000 = ticket->m_FullPath000;
314 m_SENCFileName = ticket->m_SENCFileName;
318void *SENCBuildThread::Entry() {
319 EVENTSENCResult result = SENC_BUILD_DONE_ERROR;
322 if (!m_manager || m_manager->IsShuttingDown())
return nullptr;
327 senc.setRegistrar(g_poRegistrar);
328 senc.setRefLocn(m_ticket->ref_lat, m_ticket->ref_lon);
329 senc.SetLODMeters(m_ticket->m_LOD_meters);
330 senc.setNoErrDialog(
true);
332 m_ticket->m_SENCResult = SENC_BUILD_STARTED;
334 stat = senc.createSenc200(m_FullPath000, m_SENCFileName,
false);
335 result = (stat == ERROR_INGESTING000) ? SENC_BUILD_DONE_ERROR
336 : SENC_BUILD_DONE_NOERROR;
337 }
catch (
const std::exception &e) {
338 wxLogMessage(
"SENC build thread exception: %s", e.what());
339 result = SENC_BUILD_DONE_ERROR;
344 if (!m_manager || m_manager->IsShuttingDown() ||
345 m_ticket->m_completion_posted)
348 m_ticket->m_completion_posted =
true;
349 m_ticket->m_SENCResult = result;
354 event.m_ticket = m_ticket;
355 m_manager->QueueEvent(event.Clone());
General chart base definitions.
Generic Chart canvas base.
Manager for S57 chart SENC creation threads.
Represents an S57 format electronic navigational chart in OpenCPN.
Global variables stored in configuration file.
const wxEventType wxEVT_OCPN_BUILDSENCTHREAD
Global instance.
SENCThreadManager * g_SencThreadManager
Global instance.
const wxEventType wxEVT_OCPN_BUILDSENCTHREAD
Global instance.
Abstract gFrame/MyFrame interface.