1
0
mirror of https://github.com/TREX-CoE/qmckl.git synced 2024-06-30 00:44:52 +02:00
qmckl/src/qmckl_memory.org

170 lines
4.5 KiB
Org Mode
Raw Normal View History

2021-03-09 01:16:23 +01:00
#+TITLE: Memory management
#+SETUPFILE: ../docs/theme.setup
2020-10-22 01:24:14 +02:00
2021-03-09 01:16:23 +01:00
We override the allocation functions to enable the possibility of
optimized libraries to fine-tune the memory allocation.
2020-10-16 23:56:22 +02:00
2021-03-09 01:16:23 +01:00
* Headers :noexport:
#+NAME: filename
#+begin_src elisp tangle: no
(file-name-nondirectory (substring buffer-file-name 0 -4))
#+end_src
2020-10-16 23:56:22 +02:00
2021-03-09 01:16:23 +01:00
#+begin_src c :tangle (eval c)
#include <stdint.h>
#include <stdlib.h>
2021-03-10 12:58:38 +01:00
#include <assert.h>
2021-03-30 14:51:23 +02:00
#include "qmckl_error_type.h"
#include "qmckl_context_type.h"
#include "qmckl_context_private_type.h"
#include "qmckl_memory_func.h"
#include "qmckl_context_func.h"
#include "qmckl_error_func.h"
2021-03-09 01:16:23 +01:00
#+end_src
#+begin_src c :tangle (eval c_test) :noweb yes
2020-10-17 01:10:54 +02:00
#include "qmckl.h"
#include "munit.h"
2021-03-09 01:16:23 +01:00
MunitResult test_<<filename()>>() {
#+end_src
2020-10-16 23:56:22 +02:00
2021-03-10 12:58:38 +01:00
*
2021-03-18 23:55:50 +01:00
:PROPERTIES:
:UNNUMBERED: t
:END:
2021-03-10 12:58:38 +01:00
Memory allocation inside the library should be done with
~qmckl_malloc~. It lets the library choose how the memory will be
allocated, and a pointer is returned to the user. The context is
passed to let the library store data related to the allocation
inside the context. In this particular implementation of the library,
we store a list of allocated pointers so that all the memory can be
properly freed when the library is de-initialized.
If the allocation failed, the ~NULL~ pointer is returned.
# Header
2021-03-30 14:51:23 +02:00
#+begin_src c :tangle (eval h_func) :noexport
2021-03-10 12:58:38 +01:00
void* qmckl_malloc(qmckl_context context,
2021-03-09 01:16:23 +01:00
const size_t size);
#+end_src
2021-03-10 12:58:38 +01:00
In this implementation, we use ~calloc~ because it initializes the
memory block to zero, so structs will have ~NULL~-initialized pointers.
2021-03-10 12:58:38 +01:00
# Source
#+begin_src c :tangle (eval c)
void* qmckl_malloc(qmckl_context context, const size_t size) {
2020-10-16 23:56:22 +02:00
2021-03-30 14:51:23 +02:00
assert (qmckl_context_check(context) != QMCKL_NULL_CONTEXT);
void * pointer = calloc(size, (size_t) 1);
2021-03-10 12:58:38 +01:00
2021-03-30 14:51:23 +02:00
/*
2021-03-10 12:58:38 +01:00
if (qmckl_context_check(context) != QMCKL_NULL_CONTEXT) {
qmckl_exit_code rc;
rc = qmckl_context_append_memory(context, pointer, size);
assert (rc == QMCKL_SUCCESS);
}
2021-03-30 14:51:23 +02:00
*/
2021-03-10 12:58:38 +01:00
return pointer;
}
#+end_src
2021-03-18 23:55:50 +01:00
2021-03-10 12:58:38 +01:00
# Fortran interface
2021-03-30 14:51:23 +02:00
#+begin_src f90 :tangle (eval fh_func) :noexport
2020-11-05 15:27:25 +01:00
interface
type (c_ptr) function qmckl_malloc (context, size) bind(C)
use, intrinsic :: iso_c_binding
2021-03-30 14:51:23 +02:00
import
integer (qmckl_context), intent(in), value :: context
integer (c_int64_t) , intent(in), value :: size
2020-11-05 15:27:25 +01:00
end function qmckl_malloc
end interface
2021-03-09 01:16:23 +01:00
#+end_src
2021-03-18 23:55:50 +01:00
# Test :noexport:
2021-03-09 01:16:23 +01:00
#+begin_src c :tangle (eval c_test)
2021-03-18 23:55:50 +01:00
qmckl_context context = qmckl_context_create();
2021-03-09 01:16:23 +01:00
2021-03-18 23:55:50 +01:00
int *a = (int*) qmckl_malloc(context, 3*sizeof(int));
munit_assert(a != NULL);
a[0] = 1; munit_assert_int(a[0], ==, 1);
a[1] = 2; munit_assert_int(a[1], ==, 2);
a[2] = 3; munit_assert_int(a[2], ==, 3);
#+end_src
2021-03-09 01:16:23 +01:00
2021-03-18 23:55:50 +01:00
When freeing the memory with ~qmckl_free~, the context is passed, in
case some important information has been stored related to memory
allocation and needs to be updated.
2021-03-09 01:16:23 +01:00
2021-03-30 14:51:23 +02:00
#+begin_src c :tangle (eval h_func)
2021-03-09 01:16:23 +01:00
qmckl_exit_code qmckl_free(qmckl_context context,
void *ptr);
#+end_src
2021-03-30 14:51:23 +02:00
#+begin_src f90 :tangle (eval fh_func)
2020-11-05 15:27:25 +01:00
interface
2021-03-30 14:51:23 +02:00
integer (qmckl_exit_code) function qmckl_free (context, ptr) bind(C)
2020-11-05 15:27:25 +01:00
use, intrinsic :: iso_c_binding
2021-03-30 14:51:23 +02:00
import
integer (qmckl_context), intent(in), value :: context
2020-11-05 15:27:25 +01:00
type (c_ptr), intent(in), value :: ptr
2021-02-19 01:39:42 +01:00
end function qmckl_free
2020-11-05 15:27:25 +01:00
end interface
2021-03-09 01:16:23 +01:00
#+end_src
2021-03-05 03:45:30 +01:00
2021-03-18 23:55:50 +01:00
# Source
2021-03-09 01:16:23 +01:00
#+begin_src c :tangle (eval c)
2021-03-05 03:45:30 +01:00
qmckl_exit_code qmckl_free(qmckl_context context, void *ptr) {
2021-03-10 12:58:38 +01:00
if (qmckl_context_check(context) != QMCKL_NULL_CONTEXT) {
if (ptr == NULL) {
return qmckl_failwith(context,
QMCKL_INVALID_ARG_2,
"qmckl_free",
"NULL pointer");
}
2021-03-30 14:51:23 +02:00
/*
2021-03-10 12:58:38 +01:00
qmckl_exit_code rc;
rc = qmckl_context_remove_memory(context, ptr);
assert (rc == QMCKL_SUCCESS);
2021-03-30 14:51:23 +02:00
*/
2021-03-10 12:58:38 +01:00
}
2020-10-16 23:56:22 +02:00
free(ptr);
2021-03-05 03:45:30 +01:00
return QMCKL_SUCCESS;
2020-10-16 23:56:22 +02:00
}
2021-03-09 01:16:23 +01:00
#+end_src
2020-10-22 01:24:14 +02:00
2021-03-18 23:55:50 +01:00
# Test
#+begin_src c :tangle (eval c_test) :exports none
2021-03-05 03:45:30 +01:00
qmckl_exit_code rc;
2021-03-18 23:55:50 +01:00
munit_assert(a != NULL);
rc = qmckl_free(context, a);
munit_assert(rc == QMCKL_SUCCESS);
rc = qmckl_context_destroy(context);
2021-03-05 03:45:30 +01:00
munit_assert(rc == QMCKL_SUCCESS);
2021-02-19 01:39:42 +01:00
2021-03-09 01:16:23 +01:00
#+end_src
2020-10-16 23:56:22 +02:00
2021-03-09 01:16:23 +01:00
* End of files :noexport:
2020-10-16 23:56:22 +02:00
2021-03-09 01:16:23 +01:00
** Test
#+begin_src c :comments org :tangle (eval c_test)
2020-10-17 01:10:54 +02:00
return MUNIT_OK;
2020-10-22 01:24:14 +02:00
}
2020-10-17 01:10:54 +02:00
2021-03-09 01:16:23 +01:00
#+end_src
2020-11-05 15:27:25 +01:00
2021-03-09 01:16:23 +01:00
# -*- mode: org -*-
# vim: syntax=c