Fix MSYS2 issues
[xonotic/netradiant.git] / libs / modulesystem / singletonmodule.h
1 /*
2    Copyright (C) 2001-2006, William Joseph.
3    All Rights Reserved.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #if !defined( INCLUDED_MODULESYSTEM_SINGLETONMODULE_H )
23 #define INCLUDED_MODULESYSTEM_SINGLETONMODULE_H
24
25 #include "modulesystem.h"
26 #include <cstddef>
27 #include "debugging/debugging.h"
28 #include "modulesystem/moduleregistry.h"
29 #include "generic/reference.h"
30
31 template<typename API, typename Dependencies>
32 class DefaultAPIConstructor
33 {
34 public:
35 const char* getName(){
36         return typename API::Name();
37 }
38
39 API* constructAPI( Dependencies& dependencies ){
40         return new API;
41 }
42 void destroyAPI( API* api ){
43         delete api;
44 }
45 };
46
47 template<typename API, typename Dependencies>
48 class DependenciesAPIConstructor
49 {
50 public:
51 const char* getName(){
52         return typename API::Name();
53 }
54
55 API* constructAPI( Dependencies& dependencies ){
56         return new API( dependencies );
57 }
58 void destroyAPI( API* api ){
59         delete api;
60 }
61 };
62
63 class NullDependencies
64 {
65 };
66
67
68 template<typename API, typename Dependencies = NullDependencies, typename APIConstructor = DefaultAPIConstructor<API, Dependencies> >
69 class SingletonModule : public APIConstructor, public Module, public ModuleRegisterable
70 {
71 Dependencies* m_dependencies;
72 API* m_api;
73 std::size_t m_refcount;
74 bool m_dependencyCheck;
75 bool m_cycleCheck;
76 public:
77 typedef typename API::Type Type;
78
79 SingletonModule()
80         : m_dependencies( 0 ), m_api( 0 ), m_refcount( 0 ), m_dependencyCheck( false ), m_cycleCheck( false ){
81 }
82 explicit SingletonModule( const APIConstructor& constructor )
83         : APIConstructor( constructor ), m_dependencies( 0 ), m_api( 0 ), m_refcount( 0 ), m_dependencyCheck( false ), m_cycleCheck( false ){
84 }
85 ~SingletonModule(){
86         ASSERT_MESSAGE( m_refcount == 0, "module still referenced at shutdown" );
87 }
88
89 void selfRegister(){
90         globalModuleServer().registerModule( typename Type::Name(), typename Type::Version(), APIConstructor::getName(), *this );
91         }
92
93 Dependencies& getDependencies(){
94         return *m_dependencies;
95 }
96 void* getTable(){
97         if ( m_api != 0 ) {
98                 return m_api->getTable();
99         }
100         return 0;
101 }
102 void capture(){
103         if ( ++m_refcount == 1 ) {
104                 globalOutputStream() << "Module Initialising: '" << typename Type::Name() << "' '" << APIConstructor::getName() << "'\n";
105                 m_dependencies = new Dependencies();
106                 m_dependencyCheck = !globalModuleServer().getError();
107                 if ( m_dependencyCheck ) {
108                         m_api = APIConstructor::constructAPI( *m_dependencies );
109                         globalOutputStream() << "Module Ready: '" << typename Type::Name() << "' '" << APIConstructor::getName() << "'\n";
110                 }
111                 else
112                 {
113                         globalOutputStream() << "Module Dependencies Failed: '" << typename Type::Name() << "' '" << APIConstructor::getName() << "'\n";
114                 }
115                 m_cycleCheck = true;
116         }
117
118         ASSERT_MESSAGE( m_cycleCheck, "cyclic dependency detected" );
119 }
120 void release(){
121         if ( --m_refcount == 0 ) {
122                 if ( m_dependencyCheck ) {
123                         APIConstructor::destroyAPI( m_api );
124                 }
125                 delete m_dependencies;
126         }
127 }
128 };
129
130
131 #endif