#include "service_manager.hh"
+#include <algorithm>
#include <stdexcept>
#include <utility>
return services_.find(name) != services_.end();
}
-void ServiceManager::Remove(const std::string& name) { services_.erase(name); }
+void ServiceManager::Remove(const std::string& name) {
+ auto it = services_.find(name);
+ if (it == services_.end())
+ return;
-void ServiceManager::AddEventListener(ServiceManager::IEvent* listener) {
- listeners_.push_back(listener);
+ auto service = it->second;
+ listeners_.erase(service);
+ services_.erase(it);
}
-void ServiceManager::RemoveEventListener(ServiceManager::IEvent* listener) {
- auto found = std::find(listeners_.begin(), listeners_.end(), listener);
- if (found == listeners_.end()) return;
+void ServiceManager::AddEventListener(const std::shared_ptr<Service>& service,
+ IEvent* listener) {
+ listeners_[service].push_back(listener);
+}
- listeners_.erase(found);
+void ServiceManager::RemoveEventListener(
+ const std::shared_ptr<Service>& service,
+ IEvent* listener) {
+ auto found = listeners_.find(service);
+ if (found == listeners_.end())
+ return;
+
+ auto& core_listeners = found->second;
+ auto it = std::find(core_listeners.begin(), core_listeners.end(), listener);
+ if (it != core_listeners.end())
+ core_listeners.erase(it);
}
-void ServiceManager::NotifyServiceStateChanged(const Service* service) {
- for (auto* listener : listeners_) listener->OnServiceStateChanged(service);
+void ServiceManager::NotifyServiceStateChanged(Service* service) {
+ for (auto [svc, listeners] : listeners_) {
+ for (auto listener : listeners) {
+ auto* cb_info = new std::tuple<IEvent*, Service*, Service::State>(
+ listener, service, service->GetState());
+ tizen_core_source_h source = nullptr;
+ tizen_core_add_idle_job(
+ svc->GetCore(),
+ [](void* user_data) -> bool {
+ auto* cb_info =
+ static_cast<std::tuple<IEvent*, Service*, Service::State>*>(
+ user_data);
+ auto [listener, service, state] = *cb_info;
+ delete cb_info;
+ listener->OnServiceStateChanged(service, state);
+ return false;
+ },
+ cb_info, &source);
+ if (source == nullptr) {
+ _E("Failed to create idle job");
+ delete cb_info;
+ }
+ }
+ }
+}
+
+std::shared_ptr<Service> ServiceManager::FindFromThisThread() {
+ tizen_core_h core = nullptr;
+ tizen_core_find_from_this_thread(&core);
+ if (core == nullptr)
+ return nullptr;
+
+ auto it = std::find_if(
+ services_.begin(), services_.end(),
+ [&](const std::pair<std::string, std::shared_ptr<Service>>& element)
+ -> bool {
+ auto& [name, service] = element;
+ return service->GetCore() == core;
+ });
+
+ if (it == services_.end())
+ return nullptr;
+
+ return it->second;
}
ServiceManager::ServiceManager() {}
ServiceManager::~ServiceManager() {}
-} // namespace tizen_base
+} // namespace tizen_base
class IEvent {
public:
virtual ~IEvent() = default;
- virtual void OnServiceStateChanged(const Service* service) = 0;
+ virtual void OnServiceStateChanged(Service* service,
+ Service::State state) = 0;
};
static ServiceManager& GetInst();
std::shared_ptr<Service> Get(const std::string& name) const;
bool Contains(const std::string& name) const;
void Remove(const std::string& name);
- void AddEventListener(IEvent* listener);
- void RemoveEventListener(IEvent* listener);
- void NotifyServiceStateChanged(const Service* service);
+ void AddEventListener(const std::shared_ptr<Service>& service,
+ IEvent* listener);
+ void RemoveEventListener(const std::shared_ptr<Service>& service,
+ IEvent* listener);
+ void NotifyServiceStateChanged(Service* service);
+
+ std::shared_ptr<Service> FindFromThisThread();
private:
ServiceManager();
private:
std::unordered_map<std::string, std::shared_ptr<Service>> services_;
- std::vector<IEvent*> listeners_;
+ std::unordered_map<std::shared_ptr<Service>, std::vector<IEvent*>> listeners_;
};
-} // namespace tizen_base
+} // namespace tizen_base
#endif // SERVICE_MANAGER_HH_
* limitations under the License.
*/
-#include "service_manager.h"
#include "service.h"
+#include "service_manager.h"
+#include <algorithm>
#include <new>
#include <stdexcept>
#include <utility>
virtual ~ServiceExt() {}
- void SetCallback(service_lifecycle_callback_s *callback, void* user_data) {
+ void SetCallback(service_lifecycle_callback_s* callback, void* user_data) {
callback_ = *callback;
user_data_ = user_data;
}
virtual ~EventHandler() {}
- void OnServiceStateChanged(const tizen_base::Service* service) override {
+ void OnServiceStateChanged(tizen_base::Service* service,
+ tizen_base::Service::State state) override {
if (callback_) {
- callback_(
- reinterpret_cast<service_h>(
- const_cast<tizen_base::Service*>(service)),
- static_cast<service_state_e>(service->GetState()),
- user_data_);
+ callback_(reinterpret_cast<service_h>(
+ const_cast<tizen_base::Service*>(service)),
+ static_cast<service_state_e>(state), user_data_);
}
}
return SERVICE_ERROR_NONE;
}
-API int service_send_message(service_h service, bundle *envelope) {
+API int service_send_message(service_h service, bundle* envelope) {
if (!service || !envelope) {
_E("Invalid parameter");
return SERVICE_ERROR_INVALID_PARAMETER;
return SERVICE_ERROR_NONE;
}
-
API int service_get_name(service_h service, char** name) {
if (!service || !name) {
_E("Invalid parameter");
return SERVICE_MANAGER_ERROR_OUT_OF_MEMORY;
}
- tizen_base::ServiceManager::GetInst().AddEventListener(handle);
+ auto& inst = tizen_base::ServiceManager::GetInst();
+ auto service = inst.FindFromThisThread();
+ if (service == nullptr) {
+ _E("Failed to find service from this thread");
+ return SERVICE_ERROR_INVALID_CONTEXT;
+ }
+
+ tizen_base::ServiceManager::GetInst().AddEventListener(service, handle);
*event_handler = reinterpret_cast<service_manager_event_h>(handle);
return SERVICE_MANAGER_ERROR_NONE;
}
}
auto* handle = reinterpret_cast<EventHandler*>(event_handler);
- tizen_base::ServiceManager::GetInst().RemoveEventListener(handle);
+ auto& inst = tizen_base::ServiceManager::GetInst();
+
+ auto service = inst.FindFromThisThread();
+ if (service == nullptr) {
+ _E("Failed to find service from this thread");
+ return SERVICE_ERROR_INVALID_CONTEXT;
+ }
+
+ inst.RemoveEventListener(service, handle);
delete handle;
return SERVICE_MANAGER_ERROR_NONE;
}