life_maintainer.cpp

Go to the documentation of this file.
00001 #ifndef LIFE_MAINTAINER_IMPLEMENTATION_FILE
00002 #define LIFE_MAINTAINER_IMPLEMENTATION_FILE
00003 
00004 /*****************************************************************************\
00005 *                                                                             *
00006 *  Name   : life_maintainer                                                   *
00007 *  Author : Chris Koeritz                                                     *
00008 *                                                                             *
00009 *******************************************************************************
00010 * Copyright (c) 1996-$now By Author.  This program is free software; you can  *
00011 * redistribute it and/or modify it under the terms of the GNU General Public  *
00012 * License as published by the Free Software Foundation; either version 2 of   *
00013 * the License or (at your option) any later version.  This is online at:      *
00014 *     http://www.fsf.org/copyleft/gpl.html                                    *
00015 * Please send any updates to: fred@gruntose.com                               *
00016 \*****************************************************************************/
00017 
00018 #include "living_item.h"
00019 #include "life_maintainer.h"
00020 
00021 #include <basis/auto_synch.h>
00022 #include <basis/mutex.h>
00023 #include <data_struct/byte_hasher.h>
00024 #include <data_struct/int_hash.cpp>
00025 #include <data_struct/unique_id.h>
00026 #include <mechanisms/heartbeat.h>
00027 
00028 using namespace nodes;
00029 
00030 const int MAX_LFMT_BITS = 10;
00031   // the maximum bits used for hash values.
00032 
00033 #undef AUTO_LOCK
00034 #define AUTO_LOCK auto_synchronizer l(*_lock)
00035 
00036 #undef LOG
00037 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger(), s)
00038 
00040 
00041 class living_item_table : public int_hash<living_item>
00042 {
00043 public:
00044   living_item_table() : int_hash<living_item>(MAX_LFMT_BITS) {}
00045 };
00046 
00048 
00049 life_maintainer::life_maintainer()
00050 : _items(new living_item_table),
00051   _lock(new mutex)
00052 {}
00053 
00054 life_maintainer::~life_maintainer()
00055 {
00056   WHACK(_items);
00057   WHACK(_lock);
00058 }
00059 
00060 int_set life_maintainer::valid_ids() const
00061 {
00062   AUTO_LOCK;
00063   return _items->ids();
00064 }
00065 
00066 bool life_maintainer::add(living_item *to_add)
00067 {
00068   AUTO_LOCK;
00069   _items->add(to_add->id().raw_id(), to_add);
00070   return true;
00071 }
00072 
00073 bool life_maintainer::zap(const unique_int &uid)
00074 {
00075   living_item *item = acquire(uid);
00076   if (!item) return false;
00077   item->lock();
00078     // we want to ensure that we get this node's attention.  since it's not in
00079     // the list any longer, nobody should be able to touch it except for those
00080     // who are already waiting on it.  once we've been given the lock, we've
00081     // ensured no one else is waiting for it anymore.
00082   item->unlock();
00083     // release the lock again; nobody else should be able to mess with it
00084     // any longer.
00085   item->shut_down_safely();  // this guy is toast; remove its parts.
00086   WHACK(item);
00087   return true;
00088 }
00089 
00090 heartbeat life_maintainer::get_liveness(const unique_int &uid)
00091 {
00092   heartbeat to_return;
00093   living_item *item = locking_find(uid);
00094   if (!item) return to_return;
00095   to_return = item->liveness();
00096   unlock_find(item);
00097   return to_return;
00098 }
00099 
00100 bool life_maintainer::set_liveness(const unique_int &uid,
00101     const heartbeat &new_beat)
00102 {
00103   living_item *item = locking_find(uid);
00104   if (!item) return false;
00105   item->liveness(new_beat);
00106   unlock_find(item);
00107   return true;
00108 }
00109 
00110 bool life_maintainer::kabump(const unique_int &id)
00111 {
00112   living_item *item = locking_find(id);
00113   if (!item) return false;
00114   item->liveness().kabump();
00115   unlock_find(item);
00116   return true;
00117 }
00118 
00119 bool life_maintainer::made_request(const unique_int &id)
00120 {
00121   living_item *item = locking_find(id);
00122   if (!item) return false;
00123   item->liveness().made_request();
00124   unlock_find(item);
00125   return true;
00126 }
00127 
00128 void life_maintainer::apply(apply_function *to_apply, void *datalink)
00129 {
00130   FUNCDEF("apply");
00131   int_set ids;
00132   {
00133     AUTO_LOCK;
00134     _items->ids(ids);
00135   }
00136   // this algorithm goes through the list without keeping it locked.
00137   for (int i = 0; i < ids.length(); i++) {
00138     living_item *iti = locking_find(ids[i]);
00139     if (!iti) continue;  // got nothing.
00140     to_apply(*iti, datalink);
00141     unlock_find(iti);
00142   }
00143 }
00144 
00145 living_item *life_maintainer::locking_find(const unique_int &uid)
00146 {
00147   _lock->lock();
00148   living_item *to_return = _items->find(uid.raw_id());
00149   if (!to_return) {
00150     _lock->unlock();
00151     return NIL;
00152   }
00153   // we transition now to downgrading our lock, but we must first acquire the
00154   // lock on the item.  we will wait until it's released it, which is hopefully
00155   // not going to take long.
00156   to_return->lock();
00157   _lock->unlock();
00158   return to_return;
00159 }
00160 
00161 void life_maintainer::unlock_find(living_item *to_close)
00162 {
00163   if (!to_close) return;
00164   to_close->unlock();
00165 }
00166 
00167 living_item *life_maintainer::acquire(const unique_int &uid)
00168 {
00169   AUTO_LOCK;
00170   return _items->acquire(uid.raw_id());
00171 }
00172 
00173 
00174 #endif //LIFE_MAINTAINER_IMPLEMENTATION_FILE
00175 

Generated on Thu Nov 20 04:28:47 2008 for HOOPLE Libraries by  doxygen 1.5.1