mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
General refactoring of beast framework classes
This commit is contained in:
135
modules/beast_core/time/AtExitHook.cpp
Normal file
135
modules/beast_core/time/AtExitHook.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, 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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
// Manages the list of hooks, and calls
|
||||
// whoever is in the list at exit time.
|
||||
//
|
||||
class AtExitHook::Manager
|
||||
{
|
||||
public:
|
||||
Manager ()
|
||||
: m_didStaticDestruction (false)
|
||||
{
|
||||
}
|
||||
|
||||
static inline Manager& get ()
|
||||
{
|
||||
return StaticObject <Manager>::get();
|
||||
}
|
||||
|
||||
void insert (Item& item)
|
||||
{
|
||||
ScopedLockType lock (m_mutex);
|
||||
|
||||
// Adding a new AtExitHook during or after the destruction
|
||||
// of objects with static storage duration has taken place?
|
||||
// Surely something has gone wrong.
|
||||
//
|
||||
bassert (! m_didStaticDestruction);
|
||||
m_list.push_front (item);
|
||||
}
|
||||
|
||||
void erase (Item& item)
|
||||
{
|
||||
ScopedLockType lock (m_mutex);
|
||||
|
||||
m_list.erase (m_list.iterator_to (item));
|
||||
}
|
||||
|
||||
private:
|
||||
// Called at program exit when destructors for objects
|
||||
// with static storage duration are invoked.
|
||||
//
|
||||
void doStaticDetruction ()
|
||||
{
|
||||
// In theory this shouldn't be needed (?)
|
||||
ScopedLockType lock (m_mutex);
|
||||
|
||||
bassert (! m_didStaticDestruction);
|
||||
|
||||
for (List <Item>::iterator iter (m_list.begin()); iter != m_list.end();)
|
||||
{
|
||||
Item& item (*iter++);
|
||||
AtExitHook* const hook (item.hook ());
|
||||
hook->onExit ();
|
||||
}
|
||||
|
||||
// Now do the leak checking
|
||||
//
|
||||
LeakCheckedBase::checkForLeaks ();
|
||||
}
|
||||
|
||||
struct StaticDestructor
|
||||
{
|
||||
~StaticDestructor ()
|
||||
{
|
||||
Manager::get().doStaticDetruction();
|
||||
}
|
||||
};
|
||||
|
||||
typedef CriticalSection MutexType;
|
||||
typedef MutexType::ScopedLockType ScopedLockType;
|
||||
|
||||
static StaticDestructor s_staticDestructor;
|
||||
|
||||
MutexType m_mutex;
|
||||
List <Item> m_list;
|
||||
bool m_didStaticDestruction;
|
||||
};
|
||||
|
||||
// This is an object with static storage duration.
|
||||
// When it gets destroyed, we will call into the Manager to
|
||||
// call all of the AtExitHook items in the list.
|
||||
//
|
||||
AtExitHook::Manager::StaticDestructor AtExitHook::Manager::s_staticDestructor;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
AtExitHook::Item::Item (AtExitHook* hook)
|
||||
: m_hook (hook)
|
||||
{
|
||||
}
|
||||
|
||||
AtExitHook* AtExitHook::Item::hook ()
|
||||
{
|
||||
return m_hook;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
AtExitHook::AtExitHook ()
|
||||
: m_item (this)
|
||||
{
|
||||
#if BEAST_IOS
|
||||
// Patrick Dehne:
|
||||
// AtExitHook::Manager::insert crashes on iOS
|
||||
// if the storage is not accessed before it is used.
|
||||
//
|
||||
// VFALCO TODO Figure out why and fix it cleanly if needed.
|
||||
//
|
||||
char* hack = AtExitHook::Manager::s_list.s_storage;
|
||||
#endif
|
||||
|
||||
Manager::get().insert (m_item);
|
||||
}
|
||||
|
||||
AtExitHook::~AtExitHook ()
|
||||
{
|
||||
Manager::get().erase (m_item);
|
||||
}
|
||||
88
modules/beast_core/time/AtExitHook.h
Normal file
88
modules/beast_core/time/AtExitHook.h
Normal file
@@ -0,0 +1,88 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, 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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_CORE_ATEXITHOOK_H_INCLUDED
|
||||
#define BEAST_CORE_ATEXITHOOK_H_INCLUDED
|
||||
|
||||
/** Hook for performing activity on program exit.
|
||||
|
||||
These hooks execute when objects with static storage duration are
|
||||
destroyed. The hooks are called in the reverse order that they were
|
||||
created.
|
||||
|
||||
To use, derive your class from AtExitHook and implement onExit.
|
||||
Alternatively, add AtExitMemberHook as a data member of your class and
|
||||
then provide your own onExit function with this signature:
|
||||
|
||||
@code
|
||||
|
||||
void onExit ()
|
||||
|
||||
@endcode
|
||||
|
||||
@see AtExitMemberHook
|
||||
*/
|
||||
/** @{ */
|
||||
class AtExitHook
|
||||
{
|
||||
protected:
|
||||
AtExitHook ();
|
||||
virtual ~AtExitHook ();
|
||||
|
||||
protected:
|
||||
/** Called at program exit. */
|
||||
virtual void onExit () = 0;
|
||||
|
||||
private:
|
||||
class Manager;
|
||||
|
||||
class Item : public List <Item>::Node
|
||||
{
|
||||
public:
|
||||
explicit Item (AtExitHook* hook);
|
||||
AtExitHook* hook ();
|
||||
|
||||
private:
|
||||
AtExitHook* m_hook;
|
||||
};
|
||||
|
||||
Item m_item;
|
||||
};
|
||||
|
||||
/** Helper for utilizing the AtExitHook as a data member.
|
||||
*/
|
||||
template <class Object>
|
||||
class AtExitMemberHook : public AtExitHook
|
||||
{
|
||||
public:
|
||||
explicit AtExitMemberHook (Object* owner) : m_owner (owner)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
void onExit ()
|
||||
{
|
||||
m_owner->onExit ();
|
||||
}
|
||||
|
||||
Object* m_owner;
|
||||
};
|
||||
/** @} */
|
||||
|
||||
#endif
|
||||
@@ -1,74 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, 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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
class PerformedAtExit::ExitHook
|
||||
{
|
||||
public:
|
||||
typedef Static::Storage <LockFreeStack <PerformedAtExit>, PerformedAtExit> StackType;
|
||||
|
||||
private:
|
||||
~ExitHook ()
|
||||
{
|
||||
// Call all PerformedAtExit objects
|
||||
//
|
||||
PerformedAtExit* object = s_list->pop_front ();
|
||||
|
||||
while (object != nullptr)
|
||||
{
|
||||
object->performAtExit ();
|
||||
|
||||
object = s_list->pop_front ();
|
||||
}
|
||||
|
||||
// Now do the leak checking
|
||||
//
|
||||
LeakCheckedBase::checkForLeaks ();
|
||||
}
|
||||
|
||||
public:
|
||||
static void push_front (PerformedAtExit* object)
|
||||
{
|
||||
s_list->push_front (object);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class PerformedAtExit;
|
||||
|
||||
static StackType s_list;
|
||||
|
||||
static ExitHook s_performer;
|
||||
};
|
||||
|
||||
PerformedAtExit::ExitHook PerformedAtExit::ExitHook::s_performer;
|
||||
PerformedAtExit::ExitHook::StackType PerformedAtExit::ExitHook::s_list;
|
||||
|
||||
PerformedAtExit::PerformedAtExit ()
|
||||
{
|
||||
#if BEAST_IOS
|
||||
// Patrick Dehne:
|
||||
// PerformedAtExit::ExitHook::push_front crashes on iOS
|
||||
// if s_storage is not accessed before used
|
||||
//
|
||||
// VFALCO TODO Figure out why and fix it cleanly if needed.
|
||||
//
|
||||
char* hack = PerformedAtExit::ExitHook::s_list.s_storage;
|
||||
#endif
|
||||
|
||||
ExitHook::push_front (this);
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, 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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_PERFORMEDATEXIT_H_INCLUDED
|
||||
#define BEAST_PERFORMEDATEXIT_H_INCLUDED
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
Perform an action at program exit
|
||||
|
||||
To use, derive your class from PerformedAtExit, and override `performAtExit()`.
|
||||
The call will be made during the destruction of objects with static storage
|
||||
duration, before LeakChecked performs its diagnostics.
|
||||
|
||||
@ingroup beast_core
|
||||
*/
|
||||
// VFALCO TODO Make the linked list element a private type and use composition
|
||||
// instead of inheritance, so that PerformedAtExit doesn't expose
|
||||
// lock free stack node interfaces.
|
||||
//
|
||||
class BEAST_API PerformedAtExit : public LockFreeStack <PerformedAtExit>::Node
|
||||
{
|
||||
public:
|
||||
class ExitHook;
|
||||
|
||||
protected:
|
||||
PerformedAtExit ();
|
||||
virtual ~PerformedAtExit () { }
|
||||
|
||||
protected:
|
||||
/** Called at program exit.
|
||||
*/
|
||||
virtual void performAtExit () = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user