30 using namespace basis;
43 #define LOG(a) CLASS_EMERGENCY_LOG(program_wide_logger::get(), a)
60 class 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!"));
94 class 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",
123 class route_map :
public amorph<tagged_mail_stop>
126 tagged_mail_stop *find(
const unique_int &
id) {
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)) {
149 class letter_morph :
public amorph<letter> {};
153 post_office::post_office()
155 _routes(new route_map),
166 WHACK(_next_cleaning);
176 if (_routes->elements())
177 to_fill +=
astring(
"Mail Delivery Routes:") + parser_bits::platform_eol_to_chars();
179 for (
int i = 0; i < _routes->elements(); i++) {
180 const tagged_mail_stop *tag = _routes->get(i);
182 temp =
astring(astring::SPRINTF,
"%d ", tag->_id.raw_id());
184 current_line += parser_bits::platform_eol_to_chars();
185 to_fill += current_line;
186 current_line.
reset();
188 current_line += temp;
191 if (!!current_line) to_fill += current_line;
199 output += parser_bits::platform_eol_to_chars();
200 output +=
astring(
"Mailbox Contents at ") + time_stamp::notarize(
true)
201 + parser_bits::platform_eol_to_chars() + parser_bits::platform_eol_to_chars();
203 _post->
show(box_state);
204 if (box_state.
t()) output += box_state;
206 output +=
astring(
"No items are awaiting delivery.")
207 + parser_bits::platform_eol_to_chars();
212 #ifdef DEBUG_POST_OFFICE
214 LOG(
astring(astring::SPRINTF,
"mailbox drop for %d: ",
id)
218 #ifdef DEBUG_POST_OFFICE
227 #ifdef DEBUG_POST_OFFICE
230 bool to_return = _post->
pick_up(
id, package);
231 #ifdef DEBUG_POST_OFFICE
233 LOG(
astring(astring::SPRINTF,
"mailbox grab for %d: ",
id)
242 get_route_list(route_set);
243 return route_set.
member(
id.raw_id());
246 void 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());
265 void 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.
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.
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.
Represents a point in time relative to the operating system startup time.
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()