neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
services.hpp
Go to the documentation of this file.
1// services.hpp
2/*
3 * Copyright (c) 2020 Leigh Johnston.
4 *
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * * Neither the name of Leigh Johnston nor the names of any
19 * other contributors to this software may be used to endorse or
20 * promote products derived from this software without specific prior
21 * written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
24 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*/
35
36#pragma once
37
38#include <stdexcept>
39#include <atomic>
40#include <mutex>
41#include <neolib/core/uuid.hpp>
42
44{
45 struct no_service_provider_instance : std::logic_error { no_service_provider_instance() : std::logic_error{ "neolib::services::no_service_provider_instance" } {} };
46 struct service_provider_instance_exists : std::logic_error { service_provider_instance_exists() : std::logic_error{ "neolib::services::service_provider_instance_exists" } {} };
47 struct service_not_found : std::logic_error { service_not_found() : std::logic_error{ "neolib::services::service_not_found" } {} };
48
49 template <typename Service>
50 inline std::atomic<Service*>& service_ptr()
51 {
52 static std::atomic<Service*> sService;
53 return sService;
54 }
55
57 {
58 public:
59 virtual ~i_service() = default;
60 };
61
63 {
64 public:
65 virtual ~i_service_provider() = default;
66 public:
67 virtual void lock() = 0;
68 virtual void unlock() = 0;
69 public:
70 virtual bool service_registered(uuid aServiceIid) const = 0;
71 virtual i_service& service(uuid aServiceIid) = 0;
72 virtual void register_service(i_service& aService, uuid aServiceIid) = 0;
73 virtual void unregister_service(uuid aServiceIid) = 0;
74 public:
75 template <typename Service>
76 Service& service()
77 {
78 return static_cast<Service&>(service(Service::iid()));
79 }
80 };
81
85
86 template <typename Service>
87 inline bool service_registered()
88 {
89 return get_service_provider().service_registered(Service::iid());
90 }
91
92 template <typename Service>
93 inline void register_service(Service& aService)
94 {
95 get_service_provider().register_service(aService, Service::iid());
96 service_ptr<Service>() = &aService;
97 }
98
99 template <typename Service>
100 inline void unregister_service(Service& aService)
101 {
103 service_ptr<Service>() = nullptr;
104 }
105
106 template <typename Service>
107 Service& start_service();
108
109 template <typename Service>
111
112 template <typename Service>
113 inline Service& service()
114 {
115 if (service_ptr<Service>() != nullptr)
116 return *service_ptr<Service>();
117 std::unique_lock lock{ get_service_provider() };
118 if (!service_registered<Service>())
119 register_service(start_service<Service>());
120 else
121 service_ptr<Service>() = &get_service_provider().service<Service>();
122 return *service_ptr<Service>();
123 }
124}
125
126namespace neolib
127{
128 using namespace services;
129}
virtual void register_service(i_service &aService, uuid aServiceIid)=0
virtual i_service & service(uuid aServiceIid)=0
virtual void unregister_service(uuid aServiceIid)=0
virtual bool service_registered(uuid aServiceIid) const =0
virtual ~i_service()=default
void register_service(Service &aService)
Definition services.hpp:93
void teardown_service()
i_service_provider & allocate_service_provider()
void unregister_service(Service &aService)
Definition services.hpp:100
Service & service()
Definition services.hpp:113
bool service_registered()
Definition services.hpp:87
Service & start_service()
void set_service_provider(i_service_provider &aServiceProvider)
std::atomic< Service * > & service_ptr()
Definition services.hpp:50
i_service_provider & get_service_provider()