From 047f801078a52042ef02750b577233d115ed0f57 Mon Sep 17 00:00:00 2001
From: lichao <lichao@aiotlink.com>
Date: 星期二, 13 四月 2021 17:12:25 +0800
Subject: [PATCH] rename library, add box.

---
 box/center_main.cc   |   35 +++++
 .gitignore           |    3 
 box/center.cpp       |    0 
 box/signalhandle.h   |   41 ++++++
 src/CMakeLists.txt   |    2 
 box/CMakeLists.txt   |   15 ++
 box/center.h         |    0 
 utest/CMakeLists.txt |    2 
 box/box.h            |   27 ++++
 CMakeLists.txt       |    2 
 box/signalhandle.cpp |   70 +++++++++++
 box/box.cc           |  134 ++++++++++++++++++++++
 12 files changed, 329 insertions(+), 2 deletions(-)

diff --git a/.gitignore b/.gitignore
index 8e81403..d6ac3de 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,6 @@
 utest/utest
 *.bak
 gmon.out
+box/bhshmqbox
+box/bhshmq_center
+box/help
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 23f3ce7..fa3cc44 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -16,7 +16,9 @@
 
 add_subdirectory(${PROJECT_SOURCE_DIR}/proto/cpp proto)
 include_directories(${CMAKE_CURRENT_BINARY_DIR}/proto)
+include_directories(${PROJECT_SOURCE_DIR}/box)
 
 add_subdirectory(${PROJECT_SOURCE_DIR}/src)
+add_subdirectory(${PROJECT_SOURCE_DIR}/box)
 add_subdirectory(${PROJECT_SOURCE_DIR}/utest)
 
diff --git a/box/CMakeLists.txt b/box/CMakeLists.txt
new file mode 100644
index 0000000..3ecb694
--- /dev/null
+++ b/box/CMakeLists.txt
@@ -0,0 +1,15 @@
+
+file(GLOB lib_sources "./*.cpp")
+file(GLOB exe_sources "./*.cc")
+
+set(Target bhshmqbox)
+set(BinTarget ${Target}-bin)
+
+include_directories(../src)
+add_library(${Target} ${lib_sources})
+add_executable(${BinTarget} ${exe_sources})
+
+target_link_libraries(${Target} bhome_shmq bhome_msg pthread rt)
+target_link_libraries(${BinTarget} ${Target} boost_filesystem )
+set_target_properties(${BinTarget}
+	PROPERTIES OUTPUT_NAME ${Target})
diff --git a/box/box.cc b/box/box.cc
new file mode 100644
index 0000000..dab1c42
--- /dev/null
+++ b/box/box.cc
@@ -0,0 +1,134 @@
+/*
+ * =====================================================================================
+ *
+ *       Filename:  box.cpp
+ *
+ *    Description:  
+ *
+ *        Version:  1.0
+ *        Created:  2021骞�04鏈�13鏃� 15鏃�21鍒�44绉�
+ *       Revision:  none
+ *       Compiler:  gcc
+ *
+ *         Author:  Li Chao (), lichao@aiotlink.com
+ *   Organization:  
+ *
+ * =====================================================================================
+ */
+#include "box.h"
+#include <boost/filesystem/path.hpp>
+#include <map>
+#include <unordered_map>
+
+namespace fs = boost::filesystem;
+
+namespace
+{
+
+class Box
+{
+public:
+	bool Install(const std::string &name, MainFunc const &func, const std::string &desc)
+	{
+		return functions_.emplace(name, FuncInfo{name, func, desc}).second;
+	}
+	bool Find(const std::string &name, MainFunc &func)
+	{
+		auto pos = functions_.find(name);
+		if (pos != functions_.end()) {
+			func = pos->second.func_;
+			return true;
+		}
+		return false;
+	}
+	void Apply(std::function<void(const std::string &id, const std::string &desc)> f) const
+	{
+		for (auto &kv : functions_) {
+			f(kv.second.id_, kv.second.desc_);
+		}
+	}
+
+private:
+	struct FuncInfo {
+		std::string id_;
+		MainFunc func_;
+		std::string desc_;
+	};
+	std::unordered_map<std::string, FuncInfo> functions_;
+};
+
+Box &TheBox()
+{
+	static Box box;
+	return box;
+}
+
+} // namespace
+
+bool BoxInstall(const std::string &name, MainFunc const &func, const std::string &desc)
+{
+	return TheBox().Install(name, func, desc);
+}
+
+bool BoxFind(const std::string &name, MainFunc &func)
+{
+	return TheBox().Find(name, func);
+}
+
+const std::string kOrigName("bhshmqbox");
+void Help()
+{
+	printf("%s : bhome shared memory message queue box application.\n", kOrigName.c_str());
+	printf("usage:\n");
+	printf("\t1) %s [function [options]...]\n", kOrigName.c_str());
+	printf("\t2) rename or link %s to a function name then run it directly.\n", kOrigName.c_str());
+	printf("\nsupported functions:\n");
+	std::map<std::string, std::string> funcs;
+	auto getInfo = [&](const std::string &name, const std::string &desc) {
+		funcs[name] = desc;
+	};
+	TheBox().Apply(getInfo);
+	auto cmp_name_len = [](auto &a, auto &b) { return a.first.size() < b.first.size(); };
+	int max_len = std::max_element(funcs.begin(), funcs.end(), cmp_name_len)->first.size();
+	for (auto &kv : funcs) {
+		int npad = max_len - kv.first.size();
+		printf("\n\t%s%s : %s\n", kv.first.c_str(), std::string(npad, ' ').c_str(), kv.second.c_str());
+	}
+	printf("\n");
+}
+
+int BoxMain(int argc, const char *argv[])
+{
+	fs::path exe(argv[0]);
+	auto name = exe.filename().string();
+
+	MainFunc func;
+	if (BoxFind(name, func)) {
+		return func(argc, argv);
+	} else {
+		printf("%s : function not found!\n", name.c_str());
+		// Help();
+	}
+	return 0;
+}
+
+int main(int argc, const char *argv[])
+{
+	BoxInstall(
+	    "help", [](int, const char **) { Help(); return 0; }, "show this help message.");
+
+	fs::path exe(argv[0]);
+	auto name = exe.filename().string();
+	// printf("name: %s\n", name.c_str());
+
+	if (name == kOrigName) {
+		if (argc > 1) {
+			argc--;
+			argv++;
+		} else {
+			Help();
+			return 0;
+		}
+	}
+	return BoxMain(argc, argv);
+}
\ No newline at end of file
diff --git a/box/box.h b/box/box.h
new file mode 100644
index 0000000..14c19f4
--- /dev/null
+++ b/box/box.h
@@ -0,0 +1,27 @@
+/*
+ * =====================================================================================
+ *
+ *       Filename:  box.h
+ *
+ *    Description:  
+ *
+ *        Version:  1.0
+ *        Created:  2021骞�04鏈�13鏃� 16鏃�12鍒�44绉�
+ *       Revision:  none
+ *       Compiler:  gcc
+ *
+ *         Author:  Li Chao (), lichao@aiotlink.com
+ *   Organization:  
+ *
+ * =====================================================================================
+ */
+#ifndef BOX_L3FWJE7T
+#define BOX_L3FWJE7T
+#include <functional>
+#include <string>
+
+typedef std::function<int(int, const char *argv[])> MainFunc;
+bool BoxInstall(const std::string &name, MainFunc const &func, const std::string &desc);
+bool BoxFind(const std::string &name, MainFunc &func);
+
+#endif // end of include guard: BOX_L3FWJE7T
diff --git a/src/center.cpp b/box/center.cpp
similarity index 100%
rename from src/center.cpp
rename to box/center.cpp
diff --git a/src/center.h b/box/center.h
similarity index 100%
rename from src/center.h
rename to box/center.h
diff --git a/box/center_main.cc b/box/center_main.cc
new file mode 100644
index 0000000..40aed56
--- /dev/null
+++ b/box/center_main.cc
@@ -0,0 +1,35 @@
+/*
+ * =====================================================================================
+ *
+ *       Filename:  center_main.cc
+ *
+ *    Description:  
+ *
+ *        Version:  1.0
+ *        Created:  2021骞�04鏈�13鏃� 16鏃�16鍒�26绉�
+ *       Revision:  none
+ *       Compiler:  gcc
+ *
+ *         Author:  Li Chao (), lichao@aiotlink.com
+ *   Organization:  
+ *
+ * =====================================================================================
+ */
+#include "box.h"
+#include "center.h"
+#include "defs.h"
+#include "signalhandle.h"
+
+int center_main(int argc, const char *argv[])
+{
+	BHCenter center(BHomeShm());
+	center.Start();
+	WaitForSignals({SIGINT, SIGTERM});
+	// BHomeShm().Remove(); // remove ?
+	return 0;
+}
+
+namespace
+{
+static bool install = BoxInstall("bhshmq_center", center_main, "bhome center program.");
+}
diff --git a/box/signalhandle.cpp b/box/signalhandle.cpp
new file mode 100755
index 0000000..5d37787
--- /dev/null
+++ b/box/signalhandle.cpp
@@ -0,0 +1,70 @@
+#include "signalhandle.h"
+#include <errno.h>
+#include <mutex>
+#include <condition_variable>
+#include <atomic>
+#include <map>
+
+int CatchSignals(const int signals[], size_t count, void (* signal_handler)(int))
+{
+	if (nullptr == signals || 0 == count || nullptr == signal_handler) {
+		return EINVAL;	// Invalid argument (POSIX.1)
+	}
+
+	struct sigaction action = {0};
+
+	action.sa_handler = signal_handler;
+	action.sa_flags = 0;
+	sigemptyset(&action.sa_mask);
+
+	for (size_t i = 0; i < count; ++ i) {
+		if (0 != sigaction(signals[i], &action, nullptr)) {
+			return errno;
+		}
+	}
+
+	return 0;
+}
+
+int CatchSignals(const int signals[], const size_t count, SigFunc f)
+{
+	struct _ {
+		typedef std::map<int, SigFunc> SFMap;
+		static SFMap &Funcs() { static SFMap m; return m; }
+		static void OnSig(int sig) {
+			auto pf = Funcs().find(sig);
+			if (pf != Funcs().end() && pf->second) {
+				pf->second(sig);
+			}
+		}
+	};
+
+	for (int i = 0; i < int(count); ++i) {
+		_::Funcs()[signals[i]] = f;
+	}
+
+	return CatchSignals(signals, count, &_::OnSig);
+}
+
+int WaitForSignals(const int signals[], const size_t count, SigFunc f)
+{
+	std::mutex mtx;
+	std::condition_variable cv;
+	auto OnSig = [&](int sig) {
+		static std::atomic<bool> first(true);
+		if (first.exchange(false)) {
+			std::unique_lock<std::mutex> guard(mtx);
+			if (f) { f(sig); }
+			cv.notify_one();
+		}
+	};
+
+	std::unique_lock<std::mutex> guard(mtx);
+
+	const int r = CatchSignals(signals, count, OnSig);
+	if (r == 0) { // register handler.
+		cv.wait(guard);
+	}
+	return r;
+}
+
diff --git a/box/signalhandle.h b/box/signalhandle.h
new file mode 100755
index 0000000..3d89e84
--- /dev/null
+++ b/box/signalhandle.h
@@ -0,0 +1,41 @@
+#ifndef SIGNALHANDLE_WNM4OBKG
+#define SIGNALHANDLE_WNM4OBKG
+
+#include <signal.h>
+#include <functional>
+#include <vector>
+
+typedef std::function<void (int)> SigFunc;
+// return 0 on success.
+int CatchSignals(const int signals[], const size_t count, SigFunc f);
+int WaitForSignals(const int signals[], const size_t count, SigFunc f = SigFunc());
+
+template <size_t N> inline
+int CatchSignals(const int (& signals)[N], SigFunc f) {
+	return CatchSignals(signals, N, f);
+}
+
+template <class ...T> inline
+void CatchSignals(std::initializer_list<int> list, T...t)
+{
+	std::vector<int> arr(list.begin(), list.end());
+	CatchSignals(arr.data(), arr.size(), t...);
+}
+
+template <size_t N> inline
+int WaitForSignals(const int (&signals)[N]) {
+	return WaitForSignals(signals, N, SigFunc());
+}
+
+template <size_t N, class Func> inline
+int WaitForSignals(int (&signals)[N], Func f) {
+	return WaitForSignals(signals, N, f);
+}
+
+template <class ...T> inline
+void WaitForSignals(std::initializer_list<int> list, T...t)
+{
+	std::vector<int> arr(list.begin(), list.end());
+	WaitForSignals(arr.data(), arr.size(), t...);
+}
+#endif // end of include guard: SIGNALHANDLE_WNM4OBKG 
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 1db0086..b17a2f5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,7 +1,7 @@
 
 file(GLOB sources "./*.cpp")
 
-set(Target bhshm)
+set(Target bhome_shmq)
 
 add_library(${Target} ${sources})
 
diff --git a/utest/CMakeLists.txt b/utest/CMakeLists.txt
index 23ca913..4992516 100644
--- a/utest/CMakeLists.txt
+++ b/utest/CMakeLists.txt
@@ -4,4 +4,4 @@
 include_directories(../src)
 add_executable(utest ${sources})
 
-target_link_libraries(utest bhshm boost_test_exec_monitor boost_unit_test_framework boost_timer boost_chrono)
+target_link_libraries(utest bhshmqbox boost_test_exec_monitor boost_unit_test_framework boost_timer boost_chrono)

--
Gitblit v1.8.0