Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
ArcaneMain.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* ArcaneMain.cc (C) 2000-2026 */
9/* */
10/* Execution management class. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/impl/ArcaneMain.h"
15
16#include "arcane/utils/Iostream.h"
17#include "arcane/utils/List.h"
18#include "arcane/utils/Iterator.h"
19#include "arcane/utils/ScopedPtr.h"
20#include "arcane/utils/PlatformUtils.h"
21#include "arcane/utils/FatalErrorException.h"
22#include "arcane/utils/ParallelFatalErrorException.h"
23#include "arcane/utils/OStringStream.h"
24#include "arcane/utils/ApplicationInfo.h"
25#include "arcane/utils/ValueConvert.h"
26#include "arcane/utils/ITraceMng.h"
27#include "arcane/utils/SignalException.h"
28#include "arcane/utils/TimeoutException.h"
29#include "arcane/utils/ArithmeticException.h"
30#include "arcane/utils/StringBuilder.h"
31#include "arccore/base/internal/IDynamicLibraryLoader.h"
32#include "arcane/utils/CheckedConvert.h"
33#include "arcane/utils/CommandLineArguments.h"
34#include "arcane/utils/TestLogger.h"
36
37#include "arccore/base/internal/ConvertInternal.h"
39#include "arccore/common/internal/MemoryUtilsInternal.h"
40#include "arccore/common/accelerator/internal/RuntimeLoader.h"
41
42#include "arcane/core/IMainFactory.h"
43#include "arcane/core/IApplication.h"
44#include "arcane/core/IServiceLoader.h"
45#include "arcane/core/IParallelMng.h"
46#include "arcane/core/IParallelSuperMng.h"
47#include "arcane/core/ISession.h"
48#include "arcane/core/VariableRef.h"
49#include "arcane/core/ItemTypeMng.h"
50#include "arcane/core/ServiceUtils.h"
51#include "arcane/core/CaseOptions.h"
52#include "arcane/core/ItemGroupImpl.h"
53#include "arcane/core/DotNetRuntimeInitialisationInfo.h"
54#include "arcane/core/AcceleratorRuntimeInitialisationInfo.h"
55#include "arcane/core/ApplicationBuildInfo.h"
56
57#include "arcane/core/IServiceFactory.h"
58#include "arcane/core/IModuleFactory.h"
59
60#include "arcane/impl/MainFactory.h"
61#include "arcane/impl/InternalInfosDumper.h"
62#include "arcane/impl/internal/ArcaneMainExecInfo.h"
63#include "arcane/impl/internal/ThreadBindingMng.h"
64
65#include "arccore/common/accelerator/internal/RegisterRuntimeInfo.h"
66
67#include "arcane_internal_config.h"
68
69#include <signal.h>
70#include <exception>
71#ifndef ARCANE_OS_WIN32
72#include <unistd.h>
73#include <sys/stat.h>
74#include <fcntl.h>
75#endif
76
77#include <set>
78#include <map>
79#include <chrono>
80
81#ifdef ARCANE_FLEXLM
82#include "arcane/impl/FlexLMTools.h"
83#endif
84
85/*---------------------------------------------------------------------------*/
86/*---------------------------------------------------------------------------*/
87
88namespace Arcane
89{
91{
92 public:
93
94 List<IServiceFactoryInfo*> m_service_factory_infos;
95 List<IModuleFactoryInfo*> m_module_factory_infos;
96 List<IApplicationBuildInfoVisitor*> m_application_build_info_visitors;
97 ApplicationBuildInfo m_app_build_info;
98 DotNetRuntimeInitialisationInfo m_dotnet_init_info;
99 AcceleratorRuntimeInitialisationInfo m_accelerator_init_info;
100 bool m_has_dotnet_wrapper = false;
101 String m_dotnet_assembly;
102 String m_arcane_lib_path;
103 IDirectSubDomainExecuteFunctor* m_direct_exec_functor = nullptr;
105 std::atomic<Int32> m_nb_autodetect = 0;
110};
111} // namespace Arcane
112
113namespace
114{
115Arcane::ArcaneMainStaticInfo* global_static_info = nullptr;
116Arcane::ArcaneMainStaticInfo* _staticInfo()
117{
118 // TODO: see if it needs to be protected in multi-threading.
119 if (!global_static_info)
120 global_static_info = new Arcane::ArcaneMainStaticInfo();
121 return global_static_info;
122}
123void _deleteStaticInfo()
124{
125 delete global_static_info;
126 global_static_info = nullptr;
127}
128} // namespace
129
130/*---------------------------------------------------------------------------*/
131/*---------------------------------------------------------------------------*/
132
133extern "C" void arcaneEndProgram()
134{
135 // Just for a third entry point.
136}
137
138/*---------------------------------------------------------------------------*/
139/*---------------------------------------------------------------------------*/
140
141extern "C" {
142typedef void (*fSignalFunc)(int);
143void arcaneSignalHandler(int);
144}
145
146/*---------------------------------------------------------------------------*/
147/*---------------------------------------------------------------------------*/
148
149namespace Arcane
150{
151
152/*---------------------------------------------------------------------------*/
153/*---------------------------------------------------------------------------*/
154
155extern "C++" ARCANE_UTILS_EXPORT void
156arcaneRedirectSignals(fSignalFunc sig_func);
157
158extern "C++" ARCANE_UTILS_EXPORT void
159arcaneCallDefaultSignal(int val);
160
161extern "C++" ARCANE_UTILS_EXPORT void
162initializeStringConverter();
163
164extern "C++" ARCANE_IMPL_EXPORT IArcaneMain*
165createArcaneMainBatch(const ApplicationInfo& exe_info, IMainFactory*);
166
167extern "C++" ARCANE_IMPL_EXPORT ICodeService*
168createArcaneCodeService(IApplication* app);
169
170extern "C++" ARCCORE_COMMON_EXPORT void
171arccorePrintSpecificMemoryStats();
172
173std::atomic<Int32> ArcaneMain::m_nb_arcane_init(0);
174std::atomic<Int32> ArcaneMain::m_is_init_done(0);
175bool ArcaneMain::m_has_garbage_collector = false;
176bool ArcaneMain::m_is_master_io = true;
177bool ArcaneMain::m_is_use_test_logger = false;
178
179/*---------------------------------------------------------------------------*/
180/*---------------------------------------------------------------------------*/
181
183: public MainFactory
184{
185 public:
186
188 {
189 return createArcaneMainBatch(app_info, this);
190 }
191};
192
193/*---------------------------------------------------------------------------*/
194/*---------------------------------------------------------------------------*/
195
197{
198 public:
199
200 explicit Impl(const ApplicationInfo& infos)
201 : m_app_info(infos)
202 , m_application_build_info(ArcaneMain::defaultApplicationBuildInfo())
205 {}
206 Impl(const ApplicationInfo& infos, const ApplicationBuildInfo& build_infos,
207 const DotNetRuntimeInitialisationInfo& dotnet_info,
208 const AcceleratorRuntimeInitialisationInfo& accelerator_info)
209 : m_app_info(infos)
210 , m_application_build_info(build_infos)
211 , m_dotnet_info(dotnet_info)
212 , m_accelerator_info(accelerator_info)
213 {}
214
215 public:
216
217 ApplicationInfo m_app_info;
218 ApplicationBuildInfo m_application_build_info;
220 AcceleratorRuntimeInitialisationInfo m_accelerator_info;
221 ThreadBindingMng m_thread_binding_mng;
222};
223
224/*---------------------------------------------------------------------------*/
225/*---------------------------------------------------------------------------*/
226
227/*---------------------------------------------------------------------------*/
228/*---------------------------------------------------------------------------*/
229
230void ArcaneMain::
231redirectSignals()
232{
233 bool redirect_signals = true;
234 String rv = platform::getEnvironmentVariable("ARCANE_REDIRECT_SIGNALS");
235 (void)builtInGetValue(redirect_signals, rv);
236 if (redirect_signals) {
237 arcaneRedirectSignals(arcaneSignalHandler);
238 }
239}
240
241/*---------------------------------------------------------------------------*/
242/*---------------------------------------------------------------------------*/
243
244void ArcaneMain::
245setUseTestLogger(bool v)
246{
247 m_is_use_test_logger = v;
248}
249
250/*---------------------------------------------------------------------------*/
251/*---------------------------------------------------------------------------*/
252
255{
256 m_default_main_factory = mf;
257}
258
259/*---------------------------------------------------------------------------*/
260/*---------------------------------------------------------------------------*/
261
262class ArcaneMainExecFunctor
263: public IFunctor
264{
265 public:
266
267 ArcaneMainExecFunctor(const ApplicationInfo& app_info, IArcaneMain* exec_main)
268 : m_app_info(app_info)
269 , m_exec_main(exec_main)
270 {
271 }
272
273 public:
274
275 void executeFunctor() override
276 {
277 StringList args;
278 m_app_info.args(args);
279 if (!m_exec_main->parseArgs(args))
280 m_exec_main->execute();
281 }
282
283 private:
284
285 const ApplicationInfo& m_app_info;
286 IArcaneMain* m_exec_main;
287};
288
289/*---------------------------------------------------------------------------*/
290/*---------------------------------------------------------------------------*/
291
299{
300 public:
301
302 Int32 check()
303 {
304 auto* x = _staticInfo();
305 if (x->m_nb_autodetect > 0)
306 return x->m_autodetect_return_value;
307
308 ArcaneMain::_setArcaneLibraryPath();
309
310 std::chrono::high_resolution_clock clock;
311
312 // TODO: make thread-safe
313 {
314 ArcaneMain::_checkAutoDetectMPI();
315
316 bool has_accelerator = false;
317 // Measures the initialization time.
318 // Since Arcane has not been initialized yet, methods from the 'platform' namespace
319 // should not be used here.
320 auto start_time = clock.now();
321 x->m_autodetect_return_value = ArcaneMain::_checkAutoDetectAccelerator(has_accelerator);
322 auto end_time = clock.now();
323 // Only retrieve the time if an accelerator was used
324 if (has_accelerator)
325 x->m_init_time_accelerator = _getTime(end_time, start_time);
326 ++x->m_nb_autodetect;
327 }
328 return x->m_autodetect_return_value;
329 }
330
331 template <typename TimeType>
332 Real _getTime(TimeType end_time, TimeType start_time)
333 {
334 auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time);
335 Real x = static_cast<Real>(duration.count());
336 return x / 1.0e9;
337 }
338};
339
340/*---------------------------------------------------------------------------*/
341/*---------------------------------------------------------------------------*/
342
354{
355 if (m_exec_main)
356 return 0;
357
358 m_ret_val = 0;
359 m_clean_abort = false;
360
361 ArcaneMain::redirectSignals();
362
363 // Creation of the execution class
364 try {
365 if (m_has_build_info) {
366 ArcaneMain* x = new ArcaneMain(m_app_info, m_main_factory,
367 m_application_build_info,
370 m_exec_main = x;
371 }
372 else {
373 m_exec_main = m_main_factory->createArcaneMain(m_app_info);
374 }
375 m_exec_main->build();
376 ArcaneMain::m_is_master_io = m_exec_main->application()->parallelSuperMng()->isMasterIO();
377 m_exec_main->initialize();
378 IArcaneMain::setArcaneMain(m_exec_main);
379 }
380 catch (const ArithmeticException& ex) {
381 cerr << "** CATCH ARITHMETIC_EXCEPTION\n";
382 return ExceptionUtils::print(ex, nullptr);
383 }
384 catch (const Exception& ex) {
385 return ExceptionUtils::print(ex, nullptr);
386 }
387 catch (const std::exception& ex) {
388 return ExceptionUtils::print(ex, nullptr);
389 }
390 catch (...) {
391 return ExceptionUtils::print(nullptr);
392 }
393
394 // Redirects signals again because certain
395 // initialization routines (for example MPI) may
396 // divert them.
397 ArcaneMain::redirectSignals();
398
399 m_ret_val = 0;
400 m_clean_abort = false;
401
402#ifdef ARCANE_FLEXLM
403 try {
404 IApplication* app = m_exec_main->application();
405 ITraceMng* trace = app->traceMng();
406 IParallelSuperMng* parallel_super_mng = app->parallelSuperMng();
407 trace->info() << "Initializing license manager";
408 FlexLMMng::instance()->init(parallel_super_mng);
409
410 // The parallel license policy is delegated to the applications
411 // bool is_parallel = parallel_super_mng->isParallel();
412 // FlexLMTools<ArcaneFeatureModel> license_tool;
413 // Integer commSize = parallel_super_mng->commSize();
414 // if (is_parallel && commSize > 1)
415 // { // The parallel feature is only activated if necessary
416 // license_tool.getLicense(ArcaneFeatureModel::ArcaneParallel,commSize);
417 // }
418 }
419 catch (const Exception& ex) {
420 IApplication* app = m_exec_main->application();
421 ITraceMng* trace = app->traceMng();
422 m_ret_val = arcanePrintArcaneException(ex, trace);
423 if (ex.isCollective()) {
424 m_clean_abort = true;
425 }
426 }
427#endif
428 return 0;
429}
430
431/*---------------------------------------------------------------------------*/
432/*---------------------------------------------------------------------------*/
433
434// NOTE: This method must not throw exceptions
435void ArcaneMainExecInfo::
436execute()
437{
438 if (m_ret_val != 0)
439 return;
440
441 if (m_direct_exec_functor)
442 m_exec_main->setDirectExecuteFunctor(m_direct_exec_functor);
443
444 ArcaneMainExecFunctor exec_functor(m_app_info, m_exec_main);
445 if (ArcaneMain::m_exec_override_functor) {
446 // Obsolete. Do not use.
447 IApplication* app = m_exec_main->application();
448 ArcaneMain::m_exec_override_functor->m_application = app;
449 ITraceMng* trace = app->traceMng();
450 trace->info() << "Calling overriding functor";
451 m_ret_val = ArcaneMain::callFunctorWithCatchedException(ArcaneMain::m_exec_override_functor->functor(),
452 m_exec_main, &m_clean_abort, true);
453 }
454 else
455 m_ret_val = ArcaneMain::callFunctorWithCatchedException(&exec_functor, m_exec_main, &m_clean_abort, true);
456}
457
458/*---------------------------------------------------------------------------*/
459/*---------------------------------------------------------------------------*/
460
461void ArcaneMainExecInfo::
462finalize()
463{
464 // Disables floating exceptions
466
467 // If execution went well but the user specified an
468 // error code, we retrieve it.
469 int exe_error_code = m_exec_main->errorCode();
470 if (m_ret_val == 0 && exe_error_code != 0) {
471 m_ret_val = exe_error_code;
472 }
473 else if (m_ret_val != 0)
474 m_exec_main->setErrorCode(m_ret_val);
475
476 m_exec_main->finalize();
477
478 if (m_ret_val != 0 && !m_clean_abort)
479 m_exec_main->doAbort();
480
481 // Code destruction.
482 // Be careful not to destroy the manager beforehand because when an
483 // architecture exception is generated, it uses an ITraceMng to display
484 // the message
485 delete m_exec_main;
486 m_exec_main = nullptr;
487#ifndef ARCANE_USE_MPC
488 IArcaneMain::setArcaneMain(m_exec_main);
489#endif
490}
491
492/*---------------------------------------------------------------------------*/
493/*---------------------------------------------------------------------------*/
494
500_arcaneMain(const ApplicationInfo& app_info, IMainFactory* factory)
501{
502 if (!factory)
503 return 5;
504
505 ArcaneMainExecInfo exec_info(app_info, factory);
506 int r = exec_info.initialize();
507 if (r != 0)
508 return r;
509
510 IDirectSubDomainExecuteFunctor* func = _staticInfo()->m_direct_exec_functor;
511 if (func)
512 exec_info.setDirectExecFunctor(func);
513 exec_info.execute();
514 exec_info.finalize();
515
516 return exec_info.returnValue();
517}
518
519/*---------------------------------------------------------------------------*/
520/*---------------------------------------------------------------------------*/
521
524 bool* clean_abort, bool is_print)
525{
526 int ret_val = 0;
527 *clean_abort = false;
528 IApplication* app = exec_main->application();
529 ITraceMng* trace = app->traceMng();
530 bool is_parallel = app->parallelSuperMng()->isParallel();
531 bool is_master = app->parallelSuperMng()->isMasterIO();
532 try {
533 functor->executeFunctor();
534 }
535 catch (const FatalErrorException& ex) {
536 if (ex.isCollective()) {
537 if (is_parallel) {
538 *clean_abort = true;
539 ret_val = 5;
540 if (is_master && is_print) {
541 std::ofstream ofile("fatal");
542 ofile << ret_val << '\n';
543 ofile.flush();
544 trace->error() << "ParallelFatalErrorException caught in ArcaneMain::callFunctor: " << ex << '\n';
545 }
546 }
547 else {
548 trace->error() << "ParallelFatalErrorException caught in ArcaneMain::callFunctor: " << ex << '\n';
549 ret_val = 4;
550 }
551 }
552 else {
553 trace->error() << Trace::Color::red() << "FatalErrorException caught in ArcaneMain::callFunctor: " << ex << '\n';
554 ret_val = 4;
555 }
556 }
557 catch (const SignalException& ex) {
558 trace->error() << "SignalException caught in ArcaneMain::callFunctor: " << ex << '\n';
559 ret_val = 6;
560 }
561 catch (const TimeoutException& ex) {
562 trace->error() << "TimeoutException caught in ArcaneMain::callFunctor: " << ex << '\n';
563 ret_val = 7;
564 }
565 catch (const ParallelFatalErrorException& ex) {
566 // TODO: use the FatalErrorException code in collective mode.n
567 if (is_parallel) {
568 *clean_abort = true;
569 ret_val = 5;
570 if (is_master && is_print) {
571 std::ofstream ofile("fatal");
572 ofile << ret_val << '\n';
573 ofile.flush();
574 trace->error() << "ParallelFatalErrorException caught in ArcaneMain::callFunctor: " << ex << '\n';
575 }
576 }
577 else {
578 trace->error() << "ParallelFatalErrorException caught in ArcaneMain::callFunctor: " << ex << '\n';
579 ret_val = 4;
580 }
581 }
582 catch (const ArithmeticException& ex) {
583 cerr << "** ARITHMETIC EXCEPTION!\n";
584 ret_val = ExceptionUtils::print(ex, trace);
585 if (ex.isCollective()) {
586 *clean_abort = true;
587 }
588 }
589 catch (const Exception& ex) {
590 ret_val = ExceptionUtils::print(ex, trace);
591 if (ex.isCollective()) {
592 *clean_abort = true;
593 }
594 }
595 catch (const std::exception& ex) {
596 ret_val = ExceptionUtils::print(ex, trace);
597 }
598 catch (...) {
599 ret_val = ExceptionUtils::print(trace);
600 }
601 return ret_val;
602}
603
604/*---------------------------------------------------------------------------*/
605/*---------------------------------------------------------------------------*/
606
607void ArcaneMain::
608_launchMissingInitException()
609{
610 std::cerr << "ERROR: ArcaneMain: missing call to ArcaneMain::arcaneInitialize().\n";
611 throw std::runtime_error("Missing call to ArcaneMain::arcaneInitialize()");
612}
613
614/*---------------------------------------------------------------------------*/
615/*---------------------------------------------------------------------------*/
616
617void ArcaneMain::
618_checkHasInit()
619{
620 if (m_nb_arcane_init <= 0)
621 _launchMissingInitException();
622}
623
624/*---------------------------------------------------------------------------*/
625/*---------------------------------------------------------------------------*/
626
627extern "C++" void arcaneInitCheckMemory();
628extern "C++" void arcaneExitCheckMemory();
629
630/*---------------------------------------------------------------------------*/
631/*---------------------------------------------------------------------------*/
632
635{
636 if (m_nb_arcane_init != 0) {
637 cerr << "WARNING: ArcaneMain::setHasGarbageCollector has to be called before arcaneInitialize\n";
638 return;
639 }
640 m_has_garbage_collector = true;
641}
642
643/*---------------------------------------------------------------------------*/
644/*---------------------------------------------------------------------------*/
645
648{
649 if (m_nb_arcane_init != 0) {
650 cerr << "WARNING: ArcaneMain::setHasDotNETRuntime has to be called before arcaneInitialize\n";
651 return;
652 }
654}
655
656/*---------------------------------------------------------------------------*/
657/*---------------------------------------------------------------------------*/
658
661{
662 m_exec_override_functor = functor;
663}
664
665/*---------------------------------------------------------------------------*/
666/*---------------------------------------------------------------------------*/
667
670{
671 return _staticInfo()->m_has_dotnet_wrapper;
672}
673
674/*---------------------------------------------------------------------------*/
675/*---------------------------------------------------------------------------*/
676
677/*
678 * \brief Positions the path containing Arcane dynamic libraries.
679 *
680 * This method must only be called once.
681 */
682void ArcaneMain::
683_setArcaneLibraryPath()
684{
685 String dir_name;
686 String dll_full_path = platform::getLoadedSharedLibraryFullPath("arcane_impl");
687 if (!dll_full_path.null())
688 dir_name = platform::getFileDirName(dll_full_path);
689 if (dir_name.null())
691 _staticInfo()->m_arcane_lib_path = dir_name;
692}
693
694/*---------------------------------------------------------------------------*/
695/*---------------------------------------------------------------------------*/
696
699{
700 // The first thread that arrives here performs the init.
701 // Others must wait for the init to finish.
702 if (m_nb_arcane_init.fetch_add(1) == 0) {
703 (void)_staticInfo();
705 dom::DOMImplementation::initialize();
707
708 // Checks if we want to use the old mechanism (before 3.15)
709 // to convert character strings to numeric types
710 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_USE_LEGACY_BUILTINVALUECONVERT", true))
712
713 // Creates the type manager singleton
715 initializeStringConverter();
716 arcaneInitCheckMemory();
717 // Initializes the empty group singleton and keeps a reference to it.
719 m_is_init_done = 1;
720 }
721 else
722 // Waits for the thread performing the init to finish
723 while (m_is_init_done.load() == 0)
724 ;
725}
726
727/*---------------------------------------------------------------------------*/
728/*---------------------------------------------------------------------------*/
729
732{
733 _checkHasInit();
734
735 if (m_nb_arcane_init.fetch_sub(1) == 1) {
736 _deleteStaticInfo();
737
740
741 {
743 if (x) {
744 x->closeLibraries();
745 }
746 }
747 arccorePrintSpecificMemoryStats();
748 arcaneExitCheckMemory();
750 dom::DOMImplementation::terminate();
752 arcaneEndProgram();
753#ifdef ARCANE_FLEXLM
754 {
756 }
757#endif
758 m_is_init_done = 0;
759 }
760}
761
762/*---------------------------------------------------------------------------*/
763/*---------------------------------------------------------------------------*/
764
767{
768 _staticInfo()->m_service_factory_infos.add(sri);
769}
770
771/*---------------------------------------------------------------------------*/
772/*---------------------------------------------------------------------------*/
773
776{
777 _staticInfo()->m_module_factory_infos.add(mfi);
778}
779
780/*---------------------------------------------------------------------------*/
781/*---------------------------------------------------------------------------*/
782
785{
786 _staticInfo()->m_application_build_info_visitors.add(visitor);
787}
788
789/*---------------------------------------------------------------------------*/
790/*---------------------------------------------------------------------------*/
791
794{
795 return _staticInfo()->m_app_build_info._internalApplicationInfo();
796}
797
798/*---------------------------------------------------------------------------*/
799/*---------------------------------------------------------------------------*/
800
803{
804 return _staticInfo()->m_dotnet_init_info;
805}
806
807/*---------------------------------------------------------------------------*/
808/*---------------------------------------------------------------------------*/
809
812{
813 return _staticInfo()->m_accelerator_init_info;
814}
815
816/*---------------------------------------------------------------------------*/
817/*---------------------------------------------------------------------------*/
818
821{
822 return _staticInfo()->m_app_build_info;
823}
824
825/*---------------------------------------------------------------------------*/
826/*---------------------------------------------------------------------------*/
827
830{
831 return m_p->m_application_build_info;
832}
833
834/*---------------------------------------------------------------------------*/
835/*---------------------------------------------------------------------------*/
836
837ApplicationBuildInfo& ArcaneMain::
838_applicationBuildInfo()
839{
840 return m_p->m_application_build_info;
841}
842
843/*---------------------------------------------------------------------------*/
844/*---------------------------------------------------------------------------*/
845
848{
849 return m_p->m_dotnet_info;
850}
851
852/*---------------------------------------------------------------------------*/
853/*---------------------------------------------------------------------------*/
854
857{
858 return m_p->m_accelerator_info;
859}
860
861/*---------------------------------------------------------------------------*/
862/*---------------------------------------------------------------------------*/
863
866{
867 return _staticInfo()->m_init_time_accelerator;
868}
869
870/*---------------------------------------------------------------------------*/
871/*---------------------------------------------------------------------------*/
872
874arcaneMain(const ApplicationInfo& app_info, IMainFactory* factory)
875{
876 _checkHasInit();
877
878 ScopedPtrT<IMainFactory> default_factory;
879 if (!factory) {
880 factory = m_default_main_factory;
881 if (!factory) {
882 factory = new ArcaneBatchMainFactory();
883 default_factory = factory;
884 }
885 }
886
887 int ret = _arcaneMain(app_info, factory);
888
889 default_factory = nullptr;
890
891 // Error code 5 represents a parallel error for all
892 // processors.
893 if (ret != 0 && ret != 5)
894 cerr << "* Process return: " << ret << '\n';
895 if (ret == 5)
896 ret = 4;
897
898 return ret;
899}
900
901/*---------------------------------------------------------------------------*/
902/*---------------------------------------------------------------------------*/
903
904int ArcaneMain::
905_internalRun(IDirectSubDomainExecuteFunctor* func)
906{
907 _staticInfo()->m_direct_exec_functor = func;
908 return run();
909}
910
911/*---------------------------------------------------------------------------*/
912/*---------------------------------------------------------------------------*/
913
914int ArcaneMain::
915_checkTestLoggerResult()
916{
917 if (!m_is_use_test_logger)
918 return 0;
919 if (!m_is_master_io)
920 return 0;
921 return TestLogger::compare();
922}
923
924/*---------------------------------------------------------------------------*/
925/*---------------------------------------------------------------------------*/
926
927int ArcaneMain::
928_initRuntimes()
929{
930 ArcaneMainAutoDetectRuntimeHelper auto_detect_helper;
931 return auto_detect_helper.check();
932}
933
934/*---------------------------------------------------------------------------*/
935/*---------------------------------------------------------------------------*/
936
938run()
939{
940 int r = _initRuntimes();
941 if (r != 0)
942 return r;
943
945
946 // If we arrive here and the C# runtime is already loaded
947 // (because Main is in C# for example), we do not launch the wrapper
948 bool is_in_dotnet = platform::hasDotNETRuntime();
949 if (!is_in_dotnet && dotnet_info.isUsingDotNetRuntime()) {
950 r = _runDotNet();
951 // Before version 3.7.8 we called arcaneFinalize() because it could
952 // cause problems with the '.Net' Garbage Collector. Normally these
953 // problems are fixed but we allow the previous behavior just in case.
954 bool do_finalize = false;
955 String x = platform::getEnvironmentVariable("ARCANE_DOTNET_USE_LEGACY_DESTROY");
956 if (x == "1")
957 do_finalize = false;
958 if (x == "0")
959 do_finalize = true;
960 if (do_finalize)
962 }
963 else {
965 r = arcaneMain(defaultApplicationInfo(), nullptr);
967 }
968 if (r != 0)
969 return r;
970 return _checkTestLoggerResult();
971}
972
973/*---------------------------------------------------------------------------*/
974/*---------------------------------------------------------------------------*/
975
976int ArcaneMain::
977_runDotNet()
978{
979 auto si = _staticInfo();
980 si->m_has_dotnet_wrapper = true;
981
982 // TODO: check that init has not been done.
983
984 // To be able to execute .Net code, it is necessary
985 // to call the method 'arcane_mono_main' which is located
986 // in the dynamic library 'arcane_mono'.
987
988 typedef int (*DotNetMainFunctor)(const CommandLineArguments& cmd_args, const String& assembly_name);
989
990 const ApplicationInfo& app_info = defaultApplicationInfo();
992
993 DotNetMainFunctor my_functor = nullptr;
994 String os_dir(si->m_arcane_lib_path);
995
996 try {
998
999 String dll_name = "arcane_mono";
1000 String symbol_name = "arcane_mono_main2";
1001
1002 String runtime_name = dotnet_info.embeddedRuntime();
1003
1004 if (runtime_name.null() || runtime_name == "mono")
1005 // Mono is the default if nothing is specified.
1006 ;
1007 else if (runtime_name == "coreclr") {
1008 dll_name = "arcane_dotnet_coreclr";
1009 symbol_name = "arcane_dotnet_coreclr_main";
1010 }
1011 else
1012 ARCANE_FATAL("Unknown '.Net' runtime '{0}'. Valid values are 'mono' or 'coreclr'", runtime_name);
1013
1014 IDynamicLibrary* dl = dll_loader->open(os_dir, dll_name);
1015 if (!dl)
1016 ARCANE_FATAL("Can not found dynamic library '{0}' for using .Net", dll_name);
1017
1018 bool is_found = false;
1019 void* functor_addr = dl->getSymbolAddress(symbol_name, &is_found);
1020 if (!is_found)
1021 ARCANE_FATAL("Can not find symbol '{0}' in library '{1}'", symbol_name, dll_name);
1022
1023 my_functor = reinterpret_cast<DotNetMainFunctor>(functor_addr);
1024 }
1025 catch (const Exception& ex) {
1026 return ExceptionUtils::print(ex, nullptr);
1027 }
1028 catch (const std::exception& ex) {
1029 return ExceptionUtils::print(ex, nullptr);
1030 }
1031 catch (...) {
1032 return ExceptionUtils::print(nullptr);
1033 }
1034
1035 if (my_functor) {
1036 const CommandLineArguments& cmd_args = app_info.commandLineArguments();
1037 // TODO: check that the assembly 'Arcane.Main.dll' exists.
1038 String new_name = os_dir + "/Arcane.Main.dll";
1039 return (*my_functor)(cmd_args, new_name);
1040 }
1041 return (-1);
1042}
1043
1044/*---------------------------------------------------------------------------*/
1045/*---------------------------------------------------------------------------*/
1046
1047// Do not call directly but go through ArcaneMainAutoDetectHelper.
1048void ArcaneMain::
1049_checkAutoDetectMPI()
1050{
1051 auto si = _staticInfo();
1052 // To automatically register MPI, it is necessary
1053 // to call the method 'arcaneAutoDetectMessagePassingServiceMPI' which is located
1054 // in the dynamic library 'arcane_mpi'.
1055
1056 typedef void (*ArcaneAutoDetectMPIFunctor)();
1057
1058 IDynamicLibraryLoader* dll_loader = IDynamicLibraryLoader::getDefault();
1059
1060 String os_dir(si->m_arcane_lib_path);
1061 String dll_name = "arcane_mpi";
1062 String symbol_name = "arcaneAutoDetectMessagePassingServiceMPI";
1063 IDynamicLibrary* dl = dll_loader->open(os_dir, dll_name);
1064 if (!dl)
1065 return;
1066
1067 bool is_found = false;
1068 void* functor_addr = dl->getSymbolAddress(symbol_name, &is_found);
1069 if (!is_found)
1070 return;
1071
1072 auto my_functor = reinterpret_cast<ArcaneAutoDetectMPIFunctor>(functor_addr);
1073 if (my_functor)
1074 (*my_functor)();
1075}
1076
1077/*---------------------------------------------------------------------------*/
1078/*---------------------------------------------------------------------------*/
1079
1091_checkAutoDetectAccelerator(bool& has_accelerator)
1092{
1093 has_accelerator = false;
1094 String default_runtime_name;
1095#if defined(ARCANE_ACCELERATOR_RUNTIME)
1096 default_runtime_name = ARCANE_ACCELERATOR_RUNTIME;
1097#endif
1098 auto si = _staticInfo();
1099 AcceleratorRuntimeInitialisationInfo& init_info = si->m_accelerator_init_info;
1100 if (!init_info.isUsingAcceleratorRuntime())
1101 return 0;
1102 return Accelerator::Impl::RuntimeLoader::loadRuntime(init_info, default_runtime_name, si->m_arcane_lib_path, has_accelerator);
1103}
1104
1105/*---------------------------------------------------------------------------*/
1106/*---------------------------------------------------------------------------*/
1107
1108/*---------------------------------------------------------------------------*/
1109/*---------------------------------------------------------------------------*/
1110
1111IMainFactory* ArcaneMain::m_default_main_factory = nullptr;
1112ArcaneMainExecutionOverrideFunctor* ArcaneMain::m_exec_override_functor = nullptr;
1113
1114/*---------------------------------------------------------------------------*/
1115/*---------------------------------------------------------------------------*/
1116
1117ArcaneMain::
1118ArcaneMain(const ApplicationInfo& app_info, IMainFactory* factory)
1119: m_p(new Impl(app_info))
1120, m_main_factory(factory)
1121{
1122}
1123
1124/*---------------------------------------------------------------------------*/
1125/*---------------------------------------------------------------------------*/
1126
1127ArcaneMain::
1128ArcaneMain(const ApplicationInfo& app_info, IMainFactory* factory,
1129 const ApplicationBuildInfo& app_build_info,
1130 const DotNetRuntimeInitialisationInfo& dotnet_info,
1131 const AcceleratorRuntimeInitialisationInfo& accelerator_info)
1132: m_p(new Impl(app_info, app_build_info, dotnet_info, accelerator_info))
1133, m_main_factory(factory)
1134{
1135}
1136
1137/*---------------------------------------------------------------------------*/
1138/*---------------------------------------------------------------------------*/
1139
1140ArcaneMain::
1141~ArcaneMain()
1142{
1143 // Ensures that observers associated with TheadBindingMng are removed
1144 // before finalization to avoid wasting threads when
1145 // it is no longer useful.
1146 m_p->m_thread_binding_mng.finalize();
1147 delete m_application;
1148 delete m_p;
1149}
1150
1151/*---------------------------------------------------------------------------*/
1152/*---------------------------------------------------------------------------*/
1153
1154/*---------------------------------------------------------------------------*/
1155/*---------------------------------------------------------------------------*/
1156
1158build()
1159{
1160 _parseApplicationBuildInfoArgs();
1161 m_application = m_main_factory->createApplication(this);
1162 m_p->m_thread_binding_mng.initialize(m_application->traceMng(),
1163 m_p->m_application_build_info.threadBindingStrategy());
1164}
1165
1166/*---------------------------------------------------------------------------*/
1167/*---------------------------------------------------------------------------*/
1168
1170applicationInfo() const
1171{
1172 return m_p->m_app_info;
1173}
1174
1175/*---------------------------------------------------------------------------*/
1176/*---------------------------------------------------------------------------*/
1177
1178void ArcaneMain::
1179_parseApplicationBuildInfoArgs()
1180{
1181 ApplicationBuildInfo& abi = _applicationBuildInfo();
1182 abi.parseArguments(m_p->m_app_info.commandLineArguments());
1183 // Calls the registered visitors.
1184 {
1185 auto& x = _staticInfo()->m_application_build_info_visitors;
1186 for (IApplicationBuildInfoVisitor* v : x) {
1187 if (v)
1188 v->visit(abi);
1189 }
1190 }
1191 abi.setDefaultServices();
1192}
1193
1194/*---------------------------------------------------------------------------*/
1195/*---------------------------------------------------------------------------*/
1196
1198initialize()
1199{
1200 m_application->initialize();
1201
1202 ScopedPtrT<IServiceLoader> service_loader(m_main_factory->createServiceLoader());
1203 service_loader->loadApplicationServices(m_application);
1204}
1205
1206/*---------------------------------------------------------------------------*/
1207/*---------------------------------------------------------------------------*/
1208
1211{
1212 return _staticInfo()->m_service_factory_infos;
1213}
1214
1215/*---------------------------------------------------------------------------*/
1216/*---------------------------------------------------------------------------*/
1217
1220{
1221 return _staticInfo()->m_module_factory_infos;
1222}
1223
1224/*---------------------------------------------------------------------------*/
1225/*---------------------------------------------------------------------------*/
1226
1228execute()
1229{
1230 return 0;
1231}
1232
1233/*---------------------------------------------------------------------------*/
1234/*---------------------------------------------------------------------------*/
1235
1237doAbort()
1238{
1239 ::abort();
1240}
1241
1242/*---------------------------------------------------------------------------*/
1243/*---------------------------------------------------------------------------*/
1244
1246setErrorCode(int errcode)
1247{
1248 m_error_code = errcode;
1249 if (errcode != 0) {
1250 // Only the master process writes the file unless it is a fatal error because
1251 // in this case, any PE can do it.
1252 if (ArcaneMain::m_is_master_io || errcode == 4) {
1253 String errname = "fatal_" + String::fromNumber(errcode);
1254 std::ofstream ofile(errname.localstr());
1255 ofile.close();
1256 }
1257 }
1258}
1259
1260/*---------------------------------------------------------------------------*/
1261/*---------------------------------------------------------------------------*/
1262
1265{
1266 // If true, display internal information
1267 bool arcane_internal = false;
1268 // If true, display internal information for each time loop
1269 bool arcane_all_internal = false;
1270 // If true, generates a file containing internal code information.
1271 bool arcane_database = false;
1272 // If true, display information about present modules and services and a brief help
1273 bool arcane_help = false;
1274
1275 String us_arcane_opt("-arcane_opt");
1276 String us_help("help");
1277 String us_arcane_internal("arcane_internal");
1278 String us_arcane_all_internal("arcane_all_internal");
1279 String us_arcane_database("arcane_database");
1280
1281 StringList unknown_args;
1282 for (Integer i = 0, s = args.count(); i < s; ++i) {
1283 if (args[i].startsWith("-A")) {
1284 continue;
1285 }
1286 if (args[i] != us_arcane_opt) {
1287 unknown_args.add(args[i]);
1288 continue;
1289 }
1290 bool is_valid_opt = false;
1291 ++i;
1292 String str;
1293 if (i < s)
1294 str = args[i];
1295 if (str == us_arcane_internal) {
1296 arcane_internal = true;
1297 is_valid_opt = true;
1298 }
1299 if (str == us_arcane_all_internal) {
1300 arcane_all_internal = true;
1301 is_valid_opt = true;
1302 }
1303 if (str == us_arcane_database) {
1304 arcane_database = true;
1305 is_valid_opt = true;
1306 }
1307 if (str == us_help) {
1308 arcane_help = true;
1309 is_valid_opt = true;
1310 }
1311 if (!is_valid_opt) {
1312 // If the option is not valid, add it to the list of
1313 // unprocessed options
1314 unknown_args.add(us_arcane_opt);
1315 if (!str.null())
1316 unknown_args.add(str);
1317 //trace->fatal() << "Unknown arcane option <" << str << ">\n";
1318 }
1319 }
1320
1321 bool do_stop = false;
1322 if (arcane_database) {
1324 dumper.dumpArcaneDatabase();
1325 do_stop = true;
1326 }
1327 if (arcane_internal) {
1329 dumper.dumpInternalInfos();
1330 do_stop = true;
1331 }
1332 if (arcane_all_internal) {
1334 dumper.dumpInternalAllInfos();
1335 do_stop = true;
1336 }
1337 if (arcane_help) {
1338 _dumpHelp();
1339 do_stop = true;
1340 }
1341
1342 args.clear();
1343 for (StringList::Enumerator i(unknown_args); ++i;)
1344 args.add(*i);
1345
1346 return do_stop;
1347}
1348
1349/*---------------------------------------------------------------------------*/
1350/*---------------------------------------------------------------------------*/
1351
1352void ArcaneMain::
1353_dumpHelp()
1354{
1355 // We want to list by IServiceInfo. Since it is possible that a service has multiple
1356 // factories, we filter using done_set.
1357 typedef std::multimap<String, IServiceInfo*> ServiceList;
1358 ServiceList service_list;
1359 Integer max_name_size = 0;
1360
1361 {
1362 // On veut lister par IServiceInfo. Comme il est possible qu'un service ait plusieurs
1363 // fabriques, on filtre grâce à done_set.
1364 std::set<IServiceInfo*> done_set;
1365 for (ServiceFactory2Collection::Enumerator j(application()->serviceFactories2()); ++j;) {
1366 IServiceInfo* si = (*j)->serviceInfo();
1367 if (done_set.find(si) != done_set.end()) {
1368 continue;
1369 }
1370 done_set.insert(si);
1371 const String& name = si->localName();
1372 max_name_size = math::max(max_name_size, CheckedConvert::toInteger(name.length()));
1373 service_list.insert(std::make_pair(name, si));
1374 }
1375 }
1376
1377 UniqueArray<String> module_names;
1378 for (EnumeratorT<IModuleFactoryInfo*> e = application()->moduleFactoryInfos(); ++e;) {
1379 IModuleFactoryInfo* mfi = (*e);
1380 const String& name = mfi->moduleName();
1381 max_name_size = math::max(max_name_size, CheckedConvert::toInteger(name.length()));
1382 module_names.add(name);
1383 }
1384
1385 ITraceMng* trace = application()->traceMng();
1386 trace->info() << " ";
1387 trace->info() << std::setw(max_name_size) << "Module List";
1388 trace->info() << std::setw(max_name_size) << "-------------"
1389 << "--";
1390 for (int i = 0, n = module_names.size(); i < n; ++i) {
1391 trace->info() << std::setw(max_name_size) << module_names[i];
1392 }
1393
1394 trace->info() << " ";
1395 trace->info() << std::setw(max_name_size) << "Service List";
1396 trace->info() << std::setw(max_name_size) << "--------------"
1397 << "--";
1398 for (ServiceList::const_iterator i = service_list.begin(); i != service_list.end(); ++i) {
1399 IServiceInfo* si = i->second;
1400 OStringStream oss;
1401 oss() << std::setw(max_name_size) << i->first;
1402 StringCollection interfaces = si->implementedInterfaces();
1403 if (!interfaces.empty())
1404 oss() << " Implements : ";
1405 for (EnumeratorT<String> e(interfaces.enumerator()); ++e;) {
1406 oss() << e.current() << " ";
1407 }
1408 trace->info() << oss.str();
1409 }
1410
1411 const Integer option_size = 20;
1412 trace->info() << " ";
1413 trace->info() << std::setw(max_name_size) << "Usage";
1414 trace->info() << std::setw(max_name_size) << "-------"
1415 << "--";
1416 trace->info() << application()->applicationName() << ".exe [-arcane_opt OPTION] dataset_file.arc";
1417 trace->info() << "Where OPTION is";
1418 trace->info() << std::setw(option_size) << "help"
1419 << " : this help page and abort";
1420 trace->info() << std::setw(option_size) << "arcane_internal"
1421 << " : save into a file internal Arcane informations and abort execution";
1422 trace->info() << std::setw(option_size) << "arcane_all_internal"
1423 << " : save into a file timeloop informations and abort execution";
1424 trace->info() << std::setw(option_size) << "arcane_database"
1425 << " : save internal database infos in file 'arcane_database.json'";
1426 trace->info() << std::setw(option_size) << "init_only"
1427 << " : only run initialization step";
1428 trace->info() << std::setw(option_size) << "continue"
1429 << " : continue an interrupted run";
1430 trace->info() << std::setw(option_size) << "max_iteration"
1431 << " : define maximum iteration number";
1432 trace->info() << std::setw(option_size) << "casename"
1433 << " : define case name";
1434}
1435
1436/*---------------------------------------------------------------------------*/
1437/*---------------------------------------------------------------------------*/
1438
1444extern "C" void
1446{
1447 const char* signal_str = "Unknown";
1448 bool is_alarm = false;
1449 int written_signal_number = val;
1450
1451 switch (val) {
1452 case SIGSEGV:
1453 signal_str = "Segmentation Fault";
1454 break;
1455 case SIGFPE:
1456 signal_str = "Floating exception";
1457 break;
1458#ifdef SIGBUS
1459 case SIGBUS:
1460 signal_str = "Bus Error";
1461 break;
1462#endif
1463#ifdef SIGSYS
1464 case SIGSYS:
1465 signal_str = "System signal";
1466 break;
1467#endif
1468#ifdef SIGPIPE
1469 case SIGPIPE:
1470 signal_str = "Broken pipe";
1471 break;
1472#endif
1473#ifdef SIGALRM
1474 case SIGALRM:
1475 signal_str = "Sigalarm";
1476 is_alarm = true;
1477 break;
1478#endif
1479#ifdef SIGVTALRM
1480 case SIGVTALRM:
1481 signal_str = "Sigalarm(VirtualTime)";
1482 written_signal_number = SIGALRM;
1483 is_alarm = true;
1484 break;
1485#endif
1486 }
1487
1488 cerr << "Signal Caught !!! number=" << val << " name=" << signal_str << ".\n";
1489#ifdef ARCANE_DEBUG
1490 //arcaneDebugPause("SIGNAL");
1491#endif
1492
1493#ifndef ARCANE_OS_WIN32
1494 // To prevent all PEs from writing the same file for SIGALRM,
1495 // only the master process does it. In the case of other signals, everyone
1496 // does it.
1497 bool create_file = ArcaneMain::isMasterIO() || (!is_alarm);
1498 if (create_file) {
1499 // Creates the 'signal_*' file to indicate in parallel that a
1500 // signal has been sent
1501 mode_t mode = S_IRUSR | S_IWUSR;
1502 char path[256];
1503 sprintf(path, "signal_%d", written_signal_number);
1504 path[255] = '\0';
1505 int fd = ::open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
1506 if (fd != (-1))
1507 ::close(fd);
1508 }
1509#endif
1510
1511 // Repositions the signals for next time, if the signal is
1512 // one that can be received multiple times.
1513 arcaneRedirectSignals(arcaneSignalHandler);
1514
1515 Arcane::arcaneCallDefaultSignal(val);
1516 //::exit(val);
1517}
1518
1519/*---------------------------------------------------------------------------*/
1520/*---------------------------------------------------------------------------*/
1521
1522} // End namespace Arcane
1523
1524/*---------------------------------------------------------------------------*/
1525/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Utility functions for exception handling.
Int32 print(ITraceMng *tm, bool is_no_continue=true)
Prints a message for an unknown exception.
Memory and allocator management functions.
static int loadRuntime(AcceleratorRuntimeInitialisationInfo &init_info, const String &default_runtime_name, const String &library_path, bool &has_accelerator)
Detects and loads the accelerator runtime management library.
Information for constructing an instance of IApplication.
void parseArguments(const CommandLineArguments &args)
Parses the arguments in args.
Application information.
const CommandLineArguments & commandLineArguments() const
Command line arguments.
IArcaneMain * createArcaneMain(const ApplicationInfo &app_info) override
Creates an instance of IArcaneMain.
Class to manage calls to runtime auto-detection mechanisms (MPI, Accelerators).
void executeFunctor() override
Executes the associated method.
int initialize()
Creation of the 'IArcaneMain' instance.
const ApplicationInfo & m_app_info
WARNING: reference.
std::atomic< Int32 > m_nb_autodetect
Number of times auto-detection for MPI and accelerators has been run.
Real m_init_time_accelerator
Time spent (in seconds) during initialization for accelerators.
Int32 m_autodetect_return_value
Return code for auto-detection.
Execution management class.
Definition ArcaneMain.h:89
static ApplicationBuildInfo & defaultApplicationBuildInfo()
Information for accelerator initialization.
static AcceleratorRuntimeInitialisationInfo & defaultAcceleratorRuntimeInitialisationInfo()
Information for accelerator initialization.
static std::atomic< Int32 > m_nb_arcane_init
Number of times arcaneInitialize() has been called.
Definition ArcaneMain.h:364
static DotNetRuntimeInitialisationInfo & defaultDotNetRuntimeInitialisationInfo()
Information for .Net runtime initialization.
static void arcaneInitialize()
Initializes Arcane.
static void addApplicationBuildInfoVisitor(IApplicationBuildInfoVisitor *visitor)
Adds a visitor to fill ApplicationBuildInfo.
const DotNetRuntimeInitialisationInfo & dotnetRuntimeInitialisationInfo() const override
.Net runtime initialization information.
static int _checkAutoDetectAccelerator(bool &has_accelerator)
Detects and loads accelerator runtime management.
static void arcaneFinalize()
Terminates Arcane usage.
static int _arcaneMain(const ApplicationInfo &, IMainFactory *)
Executable entry point.
static Real initializationTimeForAccelerator()
Returns the time (in seconds) for the initialization of accelerator runtimes for this process.
const ApplicationInfo & applicationInfo() const override
Executable information.
ServiceFactoryInfoCollection registeredServiceFactoryInfos() override
List of registered service factories.
const AcceleratorRuntimeInitialisationInfo & acceleratorRuntimeInitialisationInfo() const override
Runtime initialization information for accelerators.
static int callFunctorWithCatchedException(IFunctor *functor, IArcaneMain *amain, bool *clean_abort, bool is_print=true)
Calls the functor functor while catching possible exceptions.
ModuleFactoryInfoCollection registeredModuleFactoryInfos() override
List of registered module factories.
void setErrorCode(int errcode) override
Sets the return code.
static void setHasDotNETRuntime()
Indicates that we are running in the .NET runtime.
IApplication * application() const override
Application.
Definition ArcaneMain.h:332
static void setHasGarbageCollector()
Indicates that certain objects are managed by a garbage collector.
static std::atomic< Int32 > m_is_init_done
1 if init finished, 0 otherwise
Definition ArcaneMain.h:366
static int run()
Entry point of the executable in Arcane.
static void addServiceFactoryInfo(IServiceFactoryInfo *factory)
Adds a service factory.
void build() override
Constructs the class members. The instance is not usable until this method has been called....
static ApplicationInfo & defaultApplicationInfo()
Default application info.
static void setExecuteOverrideFunctor(ArcaneMainExecutionOverrideFunctor *functor)
static bool hasDotNetWrapper()
Indicates if a '.Net' assembly is being executed from a C++ main.
const ApplicationBuildInfo & applicationBuildInfo() const override
Information to build the IApplication instance.
int execute() override
Starts execution. This method only returns when the program exits.
void doAbort() override
Performs an abort.
static void setDefaultMainFactory(IMainFactory *mf)
Sets the default factory.
void initialize() override
Initializes the instance. The instance is not usable until this method has been called.
bool parseArgs(StringList args) override
Parses arguments.
static void addModuleFactoryInfo(IModuleFactoryInfo *factory)
Adds a module factory.
Exception when an arithmetic error occurs.
void clear()
Removes all elements from the collection.
Integer count() const
Number of elements in the collection.
static void setUseFromChars(bool v)
Indicates whether 'std::from_chars' is used to convert character strings into a numeric type.
Template class for converting a type.
Information for the initialization of the '.Net' runtime.
bool isCollective() const
True if it is a collective error (concerns all processors).
static FlexLMMng * instance()
Access to the singleton.
void init(IParallelSuperMng *parallel_super_mng)
Initializes the license manager.
void releaseAllLicenses()
Releases all allocated licenses.
Application interface.
virtual String applicationName() const =0
Application name.
virtual IParallelSuperMng * parallelSuperMng()=0
Supervisory parallelism manager.
Interface of the code management class.
Definition IArcaneMain.h:55
virtual IApplication * application() const =0
Application.
static IArcaneMain * arcaneMain()
static void setArcaneMain(IArcaneMain *arcane_main)
virtual ITraceMng * traceMng() const =0
Trace manager.
Interface of a case loader.
Interface of a functor to execute code directly after the creation of a subdomain without going throu...
Interface of a dynamic library loader.
virtual IDynamicLibrary * open(const String &directory, const String &name)=0
Loads a dynamic library.
static IDynamicLibraryLoader * getDefault()
Service used for dynamically loading libraries.
Factory for Arcane classes.
Information about a module factory.
Abstract class of the parallelism supervisor.
virtual bool isMasterIO() const =0
Returns true if the instance is a master I/O manager.
virtual bool isParallel() const =0
Returns true if the execution is parallel.
Information about a service factory.
Interface for service or module information.
virtual String localName() const =0
Local part of the service name.
virtual TraceMessage error()=0
Stream for an error message.
virtual TraceMessage info()=0
Stream for an information message.
Internal information dumping for Arcane.
void dumpArcaneDatabase()
Saves the internal information of Arcane in a json file.
static void _buildSharedNull()
Internal.
static void _destroySharedNull()
Internal.
static void _destroySingleton()
Destroys the singleton.
static ItemTypeMng * _singleton()
Singleton instance of the type.
Implementation of a collection of elements in vector form.
Exception when a 'parallel' fatal error is generated.
Encapsulation of an automatically destructing pointer.
Definition ScopedPtr.h:44
Exception when a signal occurs.
bool null() const
Returns true if the string is null.
Definition String.cc:306
const char * localstr() const
Returns the conversion of the instance into UTF-8 encoding.
Definition String.cc:229
T max(const T &a, const T &b, const T &c)
Returns the maximum of three elements.
Definition MathUtils.h:407
void platformInitialize()
Platform-specific initialization.
String getFileDirName(const String &file_name)
Returns the directory name of a file.
void platformTerminate()
Platform-specific program termination routines.
String getCurrentDirectory()
Current directory path.
void setHasDotNETRuntime(bool v)
Sets whether the code is running with the .NET runtime.
String getLoadedSharedLibraryFullPath(const String &dll_name)
Returns the full path of a loaded dynamic library.
void enableFloatingException(bool active)
Enables or disables exceptions during a floating-point calculation. This operation is not supported o...
bool hasDotNETRuntime()
True if the code is running with the .NET runtime.
String getEnvironmentVariable(const String &name)
Environment variable named name.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Int32 Integer
Type representing an integer.
Collection< IServiceFactoryInfo * > ServiceFactoryInfoCollection
Collection of service factory information.
Collection< String > StringCollection
Collection of strings.
Definition UtilsTypes.h:506
void arcaneSignalHandler(int val)
Brief function called when the program is interrupted by the 'val' signal.
List< String > StringList
Unicode string list.
Definition UtilsTypes.h:509
Collection< IModuleFactoryInfo * > ModuleFactoryInfoCollection
Collection of module factory information.
List< IService * > ServiceList
Array of services.
double Real
Type representing a real number.
std::int32_t Int32
Signed integer type of 32 bits.