Repository: tailix/libkernaux (language: python)

Issue:
Mutex builder and tests



Discussion / hints:

Fix patch:
diff --git a/.gitignore b/.gitignore
index 7bd2910f..7a3a7aa7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -110,6 +110,7 @@
 /examples/cmdline
 /examples/fprintf
 /examples/fprintf_va
+/examples/generic_mutex
 /examples/memmap
 /examples/ntoa
 /examples/panic
diff --git a/ChangeLog b/ChangeLog
index ce2d424c..dddbe4ce 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,9 @@
 2022-06-20  Alex Kotov  <kotovalexarian@gmail.com>
 
-	* include/kernaux/alloc.h: Finished, made stable
+	* include/kernaux/alloc.h: Finished
+	* include/kernaux/generic/mutex.h: Mutex moved here
+	* include/kernaux/macro.h: Definitions "KERNAUX_ACCESS_*" made stable
+	* include/kernaux/macro.h: Macro "KERNAUX_PROTECTED_FIELD" added
 
 2022-06-18  Alex Kotov  <kotovalexarian@gmail.com>
 
diff --git a/Makefile.am b/Makefile.am
index 2f746071..859cf7d0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -19,12 +19,15 @@ endif
 libc/libc.la:
 	$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/libc libc.la
 
-AM_CFLAGS += -DKERNAUX_PRIVATE_NO
+AM_CFLAGS += -DKERNAUX_ACCESS_PRIVATE
 
 lib_LTLIBRARIES = libkernaux.la
 
-libkernaux_la_SOURCES = src/libc.h src/assert.c src/mutex.c
 libkernaux_la_LIBADD =
+libkernaux_la_SOURCES = \
+	src/assert.c \
+	src/libc.h \
+	src/generic/mutex.c
 
 if ASM_I386
 libkernaux_la_SOURCES += src/asm/i386.S
diff --git a/README.md b/README.md
index 807e2d00..140ca1be 100644
--- a/README.md
+++ b/README.md
@@ -44,11 +44,12 @@ zero). Work-in-progress APIs can change at any time.
     * [Example: Assert](/examples/assert.c)
     * [Example: Panic](/examples/panic.c)
   * Stack trace *(planned)*
-  * [Mutex](/include/kernaux/mutex.h) (*non-breaking since* **?.?.?**)
   * [Input/output](/include/kernaux/io.h) (*work in progress*)
   * Architecture-specific code (*work in progress*)
     * [Declarations](/include/kernaux/arch/)
     * [Functions](/include/kernaux/asm/)
+* Generic types
+  * [Mutex](/include/kernaux/generic/mutex.h) (*non-breaking since* **?.?.?**)
 * Device drivers (for debugging only)
   * [Serial console](/include/kernaux/console.h) (*work in progress*)
   * [Framebuffer](/include/kernaux/framebuffer.h) (*planned*)
@@ -94,7 +95,10 @@ zero). Work-in-progress APIs can change at any time.
 Define the following C preprocessor macros before including `<kernaux.h>` and
 `<kernaux/*.h>` files. They have effect on your code, not the library code.
 
-* `KERNAUX_DEBUG` - enable assertions
+* `KERNAUX_DEBUG` - enable assertions.
+* `KERNAUX_ACCESS_PRIVATE` - disable access modifier "private". Don't do this!
+* `KERNAUX_ACCESS_PROTECTED` - disable access modifier "protected". Only do this
+  (with `#define`) in a file where you implement an inherited type.
 
 ### Global variables
 
diff --git a/examples/Makefile.am b/examples/Makefile.am
index faf4a347..79740d22 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -45,6 +45,14 @@ fprintf_va_SOURCES = main.c fprintf_va.c
 endif
 endif
 
+#################
+# generic_mutex #
+#################
+
+TESTS += generic_mutex
+generic_mutex_LDADD = $(top_builddir)/libkernaux.la
+generic_mutex_SOURCES = main.c generic_mutex.c
+
 ##########
 # memmap #
 ##########
diff --git a/examples/generic_mutex.c b/examples/generic_mutex.c
new file mode 100644
index 00000000..370bbbb4
--- /dev/null
+++ b/examples/generic_mutex.c
@@ -0,0 +1,76 @@
+//============
+// my_mutex.c
+//============
+
+// To not always use macro "KERNAUX_PROTECTED_FIELD" around the names of
+// structure fields you may define "KERNAUX_ACCESS_PROTECTED" before including
+// any other headers, but ONLY in the file where you implement a generic type.
+//
+#define KERNAUX_ACCESS_PROTECTED
+
+//============
+// my_mutex.h
+//============
+
+#include <kernaux/generic/mutex.h>
+#include <pthread.h>
+
+typedef struct MyMutex {
+    struct KernAux_Mutex mutex;
+    pthread_mutex_t pthread_mutex;
+} *MyMutex;
+
+struct MyMutex MyMytex_create();
+
+//============
+// my_mutex.c
+//============
+
+#include <kernaux/generic/mutex.h>
+#include <pthread.h>
+#include <stdlib.h>
+
+static void MyMutex_lock  (void *mutex);
+static void MyMutex_unlock(void *mutex);
+
+struct MyMutex MyMutex_create()
+{
+    struct MyMutex my_mutex;
+    my_mutex.mutex.lock = MyMutex_lock;
+    my_mutex.mutex.unlock = MyMutex_unlock;
+    if (pthread_mutex_init(&my_mutex.pthread_mutex, NULL) != 0) abort();
+    return my_mutex;
+}
+
+void MyMutex_lock(void *const mutex)
+{
+    MyMutex my_mutex = mutex;
+    pthread_mutex_lock(&my_mutex->pthread_mutex);
+}
+
+void MyMutex_unlock(void *const mutex)
+{
+    MyMutex my_mutex = mutex;
+    pthread_mutex_unlock(&my_mutex->pthread_mutex);
+}
+
+//========
+// main.c
+//========
+
+static int shared_counter = 0;
+
+void example_main()
+{
+    // Create mutex
+    struct MyMutex my_mutex = MyMutex_create();
+
+    // Lock mutex
+    KernAux_Mutex_lock(&my_mutex.mutex);
+
+    // Access shared data
+    ++shared_counter;
+
+    // Unlock mutex
+    KernAux_Mutex_unlock(&my_mutex.mutex);
+}
diff --git a/include/Makefile.am b/include/Makefile.am
index 8755e0f4..16539f65 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -5,8 +5,8 @@ nobase_include_HEADERS = \
 	kernaux/arch/x86_64.h \
 	kernaux/assert.h \
 	kernaux/macro.h \
-	kernaux/mutex.h \
-	kernaux/version.h
+	kernaux/version.h \
+	kernaux/generic/mutex.h
 
 if ASM_I386
 nobase_include_HEADERS += kernaux/asm/i386.h
diff --git a/include/kernaux.h.in b/include/kernaux.h.in
index eabdfee0..834e462d 100644
--- a/include/kernaux.h.in
+++ b/include/kernaux.h.in
@@ -5,9 +5,10 @@
 
 #include <kernaux/assert.h>
 #include <kernaux/macro.h>
-#include <kernaux/mutex.h>
 #include <kernaux/version.h>
 
+#include <kernaux/generic/mutex.h>
+
 @comment_line_alloc@#include <kernaux/alloc.h>
 @comment_line_cmdline@#include <kernaux/cmdline.h>
 @comment_line_console@#include <kernaux/console.h>
diff --git a/include/kernaux/alloc.h b/include/kernaux/alloc.h
index 2a411077..15c25bc1 100644
--- a/include/kernaux/alloc.h
+++ b/include/kernaux/alloc.h
@@ -6,7 +6,7 @@ extern "C" {
 #endif
 
 #include <kernaux/macro.h>
-#include <kernaux/mutex.h>
+#include <kernaux/generic/mutex.h>
 
 #include <stddef.h>
 
diff --git a/include/kernaux/mutex.h b/include/kernaux/generic/mutex.h
similarity index 51%
rename from include/kernaux/mutex.h
rename to include/kernaux/generic/mutex.h
index 7dade04e..bcd9786a 100644
--- a/include/kernaux/mutex.h
+++ b/include/kernaux/generic/mutex.h
@@ -5,15 +5,14 @@
 extern "C" {
 #endif
 
-#define KERNAUX_MUTEX_EXTRA_DATA_SIZE (32)
+#include <kernaux/macro.h>
 
-typedef void (*KernAux_Mutex_Lock  )(void *extra_data);
-typedef void (*KernAux_Mutex_Unlock)(void *extra_data);
+typedef void (*KernAux_Mutex_Lock  )(void *mutex);
+typedef void (*KernAux_Mutex_Unlock)(void *mutex);
 
 typedef struct KernAux_Mutex {
-    KernAux_Mutex_Lock lock;
-    KernAux_Mutex_Unlock unlock;
-    char extra_data[KERNAUX_MUTEX_EXTRA_DATA_SIZE];
+    KernAux_Mutex_Lock   KERNAUX_PROTECTED_FIELD(lock);
+    KernAux_Mutex_Unlock KERNAUX_PROTECTED_FIELD(unlock);
 } *KernAux_Mutex;
 
 void KernAux_Mutex_lock  (KernAux_Mutex mutex);
diff --git a/include/kernaux/macro.h b/include/kernaux/macro.h
index d00f2cec..155687c5 100644
--- a/include/kernaux/macro.h
+++ b/include/kernaux/macro.h
@@ -5,11 +5,18 @@
 extern "C" {
 #endif
 
-#ifdef KERNAUX_PRIVATE_NO
-#define KERNAUX_PRIVATE_FIELD(id) id
+#ifdef KERNAUX_ACCESS_PRIVATE
+#   define KERNAUX_PRIVATE_FIELD(id) id
+#   define KERNAUX_PROTECTED_FIELD(id) id
 #else
-#define KERNAUX_PRIVATE_FIELD(id) _private_##id
-#endif
+#   define KERNAUX_PRIVATE_FIELD(id) _private_##id
+
+#   ifdef KERNAUX_ACCESS_PROTECTED
+#       define KERNAUX_PROTECTED_FIELD(id) id
+#   else
+#       define KERNAUX_PROTECTED_FIELD(id) _protected_##id
+#   endif
+#endif // KERNAUX_ACCESS_PRIVATE
 
 #ifdef __cplusplus
 }
diff --git a/src/mutex.c b/src/generic/mutex.c
similarity index 75%
rename from src/mutex.c
rename to src/generic/mutex.c
index 9fd46880..16f4e9a2 100644
--- a/src/mutex.c
+++ b/src/generic/mutex.c
@@ -3,14 +3,14 @@
 #endif
 
 #include <kernaux/assert.h>
-#include <kernaux/mutex.h>
+#include <kernaux/generic/mutex.h>
 
 void KernAux_Mutex_lock(const KernAux_Mutex mutex)
 {
     KERNAUX_ASSERT(mutex);
     KERNAUX_ASSERT(mutex->lock);
 
-    mutex->lock(mutex->extra_data);
+    mutex->lock(mutex);
 }
 
 void KernAux_Mutex_unlock(const KernAux_Mutex mutex)
@@ -18,5 +18,5 @@ void KernAux_Mutex_unlock(const KernAux_Mutex mutex)
     KERNAUX_ASSERT(mutex);
     KERNAUX_ASSERT(mutex->unlock);
 
-    mutex->unlock(mutex->extra_data);
+    mutex->unlock(mutex);
 }


Test patch:
diff --git a/tests/test_alloc.c b/tests/test_alloc.c
index 8523539a..420bc8e3 100644
--- a/tests/test_alloc.c
+++ b/tests/test_alloc.c
@@ -2,7 +2,7 @@
 #include "config.h"
 #endif
 
-#define KERNAUX_PRIVATE_NO
+#define KERNAUX_ACCESS_PRIVATE
 
 #include <kernaux/alloc.h>
 
diff --git a/tests/test_memmap.c b/tests/test_memmap.c
index 98638fca..00d72ca5 100644
--- a/tests/test_memmap.c
+++ b/tests/test_memmap.c
@@ -2,7 +2,7 @@
 #include "config.h"
 #endif
 
-#define KERNAUX_PRIVATE_NO
+#define KERNAUX_ACCESS_PRIVATE
 
 #include <kernaux/assert.h>
 #include <kernaux/memmap.h>