Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
P
preprocessor
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Normann Rion
preprocessor
Commits
9f96db89
Verified
Commit
9f96db89
authored
Oct 17, 2022
by
Sébastien Villemot
Browse files
Options
Downloads
Patches
Plain Diff
use_dll: ensure proper cleanup of thread workers threads in case of early exit (e.g. upon failure)
parent
781e10c2
Branches
Branches containing commit
No related tags found
No related merge requests found
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
src/DynareMain.cc
+4
-5
4 additions, 5 deletions
src/DynareMain.cc
src/ModelTree.cc
+39
-47
39 additions, 47 deletions
src/ModelTree.cc
src/ModelTree.hh
+3
-4
3 additions, 4 deletions
src/ModelTree.hh
with
46 additions
and
56 deletions
src/DynareMain.cc
+
4
−
5
View file @
9f96db89
...
...
@@ -535,12 +535,11 @@ main(int argc, char **argv)
nointeractive
,
config_file
,
check_model_changes
,
minimal_workspace
,
compute_xrefs
,
mexext
,
matlabroot
,
dynareroot
,
onlymodel
,
gui
,
notime
);
/* Ensures that the preprocessor final message is printed after the end of
compilation (and is not printed in case of compilation failure); also
avoids potential issues with destroying the thread synchronization
mechanism too soon. */
/* Ensures that workers are not destroyed before they finish compiling.
Also ensures that the preprocessor final message is printed after the end of
compilation (and is not printed in case of compilation failure). */
if
(
mod_file
->
use_dll
)
ModelTree
::
terminate
MEXCompilationWorkers
();
ModelTree
::
waitFor
MEXCompilationWorkers
();
cout
<<
"Preprocessing completed."
<<
endl
;
return
EXIT_SUCCESS
;
...
...
This diff is collapsed.
Click to expand it.
src/ModelTree.cc
+
39
−
47
View file @
9f96db89
...
...
@@ -37,11 +37,15 @@
#include
<utility>
#include
<algorithm>
vector
<
jthread
>
ModelTree
::
mex_compilation_workers
{};
condition_variable
ModelTree
::
mex_compilation_cv
;
/* NB: The workers must be listed *after* all the other static variables
related to MEX compilation, so that when the preprocessor exits, the workers
are destroyed *before* those variables (since the former rely on the latter
for their functioning). */
condition_variable_any
ModelTree
::
mex_compilation_cv
;
mutex
ModelTree
::
mex_compilation_mut
;
vector
<
tuple
<
filesystem
::
path
,
set
<
filesystem
::
path
>
,
string
>>
ModelTree
::
mex_compilation_queue
;
set
<
filesystem
::
path
>
ModelTree
::
mex_compilation_done
;
vector
<
jthread
>
ModelTree
::
mex_compilation_workers
;
void
ModelTree
::
copyHelper
(
const
ModelTree
&
m
)
...
...
@@ -1892,19 +1896,31 @@ ModelTree::initializeMEXCompilationWorkers(int numworkers)
mex_compilation_workers
.
emplace_back
([](
stop_token
stoken
)
{
unique_lock
<
mutex
>
lk
{
mex_compilation_mut
};
filesystem
::
path
output
;
string
cmd
;
look_for_job
:
for
(
auto
it
{
mex_compilation_queue
.
begin
()};
it
!=
mex_compilation_queue
.
end
();
++
it
)
/* Look for an object to compile, whose prerequisites are already
compiled. If found, remove it from the queue, save the output path and
the compilation command, and return true. Must be run under the lock. */
auto
pick_job
=
[
&
cmd
,
&
output
]
{
/* The following is a copy and not a reference, because we need it
after erasing it, and also after releasing the lock (at which
point the mex_compilation_queue may be modified by others). */
const
auto
[
output
,
prerequisites
,
cmd
]
{
*
it
};
if
(
includes
(
mex_compilation_done
.
begin
(),
mex_compilation_done
.
end
(),
for
(
auto
it
{
mex_compilation_queue
.
begin
()};
it
!=
mex_compilation_queue
.
end
();
++
it
)
if
(
const
auto
&
prerequisites
{
get
<
1
>
(
*
it
)};
// Will become dangling after erase
includes
(
mex_compilation_done
.
begin
(),
mex_compilation_done
.
end
(),
prerequisites
.
begin
(),
prerequisites
.
end
()))
{
output
=
get
<
0
>
(
*
it
);
cmd
=
get
<
2
>
(
*
it
);
mex_compilation_queue
.
erase
(
it
);
lk
.
unlock
();
// After that point, the iterator may become invalid
return
true
;
}
return
false
;
};
while
(
!
stoken
.
stop_requested
())
if
(
mex_compilation_cv
.
wait
(
lk
,
stoken
,
pick_job
))
{
lk
.
unlock
();
if
(
system
(
cmd
.
c_str
()))
{
cerr
<<
"Compilation failed"
<<
endl
;
...
...
@@ -1915,41 +1931,17 @@ ModelTree::initializeMEXCompilationWorkers(int numworkers)
/* The object just compiled may be a prerequisite for several
other objects, so notify all waiting workers. Also needed to
notify the main thread when in
ModelTree::
terminate
MEXCompilationWorkers().
*/
ModelTree::
waitFor
MEXCompilationWorkers().*/
mex_compilation_cv
.
notify_all
();
goto
look_for_job
;
}
}
if
(
stoken
.
stop_requested
())
return
;
mex_compilation_cv
.
wait
(
lk
);
goto
look_for_job
;
});
}
void
ModelTree
::
terminate
MEXCompilationWorkers
()
ModelTree
::
waitFor
MEXCompilationWorkers
()
{
// Wait until the queue is empty
unique_lock
<
mutex
>
lk
{
mex_compilation_mut
};
mex_compilation_cv
.
wait
(
lk
,
[]
{
return
mex_compilation_queue
.
empty
();
});
/* Request stop while still holding the lock, so we are sure that workers are
either compiling or waiting right now. Otherwise there could theoretically
be a race condition where the condition variable is notified just after
the thread has checked for its stoken, and just before it begins waiting;
this would be deadlock. */
for
(
auto
&
it
:
mex_compilation_workers
)
it
.
request_stop
();
lk
.
unlock
();
mex_compilation_cv
.
notify_all
();
for
(
auto
&
it
:
mex_compilation_workers
)
it
.
join
();
}
void
...
...
This diff is collapsed.
Click to expand it.
src/ModelTree.hh
+
3
−
4
View file @
9f96db89
...
...
@@ -345,7 +345,7 @@ private:
/* The following variables implement the thread synchronization mechanism for
limiting the number of concurrent GCC processes and tracking dependencies
between object files. */
static
condition_variable
mex_compilation_cv
;
static
condition_variable
_any
mex_compilation_cv
;
static
mutex
mex_compilation_mut
;
/* Object/MEX files waiting to be compiled (with their prerequisites as 2nd
element and compilation command as the 3rd element) */
...
...
@@ -557,9 +557,8 @@ public:
// Initialize the MEX compilation workers
static
void
initializeMEXCompilationWorkers
(
int
numworkers
);
/* Terminates all MEX compilation workers (after they have emptied the
waiting queue) */
static
void
terminateMEXCompilationWorkers
();
// Waits until the MEX compilation queue is empty
static
void
waitForMEXCompilationWorkers
();
//! Returns all the equation tags associated to an equation
map
<
string
,
string
>
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment