lichao
2021-04-13 047f801078a52042ef02750b577233d115ed0f57
rename library, add box.
6个文件已添加
2 文件已重命名
4个文件已修改
331 ■■■■■ 已修改文件
.gitignore 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CMakeLists.txt 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
box/CMakeLists.txt 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
box/box.cc 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
box/box.h 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
box/center.cpp 补丁 | 查看 | 原始文档 | blame | 历史
box/center.h 补丁 | 查看 | 原始文档 | blame | 历史
box/center_main.cc 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
box/signalhandle.cpp 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
box/signalhandle.h 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/CMakeLists.txt 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
utest/CMakeLists.txt 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -6,3 +6,6 @@
utest/utest
*.bak
gmon.out
box/bhshmqbox
box/bhshmq_center
box/help
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)
box/CMakeLists.txt
New file
@@ -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})
box/box.cc
New file
@@ -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);
}
box/box.h
New file
@@ -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
box/center.cpp
box/center.h
box/center_main.cc
New file
@@ -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.");
}
box/signalhandle.cpp
New file
@@ -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;
}
box/signalhandle.h
New file
@@ -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
src/CMakeLists.txt
@@ -1,7 +1,7 @@
file(GLOB sources "./*.cpp")
set(Target bhshm)
set(Target bhome_shmq)
add_library(${Target} ${sources})
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)