// --------------------------------------------------------------------------- // - Assistant.cpp - // - afnix:pim module - assistant class implementation - // --------------------------------------------------------------------------- // - This program is free software; you can redistribute it and/or modify - // - it provided that this copyright notice is kept intact. - // - - // - 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. In no event shall - // - the copyright holder be liable for any direct, indirect, incidental or - // - special damages arising in any way out of the use of this software. - // --------------------------------------------------------------------------- // - copyright (c) 1999-2007 amaury darsch - // --------------------------------------------------------------------------- #include "Integer.hpp" #include "Boolean.hpp" #include "Runnable.hpp" #include "Assistant.hpp" #include "QuarkZone.hpp" #include "Exception.hpp" namespace afnix { // ------------------------------------------------------------------------- // - class section - // ------------------------------------------------------------------------- // create a default assistant Assistant::Assistant (void) { reset (); } // create a assistant by name Assistant::Assistant (const String& name) { d_name = name; d_info = "unknown assistant info"; reset (); } // create a assistant by name and info Assistant::Assistant (const String& name, const String& info) { d_name = name; d_info = info; reset (); } // return the assistant class name String Assistant::repr (void) const { return "Assistant"; } // make this assistant shared void Assistant::mksho (void) { if (p_shared != nilp) return; Object::mksho (); d_appt.mksho (); } // reset this assistant void Assistant::reset (void) { wrlock (); d_aidx = 0; try { // get the number of appointers long len = lenappt (); // iterate in the appointer for (long i = 0; i < len; i++) { Appointer* appt = getappt (i); if (appt == nilp) continue; appt->reset (); } unlock (); } catch (...) { unlock (); throw; } } // return the assistant name String Assistant::getname (void) const { rdlock (); String result = d_name; unlock (); return result; } // return the assistant info String Assistant::getinfo (void) const { rdlock (); String result = d_info; unlock (); return result; } // return the number of appointers long Assistant::lenappt (void) const { rdlock (); try { long result = d_appt.length (); unlock (); return result; } catch (...) { unlock (); throw; } } // add an appointer to this assistant void Assistant::addappt (Appointer* appt) { wrlock (); try { d_appt.append (appt); unlock (); } catch (...) { unlock (); throw; } } // get an appointer by index Appointer* Assistant::getappt (const long index) const { rdlock (); try { Object* obj = d_appt.get (index); Appointer* result = dynamic_cast (obj); if ((obj != nilp) && (result == nilp)) { throw Exception ("internal-error", "non appointer object found", Object::repr (obj)); } unlock (); return result; } catch (...) { unlock (); throw; } } // get the average appointer time t_long Assistant::getaatm (void) const { rdlock (); try { // initialize result t_long result = 0LL; // get the number of appointers long len = lenappt (); if (len != 0) { // iterate in the appointer for (long i = 0; i < len; i++) { Appointer* appt = getappt (i); if (appt == nilp) continue; result += (appt->gettime ()); } // compute average and return result /= (t_long) len; } unlock (); return result; } catch (...) { unlock (); throw; } } // get the appointer minimum time t_long Assistant::getamtm (void) const { rdlock (); try { // get the appointer Appointer* appt = getappt (d_aidx); // get result from appointer t_long result = (appt == nilp) ? 0LL : appt->getamtm (); unlock (); return result; } catch (...) { unlock (); throw; } } // get the appointer minimum time by time t_long Assistant::getamtm (const t_long mrtm) const { rdlock (); try { // get the appointer Appointer* appt = getappt (d_aidx); // get result from appointer t_long result = (appt == nilp) ? 0LL : appt->getamtm (mrtm); unlock (); return result; } catch (...) { unlock (); throw; } } // get the total number of slots long Assistant::getsnum (void) const { rdlock (); try { // initialize result long result = 0; // get the number of appointers long len = lenappt (); // iterate in the appointer for (long i = 0; i < len; i++) { Appointer* appt = getappt (i); if (appt == nilp) continue; result += (appt->getsnum ()); } unlock (); return result; } catch (...) { unlock (); throw; } } // get the next available slot by duration Slot Assistant::getslot (const t_long dlen) { wrlock (); try { // get the appointer Appointer* appt = getappt (d_aidx); // get the slot Slot result = appt->getslot (dlen); result.setsidx (d_aidx); // update next index d_aidx = (d_aidx + 1) % d_appt.length (); // here is the next slot unlock (); return result; } catch (...) { unlock (); throw; } } // get the next available slot by time and duration Slot Assistant::getslot (const t_long time, const t_long dlen) { wrlock (); try { // get the appointer Appointer* appt = getappt (d_aidx); // get the slot Slot result = appt->getslot (time, dlen); result.setsidx (d_aidx); // update next index d_aidx = (d_aidx + 1) % d_appt.length (); // here is the next slot unlock (); return result; } catch (...) { unlock (); throw; } } // pushback a slot in the slot pool void Assistant::pushback (const Slot& slot) { wrlock (); try { // get the appointer index long aidx = slot.getsidx (); if ((aidx < 0) || (aidx >= d_appt.length ())) { unlock (); return; } // get the appointer Appointer* appt = getappt (aidx); // pushback the slot appt->pushback (slot); unlock (); } catch (...) { unlock (); throw; } } // ------------------------------------------------------------------------- // - object section - // ------------------------------------------------------------------------- // the quark zone static const long QUARK_ZONE_LENGTH = 11; static QuarkZone zone (QUARK_ZONE_LENGTH); // the object supported quarks static const long QUARK_RESET = zone.intern ("reset"); static const long QUARK_PUSHB = zone.intern ("pushback"); static const long QUARK_GETNAME = zone.intern ("get-name"); static const long QUARK_GETINFO = zone.intern ("get-info"); static const long QUARK_GETSLOT = zone.intern ("get-slot"); static const long QUARK_ADDAPPT = zone.intern ("add-appointer"); static const long QUARK_GETAPPT = zone.intern ("get-appointer"); static const long QUARK_GETSNUM = zone.intern ("get-slot-number"); static const long QUARK_GETAATM = zone.intern ("get-appointer-time"); static const long QUARK_GETAMTM = zone.intern ("get-appointer-minimum-time"); static const long QUARK_LENAPPT = zone.intern ("length-appointer"); // create a new object in a generic way Object* Assistant::mknew (Vector* argv) { long argc = (argv == nilp) ? 0 : argv->length (); // create a default assistant object if (argc == 0) return new Assistant; // check for 1 argument if (argc == 1) { String name = argv->getstring (0); return new Assistant (name); } // check for 2 arguments if (argc == 2) { String name = argv->getstring (0); String info = argv->getstring (1); return new Assistant (name, info); } throw Exception ("argument-error", "too many argument with assistant constructor"); } // return true if the given quark is defined bool Assistant::isquark (const long quark, const bool hflg) const { rdlock (); if (zone.exists (quark) == true) { unlock (); return true; } bool result = hflg ? Object::isquark (quark, hflg) : false; unlock (); return result; } // apply this object with a set of arguments and a quark Object* Assistant::apply (Runnable* robj, Nameset* nset, const long quark, Vector* argv) { // get the number of arguments long argc = (argv == nilp) ? 0 : argv->length (); // check for argument if (argc == 0) { if (quark == QUARK_GETNAME) return new String (getname ()); if (quark == QUARK_GETINFO) return new String (getinfo ()); if (quark == QUARK_LENAPPT) return new Integer (lenappt ()); if (quark == QUARK_GETAATM) return new Integer (getaatm ()); if (quark == QUARK_GETAMTM) return new Integer (getamtm ()); if (quark == QUARK_GETSNUM) return new Integer (getsnum ()); if (quark == QUARK_RESET) { reset (); return nilp; } } // check for 1 argument if (argc == 1) { if (quark == QUARK_GETSLOT) { t_long dlen = argv->getint (0); return new Slot (getslot (dlen)); } if (quark == QUARK_GETAMTM) { t_long mrtm = argv->getint (0); return new Integer (getamtm (mrtm)); } if (quark == QUARK_ADDAPPT) { Object* obj = argv->get (0); Appointer* appt = dynamic_cast (obj); if (appt == nilp) { throw Exception ("type-error", "invalid object with add-appointer", Object::repr (obj)); } addappt (appt); return nilp; } if (quark == QUARK_GETAPPT) { long index = argv->getint (0); rdlock (); try { Appointer* result = getappt (index); robj->post (result); unlock (); return result; } catch (...) { unlock (); throw; } } if (quark == QUARK_PUSHB) { Object* obj = argv->get (0); Slot* slot = dynamic_cast (obj); if (slot == nilp) { throw Exception ("type-error", "invalid object with pushback", Object::repr (obj)); } pushback (*slot); return nilp; } } // check for 2 arguments if (argc == 2) { if (quark == QUARK_GETSLOT) { t_long time = argv->getint (0); t_long dlen = argv->getint (1); return new Slot (getslot (time, dlen)); } } // call the object method return Object::apply (robj, nset, quark, argv); } }