/usr/include/compiz/core/pluginclasshandler.h is in compiz-dev 1:0.9.13.1+18.04.20180302-0ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 | /*
* Copyright © 2008 Dennis Kasprzyk
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation, and that the name of
* Dennis Kasprzyk not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior permission.
* Dennis Kasprzyk makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
* NO EVENT SHALL DENNIS KASPRZYK BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
*/
#ifndef _COMPPLUGINCLASSHANDLER_H
#define _COMPPLUGINCLASSHANDLER_H
#include <typeinfo>
#include <boost/preprocessor/cat.hpp>
#include <core/string.h>
#include <core/valueholder.h>
#include <core/pluginclasses.h>
/* Continuously increments every time a new
* plugin class is added, guaranteed to be
* the same as the pcIndex of the most up-to-date
* PluginClassHandler index. Any index that
* hold the same value this value is safe to
* use to retreive the plugin class for a base
* class (and as such we don't need to constantly
* re-query ValueHolder for the index of this plugin
* on the base class)
*/
extern unsigned int pluginClassHandlerIndex;
namespace compiz
{
namespace plugin
{
namespace internal
{
class PluginKey;
/**
* LoadedPluginClassBridge
*
* This template essentially exists so that we can reduce the
* scope of functions which are allowed to mark plugin classes
* as instantiatable as we can't really inject the interface
* from PluginClassHandler to do that anywhere. We also can't
* forward declare a nested class declaration, but we can forward
* declare PluginKey, which users should inherit from and take
* it by reference. If the class we're depending on can only be
* defined in one other place along with a private constructor
* accessible only to a friend it means that we've effectively
* limited the scope of users of this class.
*/
template <class Tp, class Tb, int ABI = 0>
class LoadedPluginClassBridge
{
public:
static void
allowInstantiations (const PluginKey &);
static void
disallowInstantiations (const PluginKey &);
};
}
}
}
template<class Tp, class Tb, int ABI = 0>
class PluginClassHandler
{
public:
typedef Tp ClassPluginType;
typedef Tb ClassPluginBaseType;
PluginClassHandler (Tb *);
~PluginClassHandler ();
/**
* Changes this PluginClassHandler's state to "failed"
*/
void setFailed () { mFailed = true; };
/**
* Checks to see if this plugin class failed to load for
* whatever reason, so that instantiation of the class
* can be aborted
*/
bool loadFailed () { return mFailed; };
/**
* Returns the unique instance of the plugin class
* for this base class
*/
Tb * get () { return mBase; };
static Tp * get (Tb *);
static const Tp * get (const Tb *);
private:
/**
* Returns the unique string identifying this plugin type with it's
* ABI
*/
static CompString keyName ()
{
return compPrintf ("%s_index_%lu", typeid (Tp).name (), ABI);
}
/**
* Actually initializes the index of this plugin class
* by allocating a new index for plugin class storage
* on this base class if there wasn't one already and then
* storing that index inside of ValueHolder
*/
static bool initializeIndex (Tb *base);
static inline Tp * getInstance (Tb *base);
static void allowInstantiations ();
static void disallowInstantiations ();
template <class Plugin, class Base, int PluginABI>
friend class compiz::plugin::internal::LoadedPluginClassBridge;
private:
bool mFailed;
Tb *mBase;
static PluginClassIndex mIndex;
static bool mPluginLoaded;
};
namespace compiz
{
namespace plugin
{
namespace internal
{
template <class Tp, class Tb, int ABI>
void
LoadedPluginClassBridge <Tp, Tb, ABI>::allowInstantiations (const PluginKey &)
{
PluginClassHandler <Tp, Tb, ABI>::allowInstantiations ();
}
template <class Tp, class Tb, int ABI>
void
LoadedPluginClassBridge <Tp, Tb, ABI>::disallowInstantiations (const PluginKey &)
{
PluginClassHandler <Tp, Tb, ABI>::disallowInstantiations ();
}
}
}
}
template<class Tp, class Tb, int ABI>
PluginClassIndex PluginClassHandler<Tp,Tb,ABI>::mIndex;
template<class Tp, class Tb, int ABI>
bool PluginClassHandler<Tp,Tb,ABI>::mPluginLoaded = false;
/**
* Attaches a unique instance of the specified plugin class to a
* unique instance of a specified base class
*/
template<class Tp, class Tb, int ABI>
PluginClassHandler<Tp,Tb,ABI>::PluginClassHandler (Tb *base) :
mFailed (false),
mBase (base)
{
/* If allocating plugin class indices for this base has
* already failed once don't bother to allocate more for
* this plugin class, just instantly fail */
if (mIndex.pcFailed)
{
mFailed = true;
}
else
{
/* The index for this plugin class hasn't been initiated
* so do that (done once per plugin) */
if (!mIndex.initiated)
mFailed = !initializeIndex (base);
/* Increase the reference count of this plugin class index
* for this plugin on this base object for each attached
* plugin class and set the index pointer */
if (!mIndex.failed)
{
mIndex.refCount++;
mBase->pluginClasses[mIndex.index] = static_cast<Tp *> (this);
}
}
}
template<class Tp, class Tb, int ABI>
bool
PluginClassHandler<Tp,Tb,ABI>::initializeIndex (Tb *base)
{
/* Allocate a new storage space index in the array of CompPrivate's
* specified in the base class */
mIndex.index = base->allocPluginClassIndex ();
if (mIndex.index != (unsigned)~0)
{
/* Allocation was successful, this is the most recently allocated
* plugin class index so it is fresh to use */
mIndex.initiated = true;
mIndex.failed = false;
mIndex.pcIndex = pluginClassHandlerIndex;
CompPrivate p;
p.uval = mIndex.index;
/* Also store the index value inside of ValueHolder for this plugin-base
* combination so that we can fetch it later should the index location
* change */
if (!ValueHolder::Default ()->hasValue (keyName ()))
{
ValueHolder::Default ()->storeValue (keyName (), p);
pluginClassHandlerIndex++;
}
else
{
compLogMessage ("core", CompLogLevelFatal,
"Private index value \"%s\" already stored in screen.",
keyName ().c_str ());
}
return true;
}
else
{
mIndex.index = 0;
mIndex.failed = true;
mIndex.initiated = false;
mIndex.pcFailed = true;
mIndex.pcIndex = pluginClassHandlerIndex;
return false;
}
}
template<class Tp, class Tb, int ABI>
PluginClassHandler<Tp,Tb,ABI>::~PluginClassHandler ()
{
/* Only bother to destroy the static mIndex if plugin
* class allocation was actually successful */
if (!mIndex.pcFailed)
{
mIndex.refCount--;
/* Once this index's reference count hits zero it
* means that there are no more plugin classes attached
* to the base class, so other plugins are free to use our
* index and we can erase our data from ValueHolder
* (also increment pluginClassHandlerIndex since after doing
* this operation, all the other indexes with the same pcIndex
* won't be fresh) */
if (mIndex.refCount == 0)
{
mBase->freePluginClassIndex (mIndex.index);
mIndex.initiated = false;
mIndex.failed = false;
mIndex.pcIndex = pluginClassHandlerIndex;
ValueHolder::Default ()->eraseValue (keyName ());
pluginClassHandlerIndex++;
}
}
}
template<class Tp, class Tb, int ABI>
Tp *
PluginClassHandler<Tp,Tb,ABI>::getInstance (Tb *base)
{
/* Return the plugin class found at index if it exists
* otherwise spawn a new one implicitly (objects should
* never expect ::get () to fail, unless the plugin class
* fails to instantiate or the underlying base object
* does not take plugin classes of this type)
*/
if (base->pluginClasses[mIndex.index])
return static_cast<Tp *> (base->pluginClasses[mIndex.index]);
else
{
/* mIndex.index will be implicitly set by
* the constructor */
Tp *pc = new Tp (base);
if (!pc)
return NULL;
/* FIXME: If a plugin class fails to load for
* whatever reason, then ::get is going to return
* NULL, which is unsafe in cases that aren't
* initScreen and initWindow */
if (pc->loadFailed ())
{
delete pc;
return NULL;
}
return static_cast<Tp *> (base->pluginClasses[mIndex.index]);
}
}
template<class Tp, class Tb, int ABI>
const Tp *
PluginClassHandler<Tp,Tb,ABI>::get (const Tb *base)
{
return get (const_cast<Tb *> (base));
}
template<class Tp, class Tb, int ABI>
Tp *
PluginClassHandler<Tp,Tb,ABI>::get (Tb *base)
{
/* Never instantiate an instance of this class
* if the relevant plugin has not been loaded
*/
if (!mPluginLoaded)
return NULL;
/* Always ensure that the index is initialized before
* calls to ::get */
if (!mIndex.initiated)
initializeIndex (base);
/* If pluginClassHandlerIndex == mIndex.pcIndex it means that our
* mIndex.index is fresh and can be used directly without needing
* to fetch it from ValueHolder */
if (mIndex.initiated && pluginClassHandlerIndex == mIndex.pcIndex)
return getInstance (base);
/* If allocating or getting the updated index failed at any point
* then just return NULL we don't know where our private data is stored */
if (mIndex.failed && pluginClassHandlerIndex == mIndex.pcIndex)
return NULL;
if (ValueHolder::Default ()->hasValue (keyName ()))
{
mIndex.index = ValueHolder::Default ()->getValue (keyName ()).uval;
mIndex.initiated = true;
mIndex.failed = false;
mIndex.pcIndex = pluginClassHandlerIndex;
return getInstance (base);
}
else
{
mIndex.initiated = false;
mIndex.failed = true;
mIndex.pcIndex = pluginClassHandlerIndex;
return NULL;
}
}
template<class Tp, class Tb, int ABI>
void
PluginClassHandler<Tp, Tb, ABI>::allowInstantiations ()
{
mPluginLoaded = true;
}
template<class Tp, class Tb, int ABI>
void
PluginClassHandler<Tp, Tb, ABI>::disallowInstantiations ()
{
mPluginLoaded = false;
}
#endif
|