From 7ec14eb603babeca5fc582138f4539af7a445702 Mon Sep 17 00:00:00 2001
From: wangzhengquan <wangzhengquan85@126.com>
Date: 星期二, 19 一月 2021 17:13:51 +0800
Subject: [PATCH] docxygen

---
 test/futex_demo.cpp              |  161 ++++++++++++++++++++
 test_net_socket/CMakeLists.txt   |    8 
 doc/CMakeLists.txt               |   28 +++
 src/CMakeLists.txt               |   55 +++---
 test/futex_test.cpp              |  148 ++++++++++++++++++
 doc/linked-lock-free-code.png    |    0 
 build.sh                         |    4 
 CMakeLists.txt                   |   11 +
 doc/基于共享内存的生产者消费者模式的无锁队列的设计方案.md |    2 
 test/CMakeLists.txt              |   22 ++
 doc/Doxyfile.in                  |    4 
 11 files changed, 401 insertions(+), 42 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 00acf78..a295a37 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,7 @@
 cmake_minimum_required(VERSION 3.5)
 
 # set the project name and version
-project(B_BUS VERSION 3.0)
+project(B_BUS VERSION 2.2)
 
 # specify the C++ standard
 set(CMAKE_CXX_STANDARD 11)
@@ -17,8 +17,13 @@
 
 
 list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/include/usgcommon")
-list(APPEND EXTRA_LIBS ${PROJECT_SOURCE_DIR}/lib/libusgcommon.a pthread)
+list(APPEND EXTRA_LIBS ${PROJECT_SOURCE_DIR}/lib/libusgcommon.a pthread rt)
 
 add_subdirectory(${PROJECT_SOURCE_DIR}/src)
 add_subdirectory(${PROJECT_SOURCE_DIR}/test)
-add_subdirectory(${PROJECT_SOURCE_DIR}/test_net_socket)
\ No newline at end of file
+add_subdirectory(${PROJECT_SOURCE_DIR}/test_net_socket)
+# build api doc
+if (CMAKE_BUILD_TYPE MATCHES "^[Rr]elease")
+    # build the docs
+    add_subdirectory(${PROJECT_SOURCE_DIR}/doc)
+endif()
diff --git a/build.sh b/build.sh
index 772ddf4..df18217 100755
--- a/build.sh
+++ b/build.sh
@@ -37,9 +37,9 @@
 # -DBUILD_SHARED_LIBS=ON
 # -DCMAKE_INSTALL_PREFIX=$(pwd/../dest)
 # -DQCA_MAN_INSTALL_DIR:PATH=/usr/share/man 
-cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/../dest" -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DSUPPORT_RDMA=OFF ..
+cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/../dest" -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DBUILD_SHARED_LIBS=ON -DSUPPORT_RDMA=OFF ..
 
 cmake --build .
 
-#cmake --build . --target install
+cmake --build . --target install
  
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
new file mode 100644
index 0000000..95712a7
--- /dev/null
+++ b/doc/CMakeLists.txt
@@ -0,0 +1,28 @@
+# first we can indicate the documentation build as an option and set it to ON by default
+option(BUILD_DOC "Build documentation" ON)
+
+# check if Doxygen is installed
+find_package(Doxygen)
+if (DOXYGEN_FOUND)
+    # set input and output files
+    set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in)
+    set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
+
+    # request to configure the file
+    configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY)
+    message("Doxygen build started")
+
+    # note the option ALL which allows to build the docs together with the application
+    add_custom_target( doc_doxygen ALL
+        COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
+        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+        COMMENT "Generating API documentation with Doxygen"
+        VERBATIM )
+
+    install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/api"
+        DESTINATION doc
+    )
+  
+else (DOXYGEN_FOUND)
+  message("Doxygen need to be installed to generate the doxygen documentation. To install type common `sudo apt install -y doxygen texlive-latex-base graphviz` ")
+endif (DOXYGEN_FOUND)
diff --git a/Doxyfile b/doc/Doxyfile.in
similarity index 98%
rename from Doxyfile
rename to doc/Doxyfile.in
index b7ad6bb..468cb0a 100644
--- a/Doxyfile
+++ b/doc/Doxyfile.in
@@ -58,7 +58,7 @@
 # entered, it will be relative to the location where doxygen was started. If
 # left blank the current directory will be used.
 
-OUTPUT_DIRECTORY       = build/doc
+OUTPUT_DIRECTORY       = @CMAKE_CURRENT_BINARY_DIR@/api
 
 # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
 # directories (in 2 levels) under the output directory of each output format and
@@ -771,7 +771,7 @@
 # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
 # Note: If this tag is empty the current directory is searched.
 
-INPUT                  = src
+INPUT                  = @CMAKE_SOURCE_DIR@/src @CMAKE_CURRENT_SOURCE_DIR@
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
diff --git a/doc/code.png b/doc/linked-lock-free-code.png
similarity index 100%
rename from doc/code.png
rename to doc/linked-lock-free-code.png
Binary files differ
diff --git "a/doc/\345\237\272\344\272\216\345\205\261\344\272\253\345\206\205\345\255\230\347\232\204\347\224\237\344\272\247\350\200\205\346\266\210\350\264\271\350\200\205\346\250\241\345\274\217\347\232\204\346\227\240\351\224\201\351\230\237\345\210\227\347\232\204\350\256\276\350\256\241\346\226\271\346\241\210.md" "b/doc/\345\237\272\344\272\216\345\205\261\344\272\253\345\206\205\345\255\230\347\232\204\347\224\237\344\272\247\350\200\205\346\266\210\350\264\271\350\200\205\346\250\241\345\274\217\347\232\204\346\227\240\351\224\201\351\230\237\345\210\227\347\232\204\350\256\276\350\256\241\346\226\271\346\241\210.md"
index 54db603..6d45155 100644
--- "a/doc/\345\237\272\344\272\216\345\205\261\344\272\253\345\206\205\345\255\230\347\232\204\347\224\237\344\272\247\350\200\205\346\266\210\350\264\271\350\200\205\346\250\241\345\274\217\347\232\204\346\227\240\351\224\201\351\230\237\345\210\227\347\232\204\350\256\276\350\256\241\346\226\271\346\241\210.md"
+++ "b/doc/\345\237\272\344\272\216\345\205\261\344\272\253\345\206\205\345\255\230\347\232\204\347\224\237\344\272\247\350\200\205\346\266\210\350\264\271\350\200\205\346\250\241\345\274\217\347\232\204\346\227\240\351\224\201\351\230\237\345\210\227\347\232\204\350\256\276\350\256\241\346\226\271\346\241\210.md"
@@ -15,7 +15,7 @@
 ## 2 鏃犻攣闃熷垪锛團ree Lock锛夌殑瀹炵幇
 鏃犻攣闃熷垪鏄敤缁嗙矑搴︾殑鍘熷瓙閿佸疄鐜扮殑锛屽杩涚▼鎿嶄綔鏃舵棤闃诲骞跺彂鎬ц兘楂樸�傜綉涓婃湁浜旇姳鍏棬鐨勭浉鍏崇畻娉曞疄鐜般�傛垜瀵规瘮浜嗕竴涓嬶紝鍐冲畾閲囩敤涓嬮潰鐨勮繖涓�傝繖涓畻娉曟�ц兘濂芥槸涓�鏂归潰锛屽畠鍚屾椂涔熻В鍐充簡闃熷垪涓虹┖鏃跺苟鍙戞搷浣滃彲鑳藉嚭鐜扮殑闂锛屼互鍙夾BA鐨勯棶棰樸��
 
-![](./code.png)
+![](./linked-lock-free-code.png)
 
 ## 3 鐢熶骇鑰呮秷璐硅�呬箣闂寸殑鍗忎綔
 
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e0913e7..d659558 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -45,34 +45,35 @@
 # install rules
 install(TARGETS shm_queue DESTINATION lib)
 install(FILES 
-	socket/socket_def.h
-	socket/net_conn_pool.h
-	socket/bus_server_socket.h
-	socket/shm_socket.h
-	socket/net_mod_socket.h
-	socket/shm_stream_mod_socket.h
-	socket/net_mod_server_socket_wrapper.h
-	socket/net_mod_socket_io.h
-	socket/net_mod_server_socket.h
-	socket/shm_mod_socket.h
-	socket/net_mod_socket_wrapper.h
-	socket/bus_server_socket_wrapper.h
-	key_def.h
-	bus_error.h
-	logger_factory.h
-	queue/linked_lock_free_queue.h
-	queue/array_lock_free_queue2.h
-	queue/array_lock_free_queue.h
-	queue/shm_queue.h
-	queue/shm_queue_wrapper.h
-	queue/lock_free_queue.h
-	shm/hashtable.h
-	shm/mem_pool.h
-	shm/mm.h
-	shm/shm_allocator.h
-	shm/shm_mm_wraper.h
+  socket/socket_def.h
+  socket/net_conn_pool.h
+  socket/bus_server_socket.h
+  socket/shm_socket.h
+  socket/net_mod_socket.h
+  socket/shm_stream_mod_socket.h
+  socket/net_mod_server_socket_wrapper.h
+  socket/net_mod_socket_io.h
+  socket/net_mod_server_socket.h
+  socket/shm_mod_socket.h
+  socket/net_mod_socket_wrapper.h
+  socket/bus_server_socket_wrapper.h
+  key_def.h
+  bus_error.h
+  px_sem_util.h
+  logger_factory.h
+  queue/linked_lock_free_queue.h
+  queue/array_lock_free_queue2.h
+  queue/array_lock_free_queue.h
+  queue/shm_queue.h
+  queue/lock_free_queue.h
+  shm/hashtable.h
+  shm/mem_pool.h
+  shm/mm.h
+  shm/shm_mm_wrapper.h
+  shm/shm_allocator.h
+
   DESTINATION include)
 
-install(FILES "${PROJECT_BINARY_DIR}/src/BusConfig.h"
+install(FILES "${PROJECT_BINARY_DIR}/src/bus_config.h"
 	DESTINATION include
 )
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index eebe164..a853353 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,11 +1,27 @@
 # add the executable
 add_executable(test1 test1.cpp )
-target_link_libraries(test1 PUBLIC  ${EXTRA_LIBS} )
-
-target_include_directories(test1 PUBLIC
+target_link_libraries(test1 PRIVATE  ${EXTRA_LIBS} )
+target_include_directories(test1 PRIVATE
                             "${PROJECT_BINARY_DIR}"
                              ${EXTRA_INCLUDES}
                             )
 
+
+add_executable(futex_demo futex_demo.cpp )
+target_link_libraries(futex_demo PRIVATE  ${EXTRA_LIBS} )
+target_include_directories(futex_demo PRIVATE
+                            "${PROJECT_BINARY_DIR}"
+                             ${EXTRA_INCLUDES}
+                            )
+
+
+add_executable(futex_test futex_test.cpp )
+target_link_libraries(futex_test PRIVATE  ${EXTRA_LIBS} )
+target_include_directories(futex_test PRIVATE
+                            "${PROJECT_BINARY_DIR}"
+                             ${EXTRA_INCLUDES}
+                            )
+
+
 # add the install targets
 install(TARGETS test1 DESTINATION bin)
diff --git a/test/futex_demo.cpp b/test/futex_demo.cpp
new file mode 100644
index 0000000..d6887e8
--- /dev/null
+++ b/test/futex_demo.cpp
@@ -0,0 +1,161 @@
+/* futex_demo.c
+
+Usage: futex_demo [nloops]
+(Default: 5)
+
+Demonstrate the use of futexes in a program where parent and child
+use a pair of futexes located inside a shared anonymous mapping to
+synchronize access to a shared resource: the terminal. The two
+processes each write 'num-loops' messages to the terminal and employ
+a synchronization protocol that ensures that they alternate in
+writing messages.
+*/
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+#include <sys/syscall.h>
+#include <linux/futex.h>
+#include <sys/time.h>
+#include "usg_common.h"
+#include <sys/mman.h>
+#include <sys/stat.h>        /* For mode constants */
+#include <fcntl.h>           /* For O_* constants */
+
+
+#define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \
+} while (0)
+
+static int *futex1, *futex2, *iaddr;
+
+  static int
+futex(int *uaddr, int futex_op, int val,
+    const struct timespec *timeout, int *uaddr2, int val3)
+{
+  return syscall(SYS_futex, uaddr, futex_op, val,
+      timeout, uaddr, val3);
+}
+
+/* Acquire the futex pointed to by 'futexp': wait for its value to
+   become 1, and then set the value to 0. */
+
+  static void
+fwait(int *futexp)
+{
+  int s;
+
+  /* __sync_bool_compare_and_swap(ptr, oldval, newval) is a gcc
+     built-in function.  It atomically performs the equivalent of:
+
+     if (*ptr == oldval)
+   *ptr = newval;
+
+   It returns true if the test yielded true and *ptr was updated.
+   The alternative here would be to employ the equivalent atomic
+   machine-language instructions.  For further information, see
+   the GCC Manual. */
+  while (1) {
+
+    /* Is the futex available? */
+
+    if (__sync_bool_compare_and_swap(futexp, 1, 0))
+      break;      /* Yes */
+
+    /* Futex is not available; wait */
+
+    s = futex(futexp, FUTEX_WAIT, 0, NULL, NULL, 0);
+    if (s == -1 && errno != EAGAIN)
+      errExit("futex-FUTEX_WAIT");
+  }
+}
+
+/* Release the futex pointed to by 'futexp': if the futex currently
+   has the value 0, set its value to 1 and the wake any futex waiters,
+   so that if the peer is blocked in fpost(), it can proceed. */
+
+  static void
+fpost(int *futexp)
+{
+  int s;
+
+  /* __sync_bool_compare_and_swap() was described in comments above */
+
+  if (__sync_bool_compare_and_swap(futexp, 0, 1)) {
+
+    s = futex(futexp, FUTEX_WAKE, 1, NULL, NULL, 0);
+    if (s  == -1)
+      errExit("futex-FUTEX_WAKE");
+  }
+}
+
+  int
+main(int argc, char *argv[])
+{
+  pid_t childPid;
+  int j, nloops;
+
+  int flags, opt, fd;
+  mode_t perms;
+  size_t size;
+
+  setbuf(stdout, NULL);
+
+  nloops = (argc > 1) ? atoi(argv[1]) : 5;
+
+  flags = O_RDWR | O_CREAT | O_EXCL;
+  perms = S_IRUSR | S_IWUSR;
+  size = sizeof(int) * 2;
+
+  fd = shm_open("futex_demo", flags, perms);
+  if (fd == -1)
+  errExit("shm_open");
+  if (ftruncate(fd, size) == -1)
+  errExit("ftruncate");
+
+  /* Create a shared anonymous mapping that will hold the futexes.
+     Since the futexes are being shared between processes, we
+     subsequently use the "shared" futex operations (i.e., not the
+     ones suffixed "_PRIVATE") */
+
+  iaddr = (int *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, fd, 0);
+  if (iaddr == MAP_FAILED)
+    errExit("mmap");
+
+  futex1 = &iaddr[0];
+  futex2 = &iaddr[1];
+
+  *futex1 = 0;        /* State: unavailable */
+  *futex2 = 1;        /* State: available */
+
+  /* Create a child process that inherits the shared anonymous
+     mapping */
+
+  childPid = fork();
+  if (childPid == -1)
+    errExit("fork");
+
+  if (childPid == 0) {        /* Child */
+    for (j = 0; j < nloops; j++) {
+      fwait(futex1);
+      printf("Child  (%ld) %d\n", (long) getpid(), j);
+      fpost(futex2);
+    }
+
+    exit(EXIT_SUCCESS);
+  }
+
+  /* Parent falls through to here */
+
+  for (j = 0; j < nloops; j++) {
+    fwait(futex2);
+    printf("Parent (%ld) %d\n", (long) getpid(), j);
+    fpost(futex1);
+  }
+
+  wait(NULL);
+
+  exit(EXIT_SUCCESS);
+}
+
diff --git a/test/futex_test.cpp b/test/futex_test.cpp
new file mode 100644
index 0000000..55d77f4
--- /dev/null
+++ b/test/futex_test.cpp
@@ -0,0 +1,148 @@
+/* futex_demo.c
+
+Usage: futex_demo [nloops]
+(Default: 5)
+
+Demonstrate the use of futexes in a program where parent and child
+use a pair of futexes located inside a shared anonymous mapping to
+synchronize access to a shared resource: the terminal. The two
+processes each write 'num-loops' messages to the terminal and employ
+a synchronization protocol that ensures that they alternate in
+writing messages.
+*/
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+#include <sys/syscall.h>
+#include <linux/futex.h>
+#include <sys/time.h>
+#include "usg_common.h"
+#include <sys/mman.h>
+#include <sys/stat.h>        /* For mode constants */
+#include <fcntl.h>           /* For O_* constants */
+
+
+#define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \
+} while (0)
+
+static int *futex1, *futex2, *iaddr;
+
+  static int
+futex(int *uaddr, int futex_op, int val,
+    const struct timespec *timeout, int *uaddr2, int val3)
+{
+  return syscall(SYS_futex, uaddr, futex_op, val,
+      timeout, uaddr, val3);
+}
+
+/* Acquire the futex pointed to by 'futexp': wait for its value to
+   become 1, and then set the value to 0. */
+
+  static void
+fwait(int *futexp)
+{
+  int s;
+
+  /* __sync_bool_compare_and_swap(ptr, oldval, newval) is a gcc
+     built-in function.  It atomically performs the equivalent of:
+
+     if (*ptr == oldval)
+   *ptr = newval;
+
+   It returns true if the test yielded true and *ptr was updated.
+   The alternative here would be to employ the equivalent atomic
+   machine-language instructions.  For further information, see
+   the GCC Manual. */
+  while (1) {
+
+    /* Is the futex available? */
+
+    if (__sync_bool_compare_and_swap(futexp, 1, 0))
+      break;      /* Yes */
+
+    /* Futex is not available; wait */
+
+    s = futex(futexp, FUTEX_WAIT, 0, NULL, NULL, 0);
+    if (s == -1 && errno != EAGAIN)
+      errExit("futex-FUTEX_WAIT");
+  }
+}
+
+/* Release the futex pointed to by 'futexp': if the futex currently
+   has the value 0, set its value to 1 and the wake any futex waiters,
+   so that if the peer is blocked in fpost(), it can proceed. */
+
+  static void
+fpost(int *futexp)
+{
+  int s;
+
+  /* __sync_bool_compare_and_swap() was described in comments above */
+
+  if (__sync_bool_compare_and_swap(futexp, 0, 1)) {
+
+    s = futex(futexp, FUTEX_WAKE, 1, NULL, NULL, 0);
+    if (s  == -1)
+      errExit("futex-FUTEX_WAKE");
+  }
+}
+
+  int
+main(int argc, char *argv[])
+{
+  pid_t childPid;
+  int j, nloops;
+
+  int   opt, fd;
+  mode_t perms;
+  size_t size;
+  bool first = true;
+
+  setbuf(stdout, NULL);
+
+  nloops = (argc > 1) ? atoi(argv[1]) : 5;
+
+  perms = S_IRUSR | S_IWUSR;
+  size = sizeof(int) ;
+
+  fd = shm_open("futex_test",  O_RDWR | O_CREAT  | O_EXCL, perms);
+  if (fd == -1 && errno == EEXIST) {
+    fd = shm_open("futex_test", O_RDWR, perms);
+    first = false;
+  } 
+  
+  if(fd == -1) {
+      errExit("shm_open");
+  }
+  if (ftruncate(fd, size) == -1)
+  errExit("ftruncate");
+
+  /* Create a shared anonymous mapping that will hold the futexes.
+     Since the futexes are being shared between processes, we
+     subsequently use the "shared" futex operations (i.e., not the
+     ones suffixed "_PRIVATE") */
+
+  iaddr = (int *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+  if (iaddr == MAP_FAILED)
+    errExit("mmap");
+
+  futex1 = iaddr;
+
+  if(first) {
+   
+    *futex1 = 1;  
+  }
+
+  /* State: available */
+
+  fwait(futex1);
+  printf("(%ld) 杩涘叆浜掓枼鍖篭n", (long) getpid());
+  sleep(5);
+  fpost(futex1);
+
+  exit(EXIT_SUCCESS);
+}
+
diff --git a/test_net_socket/CMakeLists.txt b/test_net_socket/CMakeLists.txt
index 938be49..dddf7f8 100644
--- a/test_net_socket/CMakeLists.txt
+++ b/test_net_socket/CMakeLists.txt
@@ -13,14 +13,14 @@
 
 # add the executable
 add_executable(test_net_mod_socket test_net_mod_socket.cpp  ${CMAKE_CURRENT_BINARY_DIR}/net_mod_socket.sh)
-target_link_libraries(test_net_mod_socket PUBLIC shm_queue  ${EXTRA_LIBS} )
+target_link_libraries(test_net_mod_socket PRIVATE shm_queue  ${EXTRA_LIBS} )
 
 add_executable(heart_beat heart_beat.cpp ${CMAKE_CURRENT_BINARY_DIR}/heart_beat.sh)
-target_link_libraries(heart_beat PUBLIC shm_queue )
-# target_link_libraries(heart_beat PUBLIC shm_queue  ${EXTRA_LIBS} )
+target_link_libraries(heart_beat PRIVATE shm_queue )
+# target_link_libraries(heart_beat PRIVATE shm_queue  ${EXTRA_LIBS} )
 
 
-target_include_directories(test_net_mod_socket PUBLIC
+target_include_directories(test_net_mod_socket PRIVATE
                             "${PROJECT_BINARY_DIR}"
                              ${EXTRA_INCLUDES}
                             )

--
Gitblit v1.8.0