43#define LOG(a) CLASS_EMERGENCY_LOG(program_wide_logger::get(), a)
60class postal_carrier :
public ethread
71 void perform_activity(
void *) {
75 finished = _parent.deliver_mail_on_route(_route, *
this);
77 LOG(
astring(
"caught exception during mail delivery!"));
94class postal_cache :
public mailbox {};
107 : _route(route), _thread_id(thread_id), _id(id) {}
115 virtual astring text_form()
const {
116 return a_sprintf(
"%s: id=%d, addr=%08lx, thr_id=%d",
123class route_map :
public amorph<tagged_mail_stop>
127 for (
int i = 0; i <
elements(); i++) {
128 tagged_mail_stop *curr =
borrow(i);
129 if (curr && (curr->_id ==
id))
return curr;
135 for (
int i = 0; i <
elements(); i++) {
136 tagged_mail_stop *curr =
borrow(i);
137 if (curr && (curr->_id ==
id)) {
149class letter_morph :
public amorph<letter> {};
155 _routes(new route_map),
166 WHACK(_next_cleaning);
176 if (_routes->elements())
179 for (
int i = 0; i < _routes->elements(); i++) {
180 const tagged_mail_stop *tag = _routes->get(i);
183 if (current_line.
length() + temp.length() >= 80) {
185 to_fill += current_line;
186 current_line.
reset();
188 current_line += temp;
191 if (!!current_line) to_fill += current_line;
203 _post->
show(box_state);
204 if (box_state.
t()) output += box_state;
206 output +=
astring(
"No items are awaiting delivery.")
212#ifdef DEBUG_POST_OFFICE
218#ifdef DEBUG_POST_OFFICE
227#ifdef DEBUG_POST_OFFICE
230 bool to_return = _post->
pick_up(
id, package);
231#ifdef DEBUG_POST_OFFICE
242 get_route_list(route_set);
243 return route_set.
member(
id.raw_id());
246void post_office::get_route_list(
int_set &route_set)
253 if (!_routes->elements()) {
258 for (
int i = 0; i < _routes->elements(); i++) {
259 const tagged_mail_stop *tag = _routes->get(i);
261 route_set.
add(tag->_id.raw_id());
265void post_office::clean_package_list(post_office &
formal(post),
266 letter_morph &to_clean)
272 while (to_clean.elements()) {
273 letter *
package = to_clean.acquire(0);
276 LOG(
"saw empty package in list to clean!");
286 FUNCDEF(
"deliver_mail_on_route");
289#ifdef DEBUG_POST_OFFICE
295 letter_morph items_for_route;
303 if (!_post->
pick_up(route, package)) {
308 items_for_route.append(package);
311 if (!items_for_route.elements())
return true;
314 tagged_mail_stop *real_route = _routes->find(route);
318 clean_package_list(*
this, items_for_route);
323 for (
int t = 0; t < items_for_route.elements(); t++) {
328 letter *
package = items_for_route.acquire(t);
331 real_route->_route->invoke_callback(
pack);
342 bool cleaning_time =
time_stamp() > *_next_cleaning;
349#ifdef DEBUG_POST_OFFICE
350 int duration = int(exit.
value() - enter.
value());
362 tagged_mail_stop *found = _routes->find(
id);
363 if (found)
return false;
365 postal_carrier *po =
new postal_carrier(*
this,
id);
368 tagged_mail_stop *new_stop =
new tagged_mail_stop(
id, &carrier_path,
370 _routes->append(new_stop);
381 tagged_mail_stop *tag = _routes->find(
id);
382 if (!tag)
return false;
a_sprintf is a specialization of astring that provides printf style support.
void reset(int number=0, const contents *initial_contents=NULL_POINTER)
Resizes this array and sets the contents from an array of contents.
Provides a dynamically resizable ASCII character string.
bool t() const
t() is a shortcut for the string being "true", as in non-empty.
void reset()
clears out the contents string.
int length() const
Returns the current length of the string.
auto_synchronizer simplifies concurrent code by automatically unlocking.
Defines the base class for all string processing objects in hoople.
virtual base_string & assign(const base_string &s)=0
Sets the contents of this string to "s".
A base class for objects that can provide a synopsis of their current state.
Provides a platform-independent object for adding threads to a program.
ethread()
creates a single-shot thread object.
void reschedule(int delay=0)
causes a periodic thread to activate after "delay" milliseconds from now.
bool should_stop() const
reports whether the thread should stop right now.
A virtual base class for pieces of "mail". Used by the mailbox object.
virtual void text_form(basis::base_string &fill) const =0
derived letters must print a status blurb describing their contents.
Base class for routes on which letters are automatically delivered.
Implements a thread safe "mail" delivery system.
void drop_off(const structures::unique_int &id, letter *package)
drops a "package" in the mailbox for "id".
bool pick_up(const structures::unique_int &id, letter *&package)
returns true if the mailbox for "id" had a "package" to be delivered.
void clean_up()
removes any empty mailboxes from our list.
void show(basis::astring &to_fill)
provides a picture of what's waiting in the mailbox.
Manages a collection of mailboxes and implements delivery routes for mail.
bool pick_up(const structures::unique_int &id, letter *&package)
retrieves a "package" intended for the "id" if one exists.
bool register_route(const structures::unique_int &id, mail_stop &carrier_path)
registers a route "carrier_path" for mail deliveries to the "id".
bool unregister_route(const structures::unique_int &id)
removes a route for the "id".
virtual ~post_office()
stop_serving must be invoked prior to this destructor.
void show_routes(basis::astring &to_fill)
writes a listing of the current routes into "to_fill".
void show_mail(basis::astring &to_fill)
prints a snapshot of all currently pending letters into "to_fill".
void stop_serving()
gets the mailbox to stop delivering items prior to a shutdown.
void drop_off(const structures::unique_int &id, letter *package)
sends a "package" on its way to the "id" via the registered route.
bool route_listed(const structures::unique_int &id)
returns true if there is a route listed for the "id".
bool deliver_mail_on_route(const structures::unique_int &route, ethread &carrier)
for internal use only–delivers the letters to known routes.
Manages a collection of threads.
bool zap_thread(const structures::unique_int &to_whack)
removes the thread with the id "to_whack".
structures::unique_int add_thread(ethread *to_add, bool start_it, void *parm)
adds a thread to be managed by the thread_cabinet.
void stop_all()
makes all of the threads quit.
int elements() const
the maximum number of elements currently allowed in this amorph.
basis::outcome zap(int start, int end)
Removes a range of indices from the amorph.
int find(const tagged_mail_stop *to_locate, basis::outcome &o)
Searches the amorph for the contents specified.
tagged_mail_stop * borrow(int field)
Returns a pointer to the information at the index "field".
A simple object that wraps a templated set of ints.
bool member(const contents &to_test) const
Returns true if the item "to_test" is a member of this set.
bool add(const contents &to_add)
Adds a new element "to_add" to the set.
uniquifier raw_id() const
Returns the held identifier in its native form.
A unique identifier based on integers.
static const char * platform_eol_to_chars()
provides the characters that make up this platform's line ending.
Represents a point in time relative to the operating system startup time.
static basis::astring notarize(bool add_space=true)
a useful method for getting a textual version of the time "right now".
void reset()
sets the stamp time back to now.
time_representation value() const
returns the time_stamp in terms of the lower level type.
#define formal(parameter)
This macro just eats what it's passed; it marks unused formal parameters.
#define NULL_POINTER
The value representing a pointer to nothing.
#define DEFINE_CLASS_NAME(objname)
Defines the name of a class by providing a couple standard methods.
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
The guards collection helps in testing preconditions and reporting errors.
void WHACK(contents *&ptr)
deletion with clearing of the pointer.
const int SECOND_ms
Number of milliseconds in a second.
A logger that sends to the console screen using the standard output device.
const int CLEANING_INTERVAL
const int SNOOZE_TIME_FOR_POSTMAN
const int DELIVERIES_ALLOWED
A dynamic container class that holds any kind of object via pointers.
void pack(basis::byte_array &packed_form, const set< contents > &to_pack)
provides a way to pack any set that stores packable objects.
#define static_class_name()