| | |
| | | #include "center.h" |
| | | #include "defs.h" |
| | | #include "signalhandle.h" |
| | | #include <boost/interprocess/sync/named_mutex.hpp> |
| | | #include <chrono> |
| | | #include <thread> |
| | | using namespace std::chrono_literals; |
| | | using namespace bhome_shm; |
| | | |
| | | namespace |
| | | { |
| | | const std::string kCenterRunningFlag = "bh_center_single_flag_0"; |
| | | |
| | | class InstanceFlag |
| | | { |
| | | |
| | | public: |
| | | InstanceFlag(SharedMemory &shm, const std::string &name) : |
| | | shm_(shm), name_(name), run_(false) {} |
| | | ~InstanceFlag() { Stop(); } |
| | | |
| | | bool TryStartAsFirstInstance() |
| | | { |
| | | if (run_) { |
| | | return true; |
| | | } |
| | | |
| | | auto mtx(shm_.find_or_construct<Mutex>((name_ + "_mutex_0").c_str())()); |
| | | auto time_stamp(shm_.find_or_construct<int64_t>((name_ + "_timestamp_0").c_str())(0)); |
| | | |
| | | if (mtx && time_stamp) { |
| | | Guard lock(*mtx); |
| | | auto now = NowSec(); |
| | | // printf("old: %ld, now: %ld\n", *time_stamp, now); |
| | | if (now > *time_stamp + 10) { |
| | | *time_stamp = now; |
| | | auto UpdateTime = [this, time_stamp]() { |
| | | while (run_) { |
| | | std::this_thread::sleep_for(1s); |
| | | *time_stamp = NowSec(); |
| | | } |
| | | }; |
| | | run_.store(true); |
| | | std::thread(UpdateTime).swap(worker_); |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | private: |
| | | void Stop() |
| | | { |
| | | run_.store(false); |
| | | if (worker_.joinable()) { |
| | | worker_.join(); |
| | | } |
| | | } |
| | | |
| | | std::thread worker_; |
| | | SharedMemory &shm_; |
| | | std::string name_; |
| | | std::atomic<bool> run_; |
| | | }; |
| | | |
| | | } // namespace |
| | | int center_main(int argc, const char *argv[]) |
| | | { |
| | | auto &shm = BHomeShm(); |
| | | |
| | | AppArg args(argc, argv); |
| | | if (args.Has("remove")) { |
| | | BHomeShm().Remove(); |
| | | shm.Remove(); |
| | | return 0; |
| | | } |
| | | |
| | | bool run = true; |
| | | auto showStatus = [&]() { |
| | | auto init = BHomeShm().get_free_memory(); |
| | | uint64_t idx = 0; |
| | | while (run) { |
| | | std::this_thread::sleep_for(1s); |
| | | printf("%8d shared memory: avail : %ld / %ld\n", ++idx, BHomeShm().get_free_memory(), init); |
| | | } |
| | | }; |
| | | std::thread t(showStatus); |
| | | InstanceFlag inst(shm, kCenterRunningFlag); |
| | | if (!inst.TryStartAsFirstInstance()) { |
| | | printf("another instance is running, exit.\n"); |
| | | return 0; |
| | | } |
| | | |
| | | BHCenter center(BHomeShm()); |
| | | if (args.Has("daemon") || args.Has("d")) { |
| | | int r = daemon(0, 0); // TODO center control msg to close itself. |
| | | } |
| | | |
| | | BHCenter center(shm); |
| | | center.Start(); |
| | | |
| | | printf("center started ...\n"); |
| | | WaitForSignals({SIGINT, SIGTERM}); |
| | | run = false; |
| | | t.join(); |
| | | return 0; |
| | | } |
| | | |