From 765bd54c7cd344c89977ef32560bd644b33e8dd7 Mon Sep 17 00:00:00 2001 From: Haroon Qureshi Date: Thu, 8 Jan 2026 03:07:15 -0800 Subject: [PATCH] Move GlobalModel class and functionality into its own file. We'll need some of this functionality for tests. PiperOrigin-RevId: 853652149 Change-Id: Ib924d886b73784a0f370285e0b82b2ed833e3e77 --- src/xml/CMakeLists.txt | 2 ++ src/xml/xml_api.cc | 70 +++++--------------------------------- src/xml/xml_global.cc | 77 ++++++++++++++++++++++++++++++++++++++++++ src/xml/xml_global.h | 27 +++++++++++++++ 4 files changed, 114 insertions(+), 62 deletions(-) create mode 100644 src/xml/xml_global.cc create mode 100644 src/xml/xml_global.h diff --git a/src/xml/CMakeLists.txt b/src/xml/CMakeLists.txt index 4893f77e..d35d14cb 100644 --- a/src/xml/CMakeLists.txt +++ b/src/xml/CMakeLists.txt @@ -17,6 +17,8 @@ set(MUJOCO_XML_SRCS xml_api.h xml_base.cc xml_base.h + xml_global.cc + xml_global.h xml.cc xml.h xml_native_reader.cc diff --git a/src/xml/xml_api.cc b/src/xml/xml_api.cc index 82042bf7..c27d6755 100644 --- a/src/xml/xml_api.cc +++ b/src/xml/xml_api.cc @@ -20,17 +20,15 @@ #include #include #include -#include -#include #include #include -#include #include #include #include "engine/engine_io.h" #include "user/user_resource.h" #include "xml/xml.h" +#include "xml/xml_global.h" #include "xml/xml_native_reader.h" #include "xml/xml_util.h" #if defined(mjUSEUSD) @@ -38,59 +36,7 @@ #include #endif -//---------------------------------- Globals ------------------------------------------------------- -namespace { - -// global user model class -class GlobalModel { - public: - // deletes current model and takes ownership of model - void Set(mjSpec* spec = nullptr); - - // writes XML to string - std::optional ToXML(const mjModel* m, char* error, - int error_sz); - - private: - // using raw pointers as GlobalModel needs to be trivially destructible - std::mutex* mutex_ = new std::mutex(); - mjSpec* spec_ = nullptr; -}; - -std::optional GlobalModel::ToXML(const mjModel* m, char* error, - int error_sz) { - std::lock_guard lock(*mutex_); - if (!spec_) { - mjCopyError(error, "No XML model loaded", error_sz); - return std::nullopt; - } - std::string result = WriteXML(m, spec_, error, error_sz); - if (result.empty()) { - return std::nullopt; - } - return result; -} - -void GlobalModel::Set(mjSpec* spec) { - std::lock_guard lock(*mutex_); - if (spec_ != nullptr) { - mj_deleteSpec(spec_); - } - spec_ = spec; -} - - -// returns a single instance of the global model -GlobalModel& GetGlobalModel() { - static GlobalModel global_model; - - // global variables must be trivially destructible - static_assert(std::is_trivially_destructible_v); - return global_model; -} - -} // namespace //---------------------------------- Functions ----------------------------------------------------- @@ -125,7 +71,7 @@ mjModel* mj_loadXML(const char* filename, const mjVFS* vfs, } // clear old and assign new - GetGlobalModel().Set(spec.release()); + SetGlobalXmlSpec(spec.release()); return m; } @@ -155,7 +101,7 @@ mjModel* mj_loadUSD(const char* filename, const mjVFS* vfs, char* error, int err return nullptr; } - GetGlobalModel().Set(spec.release()); + SetGlobalXmlSpec(spec.release()); return m; } #endif @@ -173,23 +119,23 @@ int mj_saveLastXML(const char* filename, const mjModel* m, char* error, int erro } } - auto result = GetGlobalModel().ToXML(m, error, error_sz); - if (result.has_value()) { - fprintf(fp, "%s", result->c_str()); + const std::string result = GetGlobalXmlSpec(m, error, error_sz); + if (!result.empty()) { + fprintf(fp, "%s", result.c_str()); } if (fp != stdout) { fclose(fp); } - return result.has_value(); + return !result.empty(); } // free last XML void mj_freeLastXML(void) { - GetGlobalModel().Set(); + SetGlobalXmlSpec(); } diff --git a/src/xml/xml_global.cc b/src/xml/xml_global.cc new file mode 100644 index 00000000..4f8ac8c7 --- /dev/null +++ b/src/xml/xml_global.cc @@ -0,0 +1,77 @@ +// Copyright 2026 DeepMind Technologies Limited +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "xml/xml_global.h" + +#include +#include +#include +#include +#include "xml/xml.h" +#include "xml/xml_util.h" + +namespace { + +// global user model class +class GlobalModel { + public: + // deletes current model and takes ownership of model + void Set(mjSpec* spec = nullptr); + + // writes XML to string + std::string ToXML(const mjModel* m, char* error, int error_sz); + + private: + // using raw pointers as GlobalModel needs to be trivially destructible + std::mutex* mutex_ = new std::mutex(); + mjSpec* spec_ = nullptr; +}; + +std::string GlobalModel::ToXML(const mjModel* m, char* error, + int error_sz) { + std::lock_guard lock(*mutex_); + if (!spec_) { + mjCopyError(error, "No XML model loaded", error_sz); + return ""; + } + return WriteXML(m, spec_, error, error_sz); +} + +void GlobalModel::Set(mjSpec* spec) { + std::lock_guard lock(*mutex_); + if (spec_ != nullptr) { + mj_deleteSpec(spec_); + } + spec_ = spec; +} + + +// returns a single instance of the global model +GlobalModel& GetGlobalModel() { + static GlobalModel global_model; + + // global variables must be trivially destructible + static_assert(std::is_trivially_destructible_v); + return global_model; +} + +} // namespace + +void SetGlobalXmlSpec(mjSpec* spec) { + GetGlobalModel().Set(spec); +} + +std::string GetGlobalXmlSpec(const mjModel* m, char* error, int error_sz) { + return GetGlobalModel().ToXML(m, error, error_sz); +} diff --git a/src/xml/xml_global.h b/src/xml/xml_global.h new file mode 100644 index 00000000..d3b6f41d --- /dev/null +++ b/src/xml/xml_global.h @@ -0,0 +1,27 @@ +// Copyright 2026 DeepMind Technologies Limited +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#ifndef MUJOCO_SRC_XML_XML_GLOBAL_H_ +#define MUJOCO_SRC_XML_XML_GLOBAL_H_ + +#include + +#include + +void SetGlobalXmlSpec(mjSpec* spec = nullptr); + +std::string GetGlobalXmlSpec(const mjModel* m, char* error, int error_sz); + +#endif // MUJOCO_SRC_XML_XML_GLOBAL_H_