lumiera_/src/backend/resourcecollector.c

192 lines
5.3 KiB
C

/*
ResourceCollector - manage/collect resources when they get short
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
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 (at your option) 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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
/** @file resourcecollector.c
** Implementation of a global service to manage scarce system resources
** @todo this was a plan from 2008 and never got beyond an initial concept stage
*/
#include "include/logging.h"
#include "lib/llist.h"
#include "lib/mutex.h"
#include "lib/safeclib.h"
#include "backend/resourcecollector.h"
#include <unistd.h>
llist lumiera_resourcecollector_registry[LUMIERA_RESOURCE_END];
lumiera_mutex lumiera_resourcecollector_lock;
struct lumiera_resourcehandler_struct
{
llist node;
lumiera_resource_handler_fn handler;
void* data;
};
void
lumiera_resourcecollector_init (void)
{
//NOBUG_INIT_FLAG (resourcecollector);
TRACE (resourcecollector_dbg);
for (int i = 0; i < LUMIERA_RESOURCE_END; ++i)
llist_init (&lumiera_resourcecollector_registry[i]);
lumiera_mutex_init (&lumiera_resourcecollector_lock, "resourcecollector", &NOBUG_FLAG(mutex_dbg), NOBUG_CONTEXT);
}
void
lumiera_resourcecollector_destroy (void)
{
TRACE (resourcecollector_dbg);
for (int i = 0; i < LUMIERA_RESOURCE_END; ++i)
LLIST_WHILE_HEAD (&lumiera_resourcecollector_registry[i], head)
lumiera_resourcehandler_unregister ((LumieraResourcehandler)head);
lumiera_mutex_destroy (&lumiera_resourcecollector_lock, &NOBUG_FLAG(mutex_dbg), NOBUG_CONTEXT);
}
int
lumiera_resourcecollector_run (enum lumiera_resource which, enum lumiera_resource_try* iteration, void* context)
{
TRACE (resourcecollector_dbg);
LUMIERA_MUTEX_SECTION (mutex_sync, &lumiera_resourcecollector_lock)
{
for (enum lumiera_resource_try progress = LUMIERA_RESOURCE_NONE; progress < *iteration; ++*iteration)
{
if (*iteration < LUMIERA_RESOURCE_PANIC)
{
LLIST_FOREACH (&lumiera_resourcecollector_registry[which], node)
{
LumieraResourcehandler self = (LumieraResourcehandler) node;
progress = self->handler (*iteration, self->data, context);
if (*iteration < LUMIERA_RESOURCE_ALL)
{
if (progress >= *iteration)
{
llist_insert_next (node, &lumiera_resourcecollector_registry[which]);
break;
}
}
}
}
else
{
ALERT (resourcecollector, "PANIC, Not enough resources %d", which);
for (int i = 0; i < LUMIERA_RESOURCE_END; ++i)
LLIST_FOREACH (&lumiera_resourcecollector_registry[i], node)
{
LumieraResourcehandler self = (LumieraResourcehandler) node;
progress = self->handler (LUMIERA_RESOURCE_PANIC, self->data, NULL);
}
_exit (EXIT_FAILURE);
}
}
}
return 1;
}
LumieraResourcehandler
lumiera_resourcecollector_register_handler (enum lumiera_resource resource, lumiera_resource_handler_fn handler, void* data)
{
TRACE (resourcecollector_dbg);
LumieraResourcehandler self = lumiera_malloc (sizeof (*self));
llist_init (&self->node);
self->handler = handler;
self->data = data;
LUMIERA_MUTEX_SECTION (mutex_sync, &lumiera_resourcecollector_lock)
{
llist_insert_tail (&lumiera_resourcecollector_registry[resource], &self->node);
}
return self;
}
void
lumiera_resourcehandler_unregister (LumieraResourcehandler self)
{
TRACE (resourcecollector_dbg);
if (self)
{
LUMIERA_MUTEX_SECTION (mutex_sync, &lumiera_resourcecollector_lock)
{
llist_unlink (&self->node);
self->handler (LUMIERA_RESOURCE_UNREGISTER, self->data, NULL);
}
lumiera_free (self);
}
}
LumieraResourcehandler
lumiera_resourcecollector_handler_find (enum lumiera_resource resource, lumiera_resource_handler_fn handler, void* data)
{
TRACE (resourcecollector_dbg);
LumieraResourcehandler self = NULL;
LUMIERA_MUTEX_SECTION (mutex_sync, &lumiera_resourcecollector_lock)
{
LLIST_FOREACH (&lumiera_resourcecollector_registry[resource], node)
{
self = (LumieraResourcehandler) node;
if (((LumieraResourcehandler)node)->handler == handler && ((LumieraResourcehandler)node)->data == data)
{
self = (LumieraResourcehandler)node;
break;
}
}
}
return self;
}
/*
// Local Variables:
// mode: C
// c-file-style: "gnu"
// indent-tabs-mode: nil
// End:
*/