Cleanup
[carla.git] / source / utils / CarlaLibCounter.hpp
blob2753d6b50b79dd29f660654a7bd69d01a2d61280
1 /*
2 * Carla library counter
3 * Copyright (C) 2013-2014 Filipe Coelho <falktx@falktx.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
18 #ifndef CARLA_LIB_COUNTER_HPP_INCLUDED
19 #define CARLA_LIB_COUNTER_HPP_INCLUDED
21 #include "CarlaLibUtils.hpp"
22 #include "CarlaMutex.hpp"
23 #include "LinkedList.hpp"
25 // -----------------------------------------------------------------------
27 class LibCounter
29 public:
30 LibCounter() noexcept
31 : fMutex(),
32 fLibs() {}
34 ~LibCounter() noexcept
36 // might have some leftovers
37 for (LinkedList<Lib>::Itenerator it = fLibs.begin2(); it.valid(); it.next())
39 static Lib libFallback = { nullptr, nullptr, 0, false };
41 Lib& lib(it.getValue(libFallback));
42 CARLA_SAFE_ASSERT_CONTINUE(lib.count > 0);
43 CARLA_SAFE_ASSERT_CONTINUE(lib.lib != nullptr);
45 // all libs should be closed by now except those explicitly marked non-delete
46 CARLA_SAFE_ASSERT(! lib.canDelete);
48 if (! lib_close(lib.lib))
49 carla_stderr("LibCounter cleanup failed, reason:\n%s", lib_error(lib.filename));
51 lib.lib = nullptr;
53 if (lib.filename != nullptr)
55 delete[] lib.filename;
56 lib.filename = nullptr;
60 fLibs.clear();
63 lib_t open(const char* const filename, const bool canDelete = true) noexcept
65 CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', nullptr);
67 // try duplicating filename first, it can throw
68 const char* dfilename = nullptr;
70 try {
71 dfilename = carla_strdup(filename);
72 } CARLA_SAFE_EXCEPTION_RETURN("LibCounter::open", nullptr);
74 const CarlaMutexLocker cml(fMutex);
76 for (LinkedList<Lib>::Itenerator it = fLibs.begin2(); it.valid(); it.next())
78 static Lib libFallback = { nullptr, nullptr, 0, false };
80 Lib& lib(it.getValue(libFallback));
81 CARLA_SAFE_ASSERT_CONTINUE(lib.count > 0);
82 CARLA_SAFE_ASSERT_CONTINUE(lib.filename != nullptr);
84 if (std::strcmp(lib.filename, filename) == 0)
86 // will not be needed
87 delete[] dfilename;
89 ++lib.count;
90 return lib.lib;
94 const lib_t libPtr = lib_open(filename);
96 if (libPtr == nullptr)
98 delete[] dfilename;
99 return nullptr;
102 Lib lib;
103 lib.lib = libPtr;
104 lib.filename = dfilename;
105 lib.count = 1;
106 lib.canDelete = canDelete;
107 #ifdef BUILD_BRIDGE
108 lib.canDelete = true;
109 #endif
111 if (fLibs.append(lib))
112 return libPtr;
114 delete[] dfilename;
115 return nullptr;
118 bool close(const lib_t libPtr) noexcept
120 CARLA_SAFE_ASSERT_RETURN(libPtr != nullptr, false);
122 const CarlaMutexLocker cml(fMutex);
124 for (LinkedList<Lib>::Itenerator it = fLibs.begin2(); it.valid(); it.next())
126 static Lib libFallback = { nullptr, nullptr, 0, false };
128 Lib& lib(it.getValue(libFallback));
129 CARLA_SAFE_ASSERT_CONTINUE(lib.count > 0);
130 CARLA_SAFE_ASSERT_CONTINUE(lib.lib != nullptr);
132 if (lib.lib != libPtr)
133 continue;
135 if (lib.count == 1 && ! lib.canDelete)
136 return true;
138 if (--lib.count == 0)
140 if (! lib_close(lib.lib))
141 carla_stderr("LibCounter::close() failed, reason:\n%s", lib_error(lib.filename));
143 lib.lib = nullptr;
145 if (lib.filename != nullptr)
147 delete[] lib.filename;
148 lib.filename = nullptr;
151 fLibs.remove(it);
154 return true;
157 carla_safe_assert("invalid lib pointer", __FILE__, __LINE__);
158 return false;
161 void setCanDelete(const lib_t libPtr, const bool canDelete)
163 CARLA_SAFE_ASSERT_RETURN(libPtr != nullptr,);
165 const CarlaMutexLocker cml(fMutex);
167 for (LinkedList<Lib>::Itenerator it = fLibs.begin2(); it.valid(); it.next())
169 static Lib libFallback = { nullptr, nullptr, 0, false };
171 Lib& lib(it.getValue(libFallback));
172 CARLA_SAFE_ASSERT_CONTINUE(lib.lib != nullptr);
174 if (lib.lib != libPtr)
175 continue;
177 lib.canDelete = canDelete;
178 return;
182 private:
183 struct Lib {
184 lib_t lib;
185 const char* filename;
186 int count;
187 bool canDelete;
190 CarlaMutex fMutex;
191 LinkedList<Lib> fLibs;
194 // -----------------------------------------------------------------------
196 #endif // CARLA_LIB_COUNTER_HPP_INCLUDED