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
1.5.1