The goal is to eventually move almost all global state into Context.
src/Compression.cpp \
src/Compressor.cpp \
src/Config.cpp \
+ src/Context.cpp \
src/Decompressor.cpp \
src/NullCompressor.cpp \
src/NullDecompressor.cpp \
--- /dev/null
+// Copyright (C) 2020 Joel Rosdahl and other contributors
+//
+// See doc/AUTHORS.adoc for a complete list of contributors.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Software Foundation, Inc., 51
+// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#include "Context.hpp"
+
+Context::~Context()
+{
+}
--- /dev/null
+// Copyright (C) 2020 Joel Rosdahl and other contributors
+//
+// See doc/AUTHORS.adoc for a complete list of contributors.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Software Foundation, Inc., 51
+// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#pragma once
+
+#include "system.hpp"
+
+#include "ArgsInfo.hpp"
+#include "NonCopyable.hpp"
+
+struct Context : NonCopyable
+{
+ Context() = default;
+ ~Context();
+};
#include "ccache.hpp"
#include "ArgsInfo.hpp"
+#include "Context.hpp"
#include "FormatNonstdStringView.hpp"
#include "ProgressBar.hpp"
#include "ScopeGuard.hpp"
}
// Initialize ccache, must be called once before anything else is run.
-static void
+static Context&
initialize()
{
- bool enable_internal_trace = getenv("CCACHE_INTERNAL_TRACE");
- if (enable_internal_trace) {
-#ifdef MTR_ENABLED
- // We don't have any conf yet, so we can't use temp_dir() here.
- trace_init(format("%s/tmp.ccache-trace.%d", tmpdir(), (int)getpid()));
-#endif
- }
+ // This object is placed onto the heap so it is available in exit functions
+ // which run after main(). It is cleaned up by the last exit function.
+ Context* ctx = new Context{};
set_up_config(g_config);
init_log(g_config);
exitfn_init();
+ exitfn_delete_context(ctx);
exitfn_add_nullary(stats_flush);
exitfn_add_nullary(clean_up_pending_tmp_files);
+ bool enable_internal_trace = getenv("CCACHE_INTERNAL_TRACE");
+ if (enable_internal_trace) {
+#ifdef MTR_ENABLED
+ // We don't have any conf yet, so we can't use temp_dir() here.
+ trace_init(format("%s/tmp.ccache-trace.%d", tmpdir(), (int)getpid()));
+#endif
+ }
cc_log("=== CCACHE %s STARTED =========================================",
CCACHE_VERSION);
cc_log("Error: tracing is not enabled!");
#endif
}
+
+ return *ctx;
}
template<class T>
orig_args = args_init(argc, argv);
- initialize();
+ Context& ctx = initialize();
+ (void)ctx;
MTR_BEGIN("main", "find_compiler");
find_compiler(argv);
{"zero-stats", no_argument, 0, 'z'},
{0, 0, 0, 0}};
- initialize();
+ Context& ctx = initialize();
+ (void)ctx;
int c;
while ((c = getopt_long(argc, argv, "cCk:hF:M:po:sVxX:z", options, NULL))
#include "exitfn.hpp"
+#include "Context.hpp"
#include "legacy_util.hpp"
#include "logging.hpp"
};
static struct exit_function* exit_functions;
+static struct Context* context_to_clean_up;
static void
call_nullary_exit_function(void* context)
*q = p;
}
+// Remember a Context pointer to delete after all exit functions have run.
+// This function can only be called once.
+void
+exitfn_delete_context(Context* ctx)
+{
+ assert(context_to_clean_up == nullptr);
+ context_to_clean_up = ctx;
+}
+
// Call added functions.
void
exitfn_call(void)
p = p->next;
free(q);
}
+ if (context_to_clean_up) {
+ delete context_to_clean_up;
+ }
}
#pragma once
+struct Context;
+
void exitfn_init();
void exitfn_add_nullary(void (*function)());
void exitfn_add(void (*function)(void*), void* context);
void exitfn_add_last(void (*function)(void*), void* context);
+void exitfn_delete_context(Context* ctx);
void exitfn_call();