// Copyright (C) 2014-2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING #include #endif #include #include #include #include #include #include #include #include #include "sample-ids.hpp" class service_sample { public: service_sample(uint32_t _cycle) : app_(vsomeip::runtime::get()->create_application()), is_registered_(false), cycle_(_cycle), blocked_(false), running_(true), is_offered_(false), offer_thread_(std::bind(&service_sample::run, this)), notify_thread_(std::bind(&service_sample::notify, this)) { } bool init() { std::lock_guard its_lock(mutex_); if (!app_->init()) { std::cerr << "Couldn't initialize application" << std::endl; return false; } app_->register_state_handler( std::bind(&service_sample::on_state, this, std::placeholders::_1)); app_->register_message_handler( SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_GET_METHOD_ID, std::bind(&service_sample::on_get, this, std::placeholders::_1)); app_->register_message_handler( SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_SET_METHOD_ID, std::bind(&service_sample::on_set, this, std::placeholders::_1)); std::set its_groups; its_groups.insert(SAMPLE_EVENTGROUP_ID); app_->offer_event( SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID, its_groups, vsomeip::event_type_e::ET_FIELD, std::chrono::milliseconds::zero(), false, true, nullptr, vsomeip::reliability_type_e::RT_UNKNOWN); { std::lock_guard its_lock(payload_mutex_); payload_ = vsomeip::runtime::get()->create_payload(); } blocked_ = true; condition_.notify_one(); return true; } void start() { app_->start(); } #ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING /* * Handle signal to shutdown */ void stop() { running_ = false; blocked_ = true; condition_.notify_one(); notify_condition_.notify_one(); app_->clear_all_handler(); stop_offer(); if (std::this_thread::get_id() != offer_thread_.get_id()) { if (offer_thread_.joinable()) { offer_thread_.join(); } } else { offer_thread_.detach(); } if (std::this_thread::get_id() != notify_thread_.get_id()) { if (notify_thread_.joinable()) { notify_thread_.join(); } } else { notify_thread_.detach(); } app_->stop(); } #endif void offer() { std::lock_guard its_lock(notify_mutex_); app_->offer_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID); is_offered_ = true; notify_condition_.notify_one(); } void stop_offer() { app_->stop_offer_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID); is_offered_ = false; } void on_state(vsomeip::state_type_e _state) { std::cout << "Application " << app_->get_name() << " is " << (_state == vsomeip::state_type_e::ST_REGISTERED ? "registered." : "deregistered.") << std::endl; if (_state == vsomeip::state_type_e::ST_REGISTERED) { if (!is_registered_) { is_registered_ = true; } } else { is_registered_ = false; } } void on_get(const std::shared_ptr &_message) { std::shared_ptr its_response = vsomeip::runtime::get()->create_response(_message); { std::lock_guard its_lock(payload_mutex_); its_response->set_payload(payload_); } app_->send(its_response); } void on_set(const std::shared_ptr &_message) { std::shared_ptr its_response = vsomeip::runtime::get()->create_response(_message); { std::lock_guard its_lock(payload_mutex_); payload_ = _message->get_payload(); its_response->set_payload(payload_); } app_->send(its_response); app_->notify(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID, payload_); } void run() { std::unique_lock its_lock(mutex_); while (!blocked_) condition_.wait(its_lock); bool is_offer(true); while (running_) { if (is_offer) offer(); else stop_offer(); for (int i = 0; i < 10 && running_; i++) std::this_thread::sleep_for(std::chrono::milliseconds(1000)); is_offer = !is_offer; } } void notify() { vsomeip::byte_t its_data[10]; uint32_t its_size = 1; while (running_) { std::unique_lock its_lock(notify_mutex_); while (!is_offered_ && running_) notify_condition_.wait(its_lock); while (is_offered_ && running_) { if (its_size == sizeof(its_data)) its_size = 1; for (uint32_t i = 0; i < its_size; ++i) its_data[i] = static_cast(i); { std::lock_guard its_lock(payload_mutex_); payload_->set_data(its_data, its_size); std::cout << "Setting event (Length=" << std::dec << its_size << ")." << std::endl; app_->notify(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID, payload_); } its_size++; std::this_thread::sleep_for(std::chrono::milliseconds(cycle_)); } } } private: std::shared_ptr app_; bool is_registered_; uint32_t cycle_; std::mutex mutex_; std::condition_variable condition_; bool blocked_; bool running_; std::mutex notify_mutex_; std::condition_variable notify_condition_; bool is_offered_; std::mutex payload_mutex_; std::shared_ptr payload_; // blocked_ / is_offered_ must be initialized before starting the threads! std::thread offer_thread_; std::thread notify_thread_; }; #ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING service_sample *its_sample_ptr(nullptr); void handle_signal(int _signal) { if (its_sample_ptr != nullptr && (_signal == SIGINT || _signal == SIGTERM)) its_sample_ptr->stop(); } #endif int main(int argc, char **argv) { uint32_t cycle = 1000; // default 1s std::string cycle_arg("--cycle"); for (int i = 1; i < argc; i++) { if (cycle_arg == argv[i] && i + 1 < argc) { i++; std::stringstream converter; converter << argv[i]; converter >> cycle; } } service_sample its_sample(cycle); #ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING its_sample_ptr = &its_sample; signal(SIGINT, handle_signal); signal(SIGTERM, handle_signal); #endif if (its_sample.init()) { its_sample.start(); return 0; } else { return 1; } }