|
- /*
- * Carla library counter
- * Copyright (C) 2013-2014 Filipe Coelho <falktx@falktx.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * For a full copy of the GNU General Public License see the doc/GPL.txt file.
- */
-
- #ifndef CARLA_LIB_COUNTER_HPP_INCLUDED
- #define CARLA_LIB_COUNTER_HPP_INCLUDED
-
- #include "CarlaLibUtils.hpp"
- #include "CarlaMutex.hpp"
- #include "LinkedList.hpp"
-
- // -----------------------------------------------------------------------
-
- class LibCounter
- {
- public:
- LibCounter() noexcept
- : fMutex(),
- fLibs() {}
-
- ~LibCounter() noexcept
- {
- // might have some leftovers
- for (LinkedList<Lib>::Itenerator it = fLibs.begin(); it.valid(); it.next())
- {
- static Lib libFallback = { nullptr, nullptr, 0, false };
-
- Lib& lib(it.getValue(libFallback));
- CARLA_SAFE_ASSERT_CONTINUE(lib.count > 0);
- CARLA_SAFE_ASSERT_CONTINUE(lib.lib != nullptr);
-
- // all libs should be closed by now except those explicitly marked non-delete
- CARLA_SAFE_ASSERT(! lib.canDelete);
-
- if (! lib_close(lib.lib))
- carla_stderr("LibCounter cleanup failed, reason:\n%s", lib_error(lib.filename));
-
- lib.lib = nullptr;
-
- if (lib.filename != nullptr)
- {
- delete[] lib.filename;
- lib.filename = nullptr;
- }
- }
-
- fLibs.clear();
- }
-
- lib_t open(const char* const filename, const bool canDelete = true) noexcept
- {
- CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', nullptr);
-
- // try duplicating filename first, it can throw
- const char* dfilename = nullptr;
-
- try {
- dfilename = carla_strdup(filename);
- } CARLA_SAFE_EXCEPTION_RETURN("LibCounter::open", nullptr);
-
- const CarlaMutexLocker cml(fMutex);
-
- for (LinkedList<Lib>::Itenerator it = fLibs.begin(); it.valid(); it.next())
- {
- static Lib libFallback = { nullptr, nullptr, 0, false };
-
- Lib& lib(it.getValue(libFallback));
- CARLA_SAFE_ASSERT_CONTINUE(lib.count > 0);
- CARLA_SAFE_ASSERT_CONTINUE(lib.filename != nullptr);
-
- if (std::strcmp(lib.filename, filename) == 0)
- {
- // will not be needed
- delete[] dfilename;
-
- ++lib.count;
- return lib.lib;
- }
- }
-
- const lib_t libPtr(lib_open(filename));
-
- if (libPtr == nullptr)
- {
- delete[] dfilename;
- return nullptr;
- }
-
- Lib lib;
- lib.lib = libPtr;
- lib.filename = dfilename;
- lib.count = 1;
- lib.canDelete = canDelete;
-
- if (fLibs.append(lib))
- return libPtr;
-
- delete[] dfilename;
- return nullptr;
- }
-
- bool close(const lib_t libPtr) noexcept
- {
- CARLA_SAFE_ASSERT_RETURN(libPtr != nullptr, false);
-
- const CarlaMutexLocker cml(fMutex);
-
- for (LinkedList<Lib>::Itenerator it = fLibs.begin(); it.valid(); it.next())
- {
- static Lib libFallback = { nullptr, nullptr, 0, false };
-
- Lib& lib(it.getValue(libFallback));
- CARLA_SAFE_ASSERT_CONTINUE(lib.count > 0);
- CARLA_SAFE_ASSERT_CONTINUE(lib.lib != nullptr);
-
- if (lib.lib != libPtr)
- continue;
-
- if (lib.count == 1 && ! lib.canDelete)
- return true;
-
- if (--lib.count == 0)
- {
- if (! lib_close(lib.lib))
- carla_stderr("LibCounter::close() failed, reason:\n%s", lib_error(lib.filename));
-
- lib.lib = nullptr;
-
- if (lib.filename != nullptr)
- {
- delete[] lib.filename;
- lib.filename = nullptr;
- }
-
- fLibs.remove(it);
- }
-
- return true;
- }
-
- carla_safe_assert("invalid lib pointer", __FILE__, __LINE__);
- return false;
- }
-
- private:
- struct Lib {
- lib_t lib;
- const char* filename;
- int count;
- bool canDelete;
- };
-
- CarlaMutex fMutex;
- LinkedList<Lib> fLibs;
- };
-
- // -----------------------------------------------------------------------
-
- #endif // CARLA_LIB_COUNTER_HPP_INCLUDED
|