summaryrefslogtreecommitdiffstats
path: root/sal/rtl/alloc_cache.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--sal/rtl/alloc_cache.cxx225
1 files changed, 225 insertions, 0 deletions
diff --git a/sal/rtl/alloc_cache.cxx b/sal/rtl/alloc_cache.cxx
new file mode 100644
index 000000000..1f165cca1
--- /dev/null
+++ b/sal/rtl/alloc_cache.cxx
@@ -0,0 +1,225 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you 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 .
+ */
+
+#include "alloc_cache.hxx"
+#include "alloc_impl.hxx"
+#include "alloc_arena.hxx"
+#include <rtllifecycle.h>
+
+#include <cassert>
+#include <cstdlib>
+#include <string.h>
+#include <stdio.h>
+
+/**
+ provided for cache_type allocations, and hash_table resizing.
+
+ @internal
+*/
+static rtl_arena_type * gp_cache_arena = nullptr;
+
+namespace
+{
+
+rtl_cache_type * rtl_cache_activate(
+ rtl_cache_type * cache,
+ const char * name,
+ size_t objsize,
+ size_t objalign,
+ int (SAL_CALL * constructor)(void * obj, void * userarg),
+ void (SAL_CALL * destructor) (void * obj, void * userarg),
+ void * userarg
+)
+{
+ assert(cache);
+
+ snprintf (cache->m_name, sizeof(cache->m_name), "%s", name);
+
+ if (objalign == 0)
+ {
+ /* determine default alignment */
+ if (objsize >= RTL_MEMORY_ALIGNMENT_8)
+ objalign = RTL_MEMORY_ALIGNMENT_8;
+ else
+ objalign = RTL_MEMORY_ALIGNMENT_4;
+ }
+ else
+ {
+ /* ensure minimum alignment */
+ if(objalign < RTL_MEMORY_ALIGNMENT_4)
+ {
+ objalign = RTL_MEMORY_ALIGNMENT_4;
+ }
+ }
+ assert(RTL_MEMORY_ISP2(objalign));
+
+ cache->m_type_size = RTL_MEMORY_P2ROUNDUP(objsize, objalign);
+
+ cache->m_constructor = constructor;
+ cache->m_destructor = destructor;
+ cache->m_userarg = userarg;
+
+ return cache;
+}
+
+} //namespace
+
+rtl_cache_type * SAL_CALL rtl_cache_create(
+ const char * name,
+ sal_Size objsize,
+ sal_Size objalign,
+ int (SAL_CALL * constructor)(void * obj, void * userarg),
+ void (SAL_CALL * destructor) (void * obj, void * userarg),
+ void (SAL_CALL * /*reclaim*/) (void * userarg),
+ void * userarg,
+ rtl_arena_type *,
+ int
+) SAL_THROW_EXTERN_C()
+{
+ rtl_cache_type * result = nullptr;
+ sal_Size size = sizeof(rtl_cache_type);
+
+try_alloc:
+ result = static_cast<rtl_cache_type*>(rtl_arena_alloc (gp_cache_arena, &size));
+ if (result)
+ {
+ rtl_cache_type * cache = result;
+ memset (cache, 0, sizeof(rtl_cache_type));
+
+ result = rtl_cache_activate (
+ cache,
+ name,
+ objsize,
+ objalign,
+ constructor,
+ destructor,
+ userarg
+ );
+
+ if (!result)
+ {
+ /* activation failed */
+ rtl_arena_free (gp_cache_arena, cache, size);
+ }
+ }
+ else if (!gp_cache_arena)
+ {
+ ensureCacheSingleton();
+ if (gp_cache_arena)
+ {
+ /* try again */
+ goto try_alloc;
+ }
+ }
+ return result;
+}
+
+void SAL_CALL rtl_cache_destroy(rtl_cache_type * cache) SAL_THROW_EXTERN_C()
+{
+ if (cache)
+ {
+ rtl_arena_free (gp_cache_arena, cache, sizeof(rtl_cache_type));
+ }
+}
+
+void * SAL_CALL rtl_cache_alloc(rtl_cache_type * cache) SAL_THROW_EXTERN_C()
+{
+ void * obj = nullptr;
+
+ if (!cache)
+ return nullptr;
+
+ obj = std::malloc(cache->m_type_size);
+ if (obj && cache->m_constructor)
+ {
+ if (!(cache->m_constructor)(obj, cache->m_userarg))
+ {
+ /* construction failure */
+ std::free(obj);
+ obj = nullptr;
+ }
+ }
+ return obj;
+}
+
+void SAL_CALL rtl_cache_free(
+ rtl_cache_type * cache,
+ void * obj
+) SAL_THROW_EXTERN_C()
+{
+ if (obj && cache)
+ {
+ if (cache->m_destructor)
+ {
+ /* destruct object */
+ (cache->m_destructor)(obj, cache->m_userarg);
+ }
+ std::free(obj);
+ }
+}
+
+#if defined(SAL_UNX)
+
+void SAL_CALL rtl_secureZeroMemory(void *Ptr, sal_Size Bytes) SAL_THROW_EXTERN_C()
+{
+ //currently glibc doesn't implement memset_s
+ volatile char *p = static_cast<volatile char*>(Ptr);
+ while (Bytes--)
+ *p++ = 0;
+}
+
+#elif defined(_WIN32)
+
+void SAL_CALL rtl_secureZeroMemory(void *Ptr, sal_Size Bytes) SAL_THROW_EXTERN_C()
+{
+ RtlSecureZeroMemory(Ptr, Bytes);
+}
+
+#endif /* SAL_UNX || _WIN32 */
+
+void rtl_cache_init()
+{
+ /* cache: internal arena */
+ assert(!gp_cache_arena);
+
+ gp_cache_arena = rtl_arena_create (
+ "rtl_cache_internal_arena",
+ 64, /* quantum */
+ 0, /* no quantum caching */
+ nullptr, /* default source */
+ rtl_arena_alloc,
+ rtl_arena_free,
+ 0 /* flags */
+ );
+ assert(gp_cache_arena);
+
+ /* check 'gp_default_arena' initialization */
+ assert(gp_default_arena);
+}
+
+void rtl_cache_fini()
+{
+ if (gp_cache_arena)
+ {
+ rtl_arena_destroy (gp_cache_arena);
+ gp_cache_arena = nullptr;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */